├── .editorconfig
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── stepstone
│ │ └── sonar
│ │ └── plugin
│ │ └── coldfusion
│ │ ├── ColdFusion.java
│ │ ├── ColdFusionPlugin.java
│ │ ├── ColdFusionSensor.java
│ │ ├── cflint
│ │ ├── CFLintAnalysisResultImporter.java
│ │ ├── CFLintAnalyzer.java
│ │ ├── CFLintConfigExporter.java
│ │ ├── CFLintExtractor.java
│ │ └── xml
│ │ │ ├── CountsAttributes.java
│ │ │ ├── IssueAttributes.java
│ │ │ ├── LocationAttributes.java
│ │ │ └── TagAttribute.java
│ │ ├── errors
│ │ └── ColdFusionPluginException.java
│ │ ├── package-info.java
│ │ ├── profile
│ │ ├── ColdFusionProfileExporter.java
│ │ └── ColdFusionSonarWayProfile.java
│ │ └── rules
│ │ └── ColdFusionSonarRulesDefinition.java
└── resources
│ └── com
│ └── stepstone
│ └── sonar
│ └── plugin
│ └── coldfusion
│ ├── profile.json
│ └── rules.xml
└── test
├── java
└── com
│ └── stepstone
│ └── sonar
│ └── plugin
│ └── coldfusion
│ ├── ColdfusionPluginTest.java
│ ├── ColdfusionSensorTest.java
│ └── OSValidator.java
└── resources
├── EpisodeClaim.cfc
├── testmetrics1.cfm
└── testmetrics2.cfm
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | insert_final_newline = true
6 | indent_style = space
7 | indent_size = 4
8 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3 |
4 | name: CI
5 |
6 | on:
7 | push:
8 | branches: [ master, sonar-9, sonar-9.0 ]
9 | pull_request:
10 | types: [opened, synchronize, reopened]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 | with:
19 | fetch-depth: 0
20 | - name: Set up JDK 11
21 | uses: actions/setup-java@v2
22 | with:
23 | distribution: 'adopt'
24 | java-version: '11'
25 | - name: Cache SonarCloud packages
26 | uses: actions/cache@v1
27 | with:
28 | path: ~/.sonar/cache
29 | key: ${{ runner.os }}-sonar
30 | restore-keys: ${{ runner.os }}-sonar
31 | - name: Cache Maven packages
32 | uses: actions/cache@v1
33 | with:
34 | path: ~/.m2
35 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
36 | restore-keys: ${{ runner.os }}-m2
37 | - name: Build and analyze
38 | env:
39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
41 | run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Psonar
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Maven
2 | target/
3 | *.versionsBackup
4 |
5 | # IntelliJ IDEA
6 | *.iws
7 | *.iml
8 | *.ipr
9 | .idea/
10 |
11 | # Eclipse
12 | .classpath
13 | .project
14 | .settings
15 |
16 | # ---- Windows
17 | # Windows image file caches
18 | Thumbs.db
19 | # Folder config file
20 | Desktop.ini
21 |
22 | # SonarQube
23 | .sonar/
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SonarQube ColdFusion Plugin
2 | [](https://github.com/stepstone-tech/sonar-coldfusion/actions/workflows/ci.yml) [](https://sonarcloud.io/dashboard?id=stepstone-tech_sonar-coldfusion) [](https://sonarcloud.io/dashboard?id=stepstone-tech_sonar-coldfusion)
3 |
4 | A [SonarQube plugin](http://www.sonarqube.org/) for analyzing ColdFusion code, based on the [CFLint library](https://github.com/cflint/CFLint).
5 |
6 | ## Installation
7 |
8 | 1. Download the JAR file from the [releases section](https://github.com/stepstone-tech/sonar-coldfusion/releases) or build it yourself by cloning the code and running `mvn install`.
9 | 1. Copy `sonar-coldfusion-plugin-{version}.jar` to `/extensions/plugins`.
10 | 1. Restart SonarQube.
11 |
12 | ## Compatibility
13 |
14 | SonarQube Version | Plugin Version
15 | ------------------|---------------
16 | 9.0 - 9.1 | 2.2.0
17 | 7.6 - 8.9 | 2.1.1
18 | 5.6 - 7.5 | 1.5.0
19 |
20 | ## Running
21 |
22 | Follow the instructions for [analyzing code with SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner). The ColdFusion plugin will automatically discover and analyze `.cfc` and `.cfm` files.
23 |
24 | ## Parameters tuning
25 |
26 | If you encounter log output indicating, that the Compute Engine of SonarQube has insufficient memory, similar to:
27 |
28 | ```
29 | 2016.06.22 16:17:43 INFO ce[o.s.s.c.t.CeWorkerCallableImpl] Execute task | project=ApplyNowModule | type=REPORT | id=AVV4eUIgcn4uboqEX1C3
30 | java.lang.OutOfMemoryError: GC overhead limit exceeded
31 | Dumping heap to java_pid8400.hprof ...
32 | Heap dump file created [565019912 bytes in 6.373 secs]
33 | ```
34 |
35 | you'll need to increase heap memory on the server, in `/conf/sonar.properties`:
36 |
37 | ```
38 | sonar.ce.javaOpts=-Xmx2g -Xms128m -XX:+HeapDumpOnOutOfMemoryError
39 | ```
40 |
41 | 2GB might be enough, or perhaps your code base warrants more.
42 |
43 | ## Building
44 |
45 | Run Maven goal
46 |
47 | ```bash
48 | mvn clean package
49 | ```
50 |
51 | ## Releasing
52 |
53 | Setup Maven settings.xml with
54 |
55 | ```xml
56 |
57 |
58 | github
59 | yourprivatekey
60 |
61 |
62 | ```
63 |
64 | Run Maven goal
65 |
66 | ```bash
67 | mvn clean package de.jutzig:github-release-plugin:1.3.0:release
68 | ```
69 |
70 | This will build the plugin jar file, create a release and a tag on github and upload the artifact to
71 | the [repo](https://github.com/stepstone-tech/sonar-coldfusion).
72 | ## Contributors
73 |
74 | Many thanks for the people, who created or improved this project:
75 |
76 | - Tomek Stec
77 | - Michał Paluchowski
78 | - Nicolas Bihan
79 | - Gareth Edwards
80 |
81 | ## License
82 |
83 | Copyright 2016-2019 StepStone GmbH
84 | and contributors
85 |
86 |
87 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
88 |
89 | http://www.apache.org/licenses/LICENSE-2.0
90 |
91 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
92 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.stepstone.sonar.plugin
7 | sonar-coldfusion-plugin
8 | sonar-plugin
9 | 2.2.0
10 |
11 | SonarQube Coldfusion Plugin
12 | Enables scanning of ColdFusion source files
13 | https://github.com/stepstone-tech/sonar-coldfusion
14 |
15 |
16 | StepStone GmbH
17 | http://www.stepstone.com/
18 |
19 |
20 |
21 | The Apache Software License, Version 2.0
22 | http://www.apache.org/licenses/LICENSE-2.0.txt
23 | repo
24 |
25 |
26 |
27 |
28 | git@github.com:stepstone-tech/sonar-coldfusion.git
29 | git@github.com:stepstone-tech/sonar-coldfusion.git
30 | https://github.com/stepstone-tech/sonar-coldfusion
31 |
32 |
33 |
34 | GitHub
35 | https://github.com/stepstone-tech/sonar-coldfusion/issues
36 |
37 |
38 |
39 | UTF-8
40 | 11
41 | 11
42 | 9.0.0.45539
43 | 1.5.0
44 | 1.16.0.719
45 |
46 |
47 |
48 |
49 | junit
50 | junit
51 | 4.13.2
52 | test
53 |
54 |
55 | org.mockito
56 | mockito-all
57 | 1.10.19
58 | test
59 |
60 |
61 |
62 | org.assertj
63 | assertj-core
64 | 3.21.0
65 | test
66 |
67 |
68 |
69 | org.sonarsource.sslr-squid-bridge
70 | sslr-squid-bridge
71 | 2.7.1.392
72 |
73 |
74 | sonar-plugin-api
75 | org.sonarsource.sonarqube
76 |
77 |
78 |
79 |
80 |
81 | org.sonarsource.analyzer-commons
82 | sonar-analyzer-commons
83 | ${sonar-analyzer-commons.version}
84 |
85 |
86 |
87 |
88 | org.sonarsource.sonarqube
89 | sonar-plugin-api
90 | ${sonar.version}
91 | provided
92 |
93 |
94 |
95 | org.sonarsource.sonarqube
96 | sonar-plugin-api-impl
97 | ${sonar.version}
98 | test
99 |
100 |
101 |
102 |
103 |
104 |
105 | org.sonarsource.sonar-packaging-maven-plugin
106 | sonar-packaging-maven-plugin
107 | 1.20.0.405
108 | true
109 |
110 | com.stepstone.sonar.plugin.coldfusion.ColdFusionPlugin
111 | ColdFusion
112 | CFLint ${cflint.version} Plugin for Sonarqube
113 | https://github.com/stepstone-tech/sonar-coldfusion
114 |
115 |
116 |
117 | org.apache.maven.plugins
118 | maven-dependency-plugin
119 | 2.10
120 |
121 |
122 | include-cflint
123 | generate-resources
124 |
125 | copy
126 |
127 |
128 |
129 |
130 | com.github.cflint
131 | CFLint
132 | ${cflint.version}
133 | all
134 | cflint.jar
135 |
136 |
137 | ${project.build.outputDirectory}/META-INF/runner
138 |
139 |
140 |
141 |
142 |
143 | de.jutzig
144 | github-release-plugin
145 | 1.4.0
146 |
147 | Sonarqube Coldfusion Plugin release
148 | ${project.version}
149 | ${project.version}
150 |
151 |
152 | ${project.build.directory}
153 |
154 | ${project.artifactId}*.jar
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | sonar
165 |
166 | stepstone-tech_sonar-coldfusion
167 | stepstone-tech
168 | https://sonarcloud.io
169 |
170 |
171 |
172 |
173 |
174 | org.sonarsource.scanner.maven
175 | sonar-maven-plugin
176 | 3.9.0.2155
177 |
178 |
179 | org.jacoco
180 | jacoco-maven-plugin
181 | 0.8.7
182 |
183 |
184 |
185 |
186 |
187 | org.jacoco
188 | jacoco-maven-plugin
189 |
190 |
191 |
192 | prepare-agent
193 |
194 |
195 |
196 | report
197 |
198 | report
199 |
200 |
201 |
202 | META-INF/runner/cflint.jar
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/ColdFusion.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion;
18 |
19 | import org.sonar.api.config.Configuration;
20 | import org.sonar.api.resources.AbstractLanguage;
21 |
22 | public class ColdFusion extends AbstractLanguage {
23 |
24 | private final Configuration configuration;
25 |
26 | public ColdFusion(Configuration configuration) {
27 | super(ColdFusionPlugin.LANGUAGE_KEY, ColdFusionPlugin.LANGUAGE_NAME);
28 | this.configuration = configuration;
29 | }
30 |
31 | @Override
32 | public String[] getFileSuffixes() {
33 | return configuration.getStringArray(ColdFusionPlugin.FILE_SUFFIXES_KEY);
34 | }
35 |
36 | @Override
37 | public boolean equals(Object o) {
38 | if (this == o) {
39 | return true;
40 | }
41 | if (o == null || getClass() != o.getClass()) {
42 | return false;
43 | }
44 | if (!super.equals(o)) {
45 | return false;
46 | }
47 |
48 | ColdFusion that = (ColdFusion) o;
49 |
50 | return !(configuration != null ? !configuration.equals(that.configuration) : that.configuration != null);
51 |
52 | }
53 |
54 | @Override
55 | public int hashCode() {
56 | int result = super.hashCode();
57 | result = 31 * result + (configuration != null ? configuration.hashCode() : 0);
58 | return result;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/ColdFusionPlugin.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion;
18 |
19 | import com.stepstone.sonar.plugin.coldfusion.profile.ColdFusionProfileExporter;
20 | import com.stepstone.sonar.plugin.coldfusion.profile.ColdFusionSonarWayProfile;
21 | import com.stepstone.sonar.plugin.coldfusion.rules.ColdFusionSonarRulesDefinition;
22 |
23 | import org.sonar.api.Plugin;
24 | import org.sonar.api.Properties;
25 | import org.sonar.api.Property;
26 |
27 | @Properties({
28 | @Property(
29 | key = ColdFusionPlugin.FILE_SUFFIXES_KEY,
30 | defaultValue = ColdFusionPlugin.FILE_SUFFIXES_DEFVALUE,
31 | name = "File suffixes",
32 | description = "Comma-separated list of suffixes of files to analyze.",
33 | project = true,
34 | multiValues = true,
35 | global = true
36 | ),
37 | @Property(
38 | key = ColdFusionPlugin.CFLINT_JAVA,
39 | defaultValue = "java",
40 | name = "Java executable",
41 | description = "",
42 | project = true,
43 | global = true
44 | ),
45 | @Property(
46 | key = ColdFusionPlugin.CFLINT_JAVA_OPTS,
47 | defaultValue = "",
48 | name = "Java executable options",
49 | description = "Additional parameters passed to java process. E.g. -Xmx1g",
50 | project = true,
51 | global = true
52 | ),
53 | })
54 | public class ColdFusionPlugin implements Plugin {
55 |
56 | public static final String LANGUAGE_KEY = "cf";
57 | public static final String LANGUAGE_NAME = "ColdFusion";
58 |
59 | public static final String FILE_SUFFIXES_KEY = "sonar.cf.file.suffixes";
60 | public static final String FILE_SUFFIXES_DEFVALUE = ".cfc,.cfm";
61 |
62 | public static final String REPOSITORY_KEY = "coldfusionsquid";
63 | public static final String REPOSITORY_NAME = "SonarQube";
64 |
65 | public static final String CFLINT_JAVA = "sonar.cf.cflint.java";
66 | public static final String CFLINT_JAVA_OPTS = "sonar.cf.cflint.java.opts";
67 |
68 | @Override
69 | public void define(Context context) {
70 | context.addExtensions(
71 | ColdFusion.class,
72 | ColdFusionSensor.class,
73 | ColdFusionSonarRulesDefinition.class,
74 | ColdFusionSonarWayProfile.class,
75 | ColdFusionProfileExporter.class
76 | );
77 |
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/ColdFusionSensor.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion;
18 |
19 | import com.google.common.base.Preconditions;
20 | import com.stepstone.sonar.plugin.coldfusion.cflint.CFLintAnalyzer;
21 | import com.stepstone.sonar.plugin.coldfusion.cflint.CFLintAnalysisResultImporter;
22 | import com.stepstone.sonar.plugin.coldfusion.cflint.CFLintConfigExporter;
23 | import org.sonar.api.batch.fs.FileSystem;
24 | import org.sonar.api.batch.fs.InputFile;
25 | import org.sonar.api.batch.sensor.Sensor;
26 | import org.sonar.api.batch.sensor.SensorContext;
27 | import org.sonar.api.batch.sensor.SensorDescriptor;
28 | import org.sonar.api.measures.CoreMetrics;
29 | import org.sonar.api.batch.rule.ActiveRules;
30 | import org.sonar.api.utils.log.Logger;
31 | import org.sonar.api.utils.log.Loggers;
32 |
33 | import javax.xml.stream.XMLStreamException;
34 | import java.io.BufferedReader;
35 | import java.io.File;
36 | import java.io.IOException;
37 | import java.io.InputStreamReader;
38 | import java.nio.file.Files;
39 | import java.util.ArrayList;
40 | import java.util.Collection;
41 | import java.util.List;
42 | import java.util.concurrent.Callable;
43 | import java.util.concurrent.ExecutorService;
44 | import java.util.concurrent.Executors;
45 | import java.util.concurrent.TimeUnit;
46 | import java.util.regex.Matcher;
47 | import java.util.regex.Pattern;
48 | import java.util.stream.Collectors;
49 |
50 | public class ColdFusionSensor implements Sensor {
51 |
52 | private final FileSystem fs;
53 | private final ActiveRules ruleProfile;
54 | private final Logger LOGGER = Loggers.get(ColdFusionSensor.class);
55 |
56 | public ColdFusionSensor(FileSystem fs, ActiveRules ruleProfile) {
57 | Preconditions.checkNotNull(fs);
58 | Preconditions.checkNotNull(ruleProfile);
59 |
60 | this.fs = fs;
61 | this.ruleProfile = ruleProfile;
62 | }
63 |
64 |
65 | @Override
66 | public void describe(SensorDescriptor descriptor) {
67 | descriptor.onlyOnLanguage(ColdFusionPlugin.LANGUAGE_KEY);
68 | descriptor.createIssuesForRuleRepository(ColdFusionPlugin.REPOSITORY_KEY);
69 | }
70 |
71 | @Override
72 | public void execute(SensorContext context) {
73 | try {
74 | analyze(context);
75 | importResults(context);
76 | measureProcessor(context);
77 | } catch (IOException | XMLStreamException e) {
78 | LOGGER.error("",e);
79 | }
80 | }
81 |
82 | private void analyze(SensorContext context) throws IOException, XMLStreamException {
83 | File configFile = generateCflintConfig();
84 | try {
85 | new CFLintAnalyzer(context).analyze(configFile);
86 | } finally {
87 | //when analysis is done we delete the created file
88 | deleteFile(configFile);
89 | }
90 | }
91 |
92 | private File generateCflintConfig() throws IOException, XMLStreamException {
93 | final File configFile = new File(fs.workDir(), "cflint-config.xml");
94 | Collection ruleKeys = ruleProfile.findByRepository(ColdFusionPlugin.REPOSITORY_KEY)
95 | .stream().map(rule -> rule.ruleKey().toString()).collect(Collectors.toList());
96 | new CFLintConfigExporter(ruleKeys).save(configFile);
97 | return configFile;
98 | }
99 |
100 | private void deleteFile(File configFile) throws IOException {
101 | if(configFile!= null){
102 | Files.deleteIfExists(configFile.toPath());
103 | }
104 | }
105 |
106 | private void importResults(SensorContext sensorContext) throws IOException {
107 | try {
108 | new CFLintAnalysisResultImporter(fs, sensorContext).parse(new File(fs.workDir(), "cflint-result.xml"));
109 | } catch (XMLStreamException e) {
110 | LOGGER.error(",e");
111 | } finally {
112 | deleteFile(new File(fs.workDir(), "cflint-result.xml"));
113 | }
114 | }
115 |
116 | private void measureProcessor(SensorContext context) {
117 | LOGGER.info("Starting measure processor");
118 |
119 | ExecutorService executorService = Executors.newSingleThreadExecutor();
120 | List> callableTasks = new ArrayList<>();
121 |
122 | for (InputFile inputFile : fs.inputFiles(fs.predicates().hasLanguage(ColdFusionPlugin.LANGUAGE_KEY))) {
123 | Callable callableTask = () -> {
124 | try {
125 | metricsCounter(inputFile, context);
126 | return 1;
127 | } catch (IOException e) {
128 | return 0;
129 | }
130 | };
131 | callableTasks.add(callableTask);
132 | }
133 |
134 | try {
135 | executorService.invokeAll(callableTasks);
136 | executorService.shutdown();
137 | executorService.awaitTermination(2, TimeUnit.MINUTES);
138 | } catch (InterruptedException e) {
139 | LOGGER.error("",e);
140 | }
141 |
142 | LOGGER.info("Measure processor done");
143 | }
144 |
145 | //Very basic and naive line of code counter for Coldfusion
146 | //Might count a line of code as comment
147 | private void metricsCounter(InputFile inputFile, SensorContext context) throws IOException {
148 | String currentLine;
149 | int commentLines = 0;
150 | int blankLines = 0;
151 | int lines = 0;
152 | int complexity = 1;
153 |
154 |
155 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputFile.inputStream()))) {
156 | if (inputFile.inputStream() != null) {
157 | while ((currentLine = reader.readLine()) != null) {
158 | lines++;
159 |
160 | if (currentLine.contains("")) {
163 | continue;
164 | }
165 | commentLines++;
166 | lines++;
167 | while (!(reader.readLine()).contains("-->")) {
168 | lines++;
169 | commentLines++;
170 | }
171 | } else if (currentLine.trim().isEmpty()) {
172 | blankLines++;
173 | continue;
174 | }
175 |
176 | complexity = getLineComplexity(currentLine, complexity);
177 | }
178 | }
179 | }
180 | int linesOfCode = lines-blankLines-commentLines;
181 | // every 100 lines of code add 1 to the content's complexity
182 | complexity = complexity + (linesOfCode / 100);
183 |
184 | context.newMeasure().forMetric(CoreMetrics.COMMENT_LINES).on(inputFile).withValue(commentLines).save();
185 | context.newMeasure().forMetric(CoreMetrics.NCLOC).on(inputFile).withValue(linesOfCode).save();
186 | context.newMeasure().forMetric(CoreMetrics.LINES).on(inputFile).withValue(lines).save();
187 | context.newMeasure().forMetric(CoreMetrics.COMPLEXITY).on(inputFile).withValue(complexity).save();
188 | }
189 |
190 | private int getLineComplexity(String currentLine, int complexity) {
191 | int mcCabeComplexity =0;
192 | int lineByLineComplexity = 0;
193 | int lineByLineComplexityIncrement = 4;
194 | int thisLineComplexityAdd = 0;
195 | int thisLineComplexitySubtract = 0;
196 |
197 | // SCORE INCREMENTS
198 | mcCabeComplexity += countRegexOccurrences(currentLine, "(inputFile.lines()){
121 | logger
122 | .error("Problem creating issue for file {}, issue is line {} but file has {} lines", inputFile, locationAttributes.getLine().get(), inputFile.lines());
123 | return;
124 | }
125 |
126 | logger.debug("create New Issue {} for file {}", issueAttributes, inputFile.filename());
127 | final NewIssue issue = sensorContext.newIssue();
128 |
129 | final NewIssueLocation issueLocation = issue.newLocation();
130 | issueLocation.on(inputFile);
131 | issueLocation.at(inputFile.selectLine(locationAttributes.getLine().get()));
132 | issueLocation.message(locationAttributes.getMessage().get());
133 |
134 | issue.forRule(RuleKey.of(ColdFusionPlugin.REPOSITORY_KEY, issueAttributes.getId().get()));
135 | issue.at(issueLocation);
136 | issue.save();
137 | }
138 |
139 | private void closeXmlStream() throws XMLStreamException {
140 | if (stream != null) {
141 | try {
142 | stream.close();
143 | } catch (Exception e) {
144 | throw e;
145 | }
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/cflint/CFLintAnalyzer.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.cflint;
18 |
19 | import com.stepstone.sonar.plugin.coldfusion.ColdFusionPlugin;
20 |
21 | import com.google.common.base.Preconditions;
22 | import com.google.common.base.Strings;
23 |
24 | import org.sonar.api.batch.fs.FileSystem;
25 | import org.sonar.api.batch.sensor.SensorContext;
26 | import org.sonar.api.config.Configuration;
27 | import org.sonar.api.utils.command.Command;
28 | import org.sonar.api.utils.command.CommandExecutor;
29 | import org.sonar.api.utils.command.StreamConsumer;
30 | import org.sonar.api.utils.log.Logger;
31 | import org.sonar.api.utils.log.Loggers;
32 |
33 | import java.io.File;
34 | import java.io.IOException;
35 | import javax.xml.stream.XMLStreamException;
36 |
37 | public class CFLintAnalyzer {
38 |
39 | private final Logger logger = Loggers.get(CFLintAnalyzer.class);
40 | private final Configuration settings;
41 | private final FileSystem fs;
42 |
43 | public CFLintAnalyzer(SensorContext sensorContext) {
44 | Preconditions.checkNotNull(sensorContext);
45 |
46 | this.settings = sensorContext.config();
47 | this.fs = sensorContext.fileSystem();
48 | }
49 |
50 | public void analyze(File configFile) throws IOException, XMLStreamException {
51 | File executableJar = null;
52 | try {
53 | Command command = Command.create(settings.get(ColdFusionPlugin.CFLINT_JAVA).orElseThrow(
54 | IllegalStateException::new
55 | ));
56 | addCflintJavaOpts(command);
57 | executableJar = extractCflintJar();
58 | command.addArgument("-jar")
59 | .addArgument(executableJar.getPath())
60 | .addArgument("-xml")
61 | .addArgument("-folder")
62 | .addArgument(settings.get("sonar.projectBaseDir").orElseThrow(
63 | IllegalStateException::new
64 | ))
65 | .addArgument("-xmlfile")
66 | .addArgument(fs.workDir() + File.separator + "cflint-result.xml")
67 | .addArgument("-configfile")
68 | .addArgument(configFile.getPath());
69 |
70 | CommandExecutor executor = CommandExecutor.create();
71 | int exitCode = executor.execute(command, new LogInfoStreamConsumer(), new LogErrorStreamConsumer(), Integer.MAX_VALUE);
72 |
73 | if (exitCode != 0) {
74 | throw new IllegalStateException("The CFLint analyzer failed with exit code: " + exitCode);
75 | }
76 | } finally {
77 | //cleanup
78 | if(executableJar!= null && executableJar.exists()) {
79 | executableJar.deleteOnExit();
80 | }
81 | }
82 |
83 | }
84 |
85 | protected File extractCflintJar() throws IOException {
86 | return new CFLintExtractor(fs.workDir()).extract();
87 | }
88 |
89 | protected void addCflintJavaOpts(Command command) {
90 | final String cflintJavaOpts = settings.get(ColdFusionPlugin.CFLINT_JAVA_OPTS).orElse("");
91 | if (!Strings.isNullOrEmpty(cflintJavaOpts)) {
92 | final String[] arguments = cflintJavaOpts.split(" ");
93 | for (String argument : arguments) {
94 | command.addArgument(argument);
95 | }
96 | }
97 | }
98 |
99 | private class LogInfoStreamConsumer implements StreamConsumer {
100 |
101 | @Override
102 | public void consumeLine(String line) {
103 | logger.info("Consuming line {}", line);
104 | }
105 |
106 | }
107 |
108 | private class LogErrorStreamConsumer implements StreamConsumer {
109 |
110 | @Override
111 | public void consumeLine(String line) {
112 | logger.error("Error consuming line {}", line);
113 | }
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/cflint/CFLintConfigExporter.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.cflint;
18 |
19 | import javax.xml.stream.XMLOutputFactory;
20 | import javax.xml.stream.XMLStreamException;
21 | import javax.xml.stream.XMLStreamWriter;
22 | import java.io.File;
23 | import java.io.FileWriter;
24 | import java.io.IOException;
25 | import java.io.Writer;
26 | import java.util.Collection;
27 |
28 | public class CFLintConfigExporter {
29 |
30 | private final Collection ruleKeys;
31 | public CFLintConfigExporter(Collection ruleKeys) {
32 | this.ruleKeys = ruleKeys;
33 | }
34 |
35 | public void save(File configFile) throws IOException, XMLStreamException {
36 | try (FileWriter writer = new FileWriter(configFile)) {
37 | save(writer);
38 | }
39 | }
40 |
41 | public void save(Writer writer) throws IOException, XMLStreamException {
42 | final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
43 | XMLStreamWriter xtw=null;
44 | try {
45 | xtw = xmlOutputFactory.createXMLStreamWriter(writer);
46 |
47 | xtw.writeStartDocument();
48 | xtw.writeStartElement("config");
49 |
50 | for (String ruleKey: ruleKeys) {
51 | xtw.writeStartElement("includes");
52 | xtw.writeAttribute("code", ruleKey);
53 | xtw.writeEndElement();
54 | }
55 |
56 | xtw.writeEndElement();
57 | xtw.writeEndDocument();
58 | } finally {
59 | if(xtw!=null) {
60 | xtw.close();
61 | }
62 | }
63 |
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/cflint/CFLintExtractor.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.cflint;
18 |
19 | import static com.google.common.base.Preconditions.checkNotNull;
20 |
21 | import org.sonar.api.batch.InstantiationStrategy;
22 |
23 | import java.io.File;
24 | import java.io.IOException;
25 | import java.io.InputStream;
26 | import java.nio.file.Files;
27 | import java.nio.file.StandardCopyOption;
28 |
29 | @InstantiationStrategy(InstantiationStrategy.PER_BATCH)
30 | public class CFLintExtractor {
31 |
32 | private static final String CFLINT_RESOURCE = "/META-INF/runner/cflint.jar";
33 | private static final String CFLINT = "runner/cflint.jar";
34 |
35 | private final File workDir;
36 |
37 | public CFLintExtractor(File workDir) {
38 | checkNotNull(workDir);
39 |
40 | this.workDir = workDir;
41 | }
42 |
43 | public File extract() throws IOException {
44 | File cflintJar = getFile();
45 |
46 | try (InputStream input = getClass().getResourceAsStream(CFLINT_RESOURCE)) {
47 | Files.copy(input, cflintJar.toPath(), StandardCopyOption.REPLACE_EXISTING);
48 | }
49 |
50 | return cflintJar;
51 | }
52 |
53 | private File getFile() throws IOException {
54 | final File cflintJar = new File(workDir, CFLINT);
55 |
56 | mkdirs(cflintJar.getParentFile());
57 |
58 | return cflintJar;
59 | }
60 |
61 | private void mkdirs(File directory) throws IOException {
62 | if (!directory.exists()) {
63 | final boolean mkdirs = directory.mkdirs();
64 |
65 | if (!mkdirs) {
66 | throw new IOException("Cannot create directory: " + directory);
67 | }
68 | }
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/cflint/xml/CountsAttributes.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.cflint.xml;
18 |
19 | import javax.xml.stream.XMLStreamReader;
20 |
21 | public class CountsAttributes extends TagAttribute {
22 |
23 | private Integer totallines;
24 | private Integer totalfiles;
25 |
26 | public CountsAttributes(XMLStreamReader stream) {
27 | this.totallines = getAttributeInteger("totallines", stream);
28 | this.totalfiles = getAttributeInteger("totalfiles", stream);
29 | }
30 |
31 | public Integer getTotalLines() {
32 | return totallines;
33 | }
34 |
35 | public Integer getTotalFiles() {
36 | return totalfiles;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/cflint/xml/IssueAttributes.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.cflint.xml;
18 |
19 |
20 | import java.util.Optional;
21 | import javax.xml.stream.XMLStreamReader;
22 |
23 | public class IssueAttributes extends TagAttribute {
24 |
25 | private Optional id;
26 |
27 | public IssueAttributes(XMLStreamReader stream) {
28 | this.id = getAttributeValue("id", stream);
29 | }
30 |
31 | public Optional getId() {
32 | return id;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/cflint/xml/LocationAttributes.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.cflint.xml;
18 |
19 |
20 | import java.util.Optional;
21 | import javax.xml.stream.XMLStreamReader;
22 |
23 | public class LocationAttributes extends TagAttribute {
24 |
25 | private final String file;
26 | private final Optional line;
27 | private final Optional message;
28 |
29 | public LocationAttributes(XMLStreamReader stream) {
30 | file = getAttributeValue("file", stream).get();
31 | message = getAttributeValue("message", stream);
32 |
33 | Optional currentLine = getAttributeValue("line", stream);
34 |
35 | this.line = currentLine.map(Integer::parseInt);
36 | }
37 |
38 | public String getFile() {
39 | return file;
40 | }
41 |
42 | public Optional getLine() {
43 | return line;
44 | }
45 |
46 | public Optional getMessage() {
47 | return message;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/cflint/xml/TagAttribute.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.cflint.xml;
18 |
19 |
20 | import org.apache.commons.lang.StringUtils;
21 |
22 | import java.util.Optional;
23 | import javax.xml.stream.XMLStreamReader;
24 |
25 | class TagAttribute {
26 |
27 | protected Optional getAttributeValue(String name, XMLStreamReader stream) {
28 |
29 | for (int i = 0; i < stream.getAttributeCount(); i++) {
30 |
31 | if (name.equalsIgnoreCase(stream.getAttributeLocalName(i))) {
32 | return Optional.of(StringUtils.trimToEmpty(stream.getAttributeValue(i)));
33 | }
34 | }
35 |
36 | return Optional.empty();
37 | }
38 |
39 |
40 | protected Integer getAttributeInteger(String name, XMLStreamReader stream) {
41 |
42 | for (int i = 0; i < stream.getAttributeCount(); i++) {
43 |
44 | if (name.equalsIgnoreCase(stream.getAttributeLocalName(i))) {
45 | return Integer.valueOf(stream.getAttributeValue(i));
46 | }
47 | }
48 |
49 | return 0;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/errors/ColdFusionPluginException.java:
--------------------------------------------------------------------------------
1 | package com.stepstone.sonar.plugin.coldfusion.errors;
2 |
3 | public class ColdFusionPluginException extends RuntimeException {
4 |
5 | public ColdFusionPluginException(String message, Throwable cause) {
6 | super(message, cause);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/package-info.java:
--------------------------------------------------------------------------------
1 | @ParametersAreNonnullByDefault package com.stepstone.sonar.plugin.coldfusion;
2 |
3 | import javax.annotation.ParametersAreNonnullByDefault;
4 |
5 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/profile/ColdFusionProfileExporter.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.profile;
18 |
19 | import com.google.common.base.Throwables;
20 | import com.stepstone.sonar.plugin.coldfusion.ColdFusionPlugin;
21 | import com.stepstone.sonar.plugin.coldfusion.cflint.CFLintConfigExporter;
22 | import org.sonar.api.profiles.ProfileExporter;
23 | import org.sonar.api.profiles.RulesProfile;
24 |
25 | import javax.xml.stream.XMLStreamException;
26 | import java.io.IOException;
27 | import java.io.Writer;
28 | import java.util.Collection;
29 | import java.util.stream.Collectors;
30 |
31 | public class ColdFusionProfileExporter extends ProfileExporter {
32 |
33 | public ColdFusionProfileExporter() {
34 | super("coldfusion-cflint", "CFLint Rule Set");
35 | setSupportedLanguages(ColdFusionPlugin.LANGUAGE_KEY);
36 | }
37 |
38 | @Override
39 | public void exportProfile(RulesProfile ruleProfile, Writer writer) {
40 | try {
41 | Collection ruleKeys = ruleProfile.getActiveRulesByRepository(ColdFusionPlugin.REPOSITORY_KEY)
42 | .stream().map(rule -> rule.getRule().ruleKey().rule())
43 | .collect(Collectors.toList());
44 | new CFLintConfigExporter(ruleKeys).save(writer);
45 | } catch (IOException | XMLStreamException e) {
46 | Throwables.propagate(e);
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/profile/ColdFusionSonarWayProfile.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.profile;
18 |
19 | import com.stepstone.sonar.plugin.coldfusion.ColdFusionPlugin;
20 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
21 | import org.sonarsource.analyzer.commons.BuiltInQualityProfileJsonLoader;
22 |
23 | public class ColdFusionSonarWayProfile implements BuiltInQualityProfilesDefinition {
24 |
25 | private static final String PROFILE_NAME = "Sonar way";
26 | private static final String DEFAULT_PROFILE_PATH = "com/stepstone/sonar/plugin/coldfusion/profile.json";
27 |
28 | @Override
29 | public void define(Context context) {
30 | NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile(PROFILE_NAME, ColdFusionPlugin.LANGUAGE_KEY);
31 | BuiltInQualityProfileJsonLoader.load(profile, ColdFusionPlugin.REPOSITORY_KEY, DEFAULT_PROFILE_PATH);
32 | profile.done();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/stepstone/sonar/plugin/coldfusion/rules/ColdFusionSonarRulesDefinition.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 StepStone GmbH
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package com.stepstone.sonar.plugin.coldfusion.rules;
18 |
19 | import static java.nio.charset.StandardCharsets.UTF_8;
20 |
21 | import com.stepstone.sonar.plugin.coldfusion.ColdFusionPlugin;
22 |
23 | import org.sonar.api.batch.ScannerSide;
24 | import org.sonar.api.server.rule.RulesDefinition;
25 | import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
26 |
27 | import java.io.InputStreamReader;
28 |
29 | @ScannerSide
30 | public class ColdFusionSonarRulesDefinition implements RulesDefinition {
31 |
32 | private static final String DEFAULT_RULES_FILE = "/com/stepstone/sonar/plugin/coldfusion/rules.xml";
33 |
34 | private final RulesDefinitionXmlLoader rulesLoader;
35 |
36 | public ColdFusionSonarRulesDefinition(RulesDefinitionXmlLoader rulesLoader) {
37 | this.rulesLoader = rulesLoader;
38 | }
39 |
40 | @Override
41 | public void define(Context context) {
42 | NewRepository repository = context
43 | .createRepository(ColdFusionPlugin.REPOSITORY_KEY, ColdFusionPlugin.LANGUAGE_KEY)
44 | .setName(ColdFusionPlugin.REPOSITORY_NAME);
45 |
46 | rulesLoader.load(repository, new InputStreamReader(getClass().getResourceAsStream(DEFAULT_RULES_FILE), UTF_8));
47 |
48 | repository.done();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/resources/com/stepstone/sonar/plugin/coldfusion/profile.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Sonar way",
3 | "ruleKeys": [
4 | "ARG_DEFAULT_MISSING",
5 | "ARG_VAR_CONFLICT",
6 | "ARG_VAR_MIXED",
7 | "NO_DEFAULT_INSIDE_SWITCH",
8 | "GLOBAL_VAR",
9 | "NESTED_CFOUTPUT",
10 | "OUTPUT_ATTR",
11 | "QUERYPARAM_REQ",
12 | "CFQUERYPARAM_REQ",
13 | "QUERYNEW_DATATYPE",
14 | "MISSING_VAR",
15 | "AVOID_USING_CFDUMP_TAG",
16 | "AVOID_USING_CFEXECUTE_TAG",
17 | "AVOID_USING_ISDATE",
18 | "AVOID_USING_CFABORT_TAG",
19 | "AVOID_USING_ABORT",
20 | "AVOID_USING_CFINSERT_TAG",
21 | "AVOID_USING_CFMODULE_TAG",
22 | "AVOID_USING_CFUPDATE_TAG",
23 | "AVOID_USING_CFINCLUDE_TAG",
24 | "COMPONENT_HINT_MISSING",
25 | "FUNCTION_HINT_MISSING",
26 | "ARG_HINT_MISSING",
27 | "ARG_HINT_MISSING_SCRIPT",
28 | "ARG_TYPE_MISSING",
29 | "ARG_TYPE_ANY",
30 | "EXCESSIVE_FUNCTION_LENGTH",
31 | "EXCESSIVE_COMPONENT_LENGTH",
32 | "FUNCTION_TYPE_MISSING",
33 | "FUNCTION_TYPE_ANY",
34 | "EXCESSIVE_ARGUMENTS",
35 | "EXCESSIVE_FUNCTIONS",
36 | "FUNCTION_TOO_COMPLEX",
37 | "AVOID_USING_WRITEDUMP",
38 | "AVOID_USING_STRUCTNEW",
39 | "AVOID_USING_ISDEBUGMODE",
40 | "AVOID_USING_ARRAYNEW",
41 | "COMPLEX_BOOLEAN_CHECK",
42 | "EXPLICIT_BOOLEAN_CHECK",
43 | "VAR_INVALID_NAME",
44 | "VAR_ALLCAPS_NAME",
45 | "SCOPE_ALLCAPS_NAME",
46 | "VAR_TOO_SHORT",
47 | "VAR_TOO_LONG",
48 | "VAR_TOO_WORDY",
49 | "VAR_IS_TEMPORARY",
50 | "VAR_HAS_PREFIX_OR_POSTFIX",
51 | "ARGUMENT_MISSING_NAME",
52 | "ARGUMENT_INVALID_NAME",
53 | "ARGUMENT_ALLCAPS_NAME",
54 | "ARGUMENT_TOO_SHORT",
55 | "ARGUMENT_TOO_LONG",
56 | "ARGUMENT_TOO_WORDY",
57 | "ARGUMENT_IS_TEMPORARY",
58 | "ARGUMENT_HAS_PREFIX_OR_POSTFIX",
59 | "METHOD_INVALID_NAME",
60 | "METHOD_ALLCAPS_NAME",
61 | "METHOD_TOO_SHORT",
62 | "METHOD_TOO_LONG",
63 | "METHOD_TOO_WORDY",
64 | "METHOD_IS_TEMPORARY",
65 | "METHOD_HAS_PREFIX_OR_POSTFIX",
66 | "COMPONENT_INVALID_NAME",
67 | "COMPONENT_ALLCAPS_NAME",
68 | "COMPONENT_TOO_SHORT",
69 | "COMPONENT_TOO_LONG",
70 | "COMPONENT_TOO_WORDY",
71 | "COMPONENT_IS_TEMPORARY",
72 | "COMPONENT_HAS_PREFIX_OR_POSTFIX",
73 | "FILE_SHOULD_START_WITH_LOWERCASE",
74 | "AVOID_USING_CREATEOBJECT",
75 | "AVOID_USING_DEBUG_ATTR",
76 | "AVOID_USING_CFSETTING_DEBUG",
77 | "UNUSED_LOCAL_VARIABLE",
78 | "UNUSED_METHOD_ARGUMENT",
79 | "COMPARE_INSTEAD_OF_ASSIGN",
80 | "PARSE_ERROR",
81 | "MISSING_SEMI",
82 | "UNQUOTED_STRUCT_KEY",
83 | "SQL_SELECT_STAR",
84 | "NEVER_USE_QUERY_IN_CFM",
85 | "USE_DISPLAY_NAME",
86 | "LOCAL_LITERAL_VALUE_USED_TOO_OFTEN",
87 | "GLOBAL_LITERAL_VALUE_USED_TOO_OFTEN",
88 | "PACKAGE_CASE_MISMATCH",
89 | "PARSE_NOTHING",
90 | "PLUGIN_ERROR",
91 | "AVOID_EMPTY_FILES"
92 | ]
93 | }
94 |
95 |
--------------------------------------------------------------------------------
/src/main/resources/com/stepstone/sonar/plugin/coldfusion/rules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ARG_DEFAULT_MISSING
5 | Optional argument is missing a default value.
6 | CRITICAL
7 | SINGLE
8 |
]]>
9 | bug
10 |
11 |
12 | ARG_VAR_CONFLICT
13 | Variable declared in both var and argument scopes.
14 | MAJOR
15 | SINGLE
16 | Variable should not be declared in both local and argument scopes. ]]>
17 | bug
18 |
19 |
20 | ARG_VAR_MIXED
21 | Variable referenced in local and argument scopes.
22 | MAJOR
23 | SINGLE
24 | Variable should not be referenced in local and argument scope. ]]>
25 | bug
26 |
27 |
28 | NO_DEFAULT_INSIDE_SWITCH
29 | Missing default switch statement.
30 | MAJOR
31 | SINGLE
32 | Not having a Default statement defined for a switch could pose potential issues. ]]>
33 |
34 |
35 | GLOBAL_VAR
36 | Global variable exists.
37 | CRITICAL
38 | SINGLE
39 | Identifier is global. Referencing in a CFC or function should be avoided. ]]>
40 | bug
41 |
42 |
43 | NESTED_CFOUTPUT
44 | Nested cfoutput with cfquery tag.
45 | MINOR
46 | SINGLE
47 | Nested CFOutput, outer CFOutput has @query
. ]]>
48 |
49 |
50 | OUTPUT_ATTR
51 | Tag should have output='false'.
52 | MAJOR
53 | SINGLE
54 |
should have @output='false' ]]>
55 |
56 |
57 | QUERYPARAM_REQ
58 | SetSql() statement should use .addParam().
59 | BLOCKER
60 | SINGLE
61 | setSql() statement should use .addParam() instead of #'s name="variable" ]]>
62 | security
63 |
64 |
65 | CFQUERYPARAM_REQ
66 | cfquery should use cfqueryparam
67 | BLOCKER
68 | SINGLE
69 |
should use
for variable 'variable'. ]]>
70 | security
71 |
72 |
73 | QUERYNEW_DATATYPE
74 | QueryNew statement should specify datatypes.
75 | BLOCKER
76 | SINGLE
77 | ]]>
78 | bug
79 |
80 |
81 | MISSING_VAR
82 | Variable is not declared with a var statement.
83 | CRITICAL
84 | SINGLE
85 | Variable is not declared with a var statement. ]]>
86 | bug
87 |
88 |
89 | AVOID_USING_CFDUMP_TAG
90 | Avoid use of cfdump tags.
91 | MAJOR
92 | SINGLE
93 | Avoid leaving
tags in committed code. Debug information should be omitted from release code ]]>
94 | security
95 |
96 |
97 | AVOID_USING_CFEXECUTE_TAG
98 | Avoid use of cfexecute tags.
99 | CRITICAL
100 | SINGLE
101 | Avoid leaving
tags in committed code. CFexecute can be used as an attack vector and is slow. ]]>
102 | security
103 |
104 |
105 | AVOID_USING_ISDATE
106 | Avoid use of isDate()
107 | MAJOR
108 | SINGLE
109 | Avoid using the isDate()
built-in function. It is too permissive. Use isValid()
instead. ]]>
110 | bug
111 |
112 |
113 | AVOID_USING_CFABORT_TAG
114 | Avoid use of cfabort tags.
115 | CRITICAL
116 | SINGLE
117 | Avoid leaving
tags in committed code. ]]>
118 | bug
119 |
120 |
121 | AVOID_USING_ABORT
122 | Avoid use of abort statements.
123 | CRITICAL
124 | SINGLE
125 | Avoid using abort in production code. ]]>
126 | bug
127 |
128 |
129 | AVOID_USING_CFINSERT_TAG
130 | Avoid use of cfinsert tags.
131 | CRITICAL
132 | SINGLE
133 | Avoid using
tags. Use cfquery and cfstoredproc instead. ]]>
134 | bug
135 |
136 |
137 | AVOID_USING_CFMODULE_TAG
138 | Avoid use of cfmodule tags.
139 | MAJOR
140 | SINGLE
141 | ]]>
142 | bug
143 |
144 |
145 | AVOID_USING_CFUPDATE_TAG
146 | Avoid use of cfupdate tags.
147 | MAJOR
148 | SINGLE
149 | Avoid using
tags. Use cfquery and cfstoredproc instead. ]]>
150 | bug
151 |
152 |
153 | AVOID_USING_CFINCLUDE_TAG
154 | Avoid use of cfinclude tags.
155 | CRITICAL
156 | SINGLE
157 | Avoid using
tags. Use components instead. ]]>
158 |
159 |
160 |
161 | COMPONENT_HINT_MISSING
162 | Component is missing a hint.
163 | MINOR
164 | SINGLE
165 | ]]>
166 |
167 |
168 | FUNCTION_HINT_MISSING
169 | Function is missing a hint.
170 | MINOR
171 | SINGLE
172 | ]]>
173 |
174 |
175 | ARG_HINT_MISSING
176 | Argument is missing a hint.
177 | MINOR
178 | SINGLE
179 | ]]>
180 |
181 |
182 | ARG_HINT_MISSING_SCRIPT
183 | Argument is missing a hint.
184 | MINOR
185 | SINGLE
186 | Argument is missing a hint. Use javadoc style annotations on cfscript functions. ]]>
187 |
188 |
189 | ARG_TYPE_MISSING
190 | Component is missing a type.
191 | BLOCKER
192 | SINGLE
193 | Argument variable is missing a type. ]]>
194 | bug
195 |
196 |
197 | ARG_TYPE_ANY
198 | Component is of type any.
199 | CRITICAL
200 | SINGLE
201 | ]]>
202 | bug
203 |
204 |
205 | EXCESSIVE_FUNCTION_LENGTH
206 | Method is too long.
207 | MAJOR
208 | SINGLE
209 | Function should be fewer than 100 lines. ]]>
210 |
211 |
212 | EXCESSIVE_COMPONENT_LENGTH
213 | Component is too long.
214 | MAJOR
215 | SINGLE
216 | Component should be fewer than 500 lines. ]]>
217 |
218 |
219 | FUNCTION_TYPE_MISSING
220 | Function is missing a return type.
221 | BLOCKER
222 | SINGLE
223 | ]]>
224 | bug
225 |
226 |
227 | FUNCTION_TYPE_ANY
228 | Function has a return type of any.
229 | CRITICAL
230 | SINGLE
231 | ]]>
232 | bug
233 |
234 |
235 | EXCESSIVE_ARGUMENTS
236 | Function has too many arguments.
237 | MAJOR
238 | SINGLE
239 | Function has too many arguments. Should be fewer than 10. ]]>
240 |
241 |
242 | EXCESSIVE_FUNCTIONS
243 | Too many functions.
244 | MINOR
245 | SINGLE
246 | Component has too many functions. Should be fewer than 10. ]]>
247 |
248 |
249 | FUNCTION_TOO_COMPLEX
250 | Function is too complex.
251 | CRITICAL
252 | SINGLE
253 | Function is too complex. Consider breaking the function into smaller functions. ]]>
254 |
255 |
256 | AVOID_USING_WRITEDUMP
257 | Avoid use of writedump statements.
258 | MAJOR
259 | SINGLE
260 | ]]>
261 | security
262 |
263 |
264 | AVOID_USING_STRUCTNEW
265 | Avoid use of structnew statements. Use {} instead.
266 | MINOR
267 | SINGLE
268 | ]]>
269 |
270 |
271 | AVOID_USING_ISDEBUGMODE
272 | Avoid use of isdebugmode statements.
273 | MINOR
274 | SINGLE
275 | Avoid using the IsDebugMode function in production code. ]]>
276 |
277 |
278 | AVOID_USING_ARRAYNEW
279 | Avoid use of arraynew statements. Use [] instead.
280 | MINOR
281 | SINGLE
282 | ]]>
283 |
284 |
285 | COMPLEX_BOOLEAN_CHECK
286 | Complex boolean expression.
287 | MAJOR
288 | SINGLE
289 | ]]>
290 |
291 |
292 | EXPLICIT_BOOLEAN_CHECK
293 | Checking boolean expression explicitly.
294 | MAJOR
295 | SINGLE
296 | Explicit check of boolean expression is not needed. ]]>
297 |
298 |
299 | VAR_INVALID_NAME
300 | Variable has invalid name.
301 | CRITICAL
302 | SINGLE
303 | Variable is not a valid name. Please use camelCase or underscores. ]]>
304 | bug
305 |
306 |
307 | VAR_ALLCAPS_NAME
308 | Variable name is allcaps.
309 | MINOR
310 | SINGLE
311 | Variable should not be upper case. ]]>
312 |
313 |
314 | VAR_TOO_SHORT
315 | Variable name is too short.
316 | MINOR
317 | SINGLE
318 | ]]>
319 |
320 |
321 | VAR_TOO_LONG
322 | Variable name is too long.
323 | MINOR
324 | SINGLE
325 | ]]>
326 |
327 |
328 | VAR_TOO_WORDY
329 | Variable name contain too many words.
330 | MINOR
331 | SINGLE
332 | ]]>
333 |
334 |
335 | VAR_IS_TEMPORARY
336 | Variable name looks temporary.
337 | MAJOR
338 | SINGLE
339 | ]]>
340 |
341 |
342 | VAR_HAS_PREFIX_OR_POSTFIX
343 | Variable name has prefix or postfix.
344 | MINOR
345 | SINGLE
346 | Variable has prefix or postfix variable and could be named better. ]]>
347 |
348 |
349 | ARGUMENT_MISSING_NAME
350 | Argument is missing a name.
351 | MINOR
352 | SINGLE
353 | ]]>
354 |
355 |
356 | ARGUMENT_INVALID_NAME
357 | Argument has invalid name.
358 | CRITICAL
359 | SINGLE
360 | Please use camelCase or underscores. ]]>
361 | bug
362 |
363 |
364 | ARGUMENT_ALLCAPS_NAME
365 | Argument name is allcaps.
366 | MINOR
367 | SINGLE
368 | ]]>
369 |
370 |
371 | ARGUMENT_TOO_SHORT
372 | Argument name is too short.
373 | MINOR
374 | SINGLE
375 | ]]>
376 |
377 |
378 | ARGUMENT_TOO_LONG
379 | Argument name is too long.
380 | MINOR
381 | SINGLE
382 | ]]>
383 |
384 |
385 | ARGUMENT_TOO_WORDY
386 | Argument name contain too many words.
387 | MINOR
388 | SINGLE
389 | ]]>
390 |
391 |
392 | ARGUMENT_IS_TEMPORARY
393 | Argument name looks temporary.
394 | MAJOR
395 | SINGLE
396 | ]]>
397 |
398 |
399 | ARGUMENT_HAS_PREFIX_OR_POSTFIX
400 | Argument name has prefix or postfix.
401 | MINOR
402 | SINGLE
403 | ]]>
404 |
405 |
406 | METHOD_INVALID_NAME
407 | Method has invalid name.
408 | CRITICAL
409 | SINGLE
410 | ]]>
411 | bug
412 |
413 |
414 | METHOD_ALLCAPS_NAME
415 | Method name is allcaps.
416 | MINOR
417 | SINGLE
418 | ]]>
419 |
420 |
421 | METHOD_TOO_SHORT
422 | Method name is too short.
423 | MINOR
424 | SINGLE
425 | ]]>
426 |
427 |
428 | METHOD_TOO_LONG
429 | Method name is too long.
430 | MINOR
431 | SINGLE
432 | ]]>
433 |
434 |
435 | METHOD_TOO_WORDY
436 | Method name contain too many words.
437 | MINOR
438 | SINGLE
439 | ]]>
440 |
441 |
442 | METHOD_IS_TEMPORARY
443 | Method name looks temporary.
444 | MAJOR
445 | SINGLE
446 | ]]>
447 |
448 |
449 | METHOD_HAS_PREFIX_OR_POSTFIX
450 | Method name has prefix or postfix.
451 | MINOR
452 | SINGLE
453 | ]]>
454 |
455 |
456 | COMPONENT_INVALID_NAME
457 | Component has invalid name.
458 | CRITICAL
459 | SINGLE
460 | ]]>
461 | bug
462 |
463 |
464 | COMPONENT_ALLCAPS_NAME
465 | Component name is allcaps.
466 | MINOR
467 | SINGLE
468 | ]]>
469 |
470 |
471 | COMPONENT_TOO_SHORT
472 | Component name is too short.
473 | MINOR
474 | SINGLE
475 | ]]>
476 |
477 |
478 | COMPONENT_TOO_LONG
479 | Component name is too long.
480 | MINOR
481 | SINGLE
482 | ]]>
483 |
484 |
485 | COMPONENT_TOO_WORDY
486 | Component name contain too many words.
487 | MINOR
488 | SINGLE
489 | ]]>
490 |
491 |
492 | COMPONENT_IS_TEMPORARY
493 | Component name looks temporary.
494 | MAJOR
495 | SINGLE
496 | Component name component could be named better. ]]>
497 |
498 |
499 | COMPONENT_HAS_PREFIX_OR_POSTFIX
500 | Component name has prefix or postfix.
501 | MINOR
502 | SINGLE
503 | Component name has prefix or postfix and could be named better. ]]>
504 |
505 |
506 | FILE_SHOULD_START_WITH_LOWERCASE
507 | CFM File starts with upper case.
508 | MINOR
509 | SINGLE
510 | Filename starts with an upper case letter. Only components (.cfc files) should start with an upper case letter. ]]>
511 |
512 |
513 | AVOID_USING_CREATEOBJECT
514 | Avoid use of creatobject statements.
515 | MAJOR
516 | SINGLE
517 | ]]>
518 |
519 |
520 | AVOID_USING_DEBUG_ATTR
521 | Avoid use of debug attribute.
522 | CRITICAL
523 | SINGLE
524 | ]]>
525 | security
526 |
527 |
528 | UNUSED_LOCAL_VARIABLE
529 | Unused local variable.
530 | MAJOR
531 | SINGLE
532 | ]]>
533 |
534 |
535 | UNUSED_METHOD_ARGUMENT
536 | Unused method argument.
537 | MAJOR
538 | SINGLE
539 | ]]>
540 |
541 |
542 | COMPARE_INSTEAD_OF_ASSIGN
543 | Using comparison where assignment was probably meant.
544 | CRITICAL
545 | SINGLE
546 | Comparing instead of Assigning ]]>
547 | bug
548 |
549 |
550 | PARSE_ERROR
551 | Unable to parse
552 | CRITICAL
553 | SINGLE
554 | ]]>
555 | bug
556 |
557 |
558 | SCOPE_ALLCAPS_NAME
559 | Variable scope name is allcaps.
560 | MINOR
561 | SINGLE
562 | Scope variable should not be upper case. ]]>
563 |
564 |
565 | AVOID_USING_CFSETTING_DEBUG
566 | Avoid using showDebugOutput attribute on cfsetting.
567 | CRITICAL
568 | SINGLE
569 | ]]>
570 | security
571 |
572 |
573 | MISSING_SEMI
574 | No semicolon!
575 | CRITICAL
576 | SINGLE
577 | This statement is missing a semicolon! ]]>
578 | bug
579 |
580 |
581 | UNQUOTED_STRUCT_KEY
582 | Unquoted struct key
583 | MAJOR
584 | SINGLE
585 | Unquoted structure keys may or may not maintain their case on output. Quoting is recommended to make sure the case of the key is always the same. ]]>
586 |
587 |
588 | SQL_SELECT_STAR
589 | Star in SQL SELECT
590 | MAJOR
591 | SINGLE
592 | Avoid using SELECT *
in a query. ]]>
593 |
594 |
595 | NEVER_USE_QUERY_IN_CFM
596 | Never use CFQUERY in .cfm files
597 | MINOR
598 | SINGLE
599 | Don't use <cfquery>
in .cfm
files. Database should not be coupled with view. ]]>
600 |
601 |
602 | USE_DISPLAY_NAME
603 | Use displayName instead of name
604 | MINOR
605 | SINGLE
606 | The component has a name
attribute perhaps you meant to use displayName
? ]]>
607 |
608 |
609 | LOCAL_LITERAL_VALUE_USED_TOO_OFTEN
610 | Local literal value used too often
611 | MINOR
612 | SINGLE
613 | The literal occurs several times in the same file. Consider giving it a name and not hard coding values. ]]>
614 |
615 |
616 | GLOBAL_LITERAL_VALUE_USED_TOO_OFTEN
617 | Global literal value used too often
618 | MINOR
619 | SINGLE
620 | The literal occurs several times in one or more files. Consider giving it a name and not hard coding values. ]]>
621 |
622 |
623 | PACKAGE_CASE_MISMATCH
624 | Package name case mismatch
625 | MINOR
626 | SINGLE
627 | The case of the package folder and the object declaration do not match. ]]>
628 |
629 |
630 | PARSE_NOTHING
631 | PARSE NOTHING
632 | CRITICAL
633 | SINGLE
634 | ]]>
635 | bug
636 |
637 |
638 | PLUGIN_ERROR
639 | PLUGIN_ERROR
640 | CRITICAL
641 | SINGLE
642 | ]]>
643 | bug
644 |
645 |
646 | AVOID_EMPTY_FILES
647 | AVOID_EMPTY_FILES
648 | MINOR
649 | SINGLE
650 | ]]>
651 | bug
652 |
653 |
654 | STRUCT_ARRAY_NOTATION
655 | Use array notation
656 | MAJOR
657 | SINGLE
658 | Unquoted struct key variable is not case-sensitive. Using array notation is recommended. ]]>
659 |
660 |
661 |
--------------------------------------------------------------------------------
/src/test/java/com/stepstone/sonar/plugin/coldfusion/ColdfusionPluginTest.java:
--------------------------------------------------------------------------------
1 | package com.stepstone.sonar.plugin.coldfusion;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 | import org.sonar.api.Plugin;
6 | import org.sonar.api.SonarEdition;
7 | import org.sonar.api.SonarQubeSide;
8 | import org.sonar.api.SonarRuntime;
9 | import org.sonar.api.utils.Version;
10 | import org.sonar.api.internal.SonarRuntimeImpl;
11 |
12 |
13 | public class ColdfusionPluginTest {
14 |
15 |
16 | private static final Version VERSION_9_0 = Version.create(9, 0);
17 |
18 | @Test
19 | public void testExtensions() {
20 | ColdFusionPlugin plugin = new ColdFusionPlugin();
21 | SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(VERSION_9_0, SonarQubeSide.SERVER, SonarEdition.COMMUNITY);
22 | Plugin.Context context = new Plugin.Context(runtime);
23 | plugin.define(context);
24 |
25 | Assert.assertEquals(5, context.getExtensions().size());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/com/stepstone/sonar/plugin/coldfusion/ColdfusionSensorTest.java:
--------------------------------------------------------------------------------
1 | package com.stepstone.sonar.plugin.coldfusion;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Rule;
5 | import org.junit.Test;
6 | import org.junit.rules.TemporaryFolder;
7 | import org.sonar.api.SonarEdition;
8 | import org.sonar.api.SonarQubeSide;
9 | import org.sonar.api.batch.fs.InputFile;
10 | import org.sonar.api.batch.fs.internal.DefaultFileSystem;
11 | import org.sonar.api.batch.fs.internal.DefaultInputFile;
12 | import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
13 | import org.sonar.api.batch.sensor.internal.SensorContextTester;
14 | import org.sonar.api.batch.sensor.measure.Measure;
15 | import org.sonar.api.internal.SonarRuntimeImpl;
16 | import org.sonar.api.internal.apachecommons.io.Charsets;
17 | import org.sonar.api.measures.CoreMetrics;
18 | import org.sonar.api.batch.rule.ActiveRules;
19 | import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
20 | import org.sonar.api.utils.Version;
21 | import org.sonar.api.utils.command.CommandExecutor;
22 |
23 | import java.io.File;
24 |
25 | import static org.assertj.core.api.Assertions.assertThat;
26 |
27 | public class ColdfusionSensorTest {
28 |
29 | private ActiveRules rulesProfile = new ActiveRulesBuilder().build();
30 | private File baseDir = new File("src/test/resources").getAbsoluteFile();
31 | private SensorContextTester context = SensorContextTester.create(baseDir);
32 |
33 | @Rule
34 | public TemporaryFolder tmpFolder = new TemporaryFolder();
35 |
36 | @Test
37 | public void testBasicCFMAnalysis() {
38 | DefaultFileSystem fileSystem = new DefaultFileSystem(tmpFolder.getRoot());
39 | fileSystem.setEncoding(Charsets.UTF_8);
40 | fileSystem.setWorkDir(tmpFolder.getRoot().toPath());
41 |
42 | context.setFileSystem(fileSystem);
43 | context.setRuntime(SonarRuntimeImpl.forSonarQube(Version.create(9, 0), SonarQubeSide.SCANNER, SonarEdition.COMMUNITY));
44 |
45 | context.settings().appendProperty("sonar.projectBaseDir", baseDir.getPath());
46 | addFilesToFs();
47 |
48 | CommandExecutor commandExecutor = CommandExecutor.create();
49 | String javaHome = System.getProperty("java.home");
50 | Assert.assertTrue(javaHome!=null && !javaHome.equals(""));
51 |
52 | if(OSValidator.isWindows()) {
53 | context.settings().appendProperty(ColdFusionPlugin.CFLINT_JAVA, javaHome + "/bin/java.exe");
54 | } else {
55 | context.settings().appendProperty(ColdFusionPlugin.CFLINT_JAVA, javaHome + "/bin/java");
56 | }
57 |
58 | ColdFusionSensor sensor = new ColdFusionSensor(context.fileSystem(), rulesProfile);
59 | sensor.execute(context);
60 |
61 | Integer nloc = 0;
62 | Integer comments = 0;
63 | Integer complexity = 0;
64 | for (InputFile o : context.fileSystem().inputFiles()) {
65 | Measure measureNloc = context.measure(o.key(),CoreMetrics.NCLOC.key());
66 | Measure measureComment = context.measure(o.key(),CoreMetrics.COMMENT_LINES.key());
67 | Measure measureComplexity = context.measure(o.key(),CoreMetrics.COMPLEXITY.key());
68 | nloc+=measureNloc.value();
69 | comments+=measureComment.value();
70 | complexity+=measureComplexity.value();
71 | }
72 | assertThat(nloc).isEqualTo(56);
73 | assertThat(comments).isEqualTo(9);
74 | assertThat(complexity).isEqualTo(10);
75 |
76 | }
77 |
78 | private void addFilesToFs() {
79 | DefaultInputFile inputFileMetrics1 = new TestInputFileBuilder(context.module().key(), baseDir.getAbsoluteFile(), new File("src/test/resources/testmetrics1.cfm").getAbsoluteFile()).setLanguage(ColdFusionPlugin.LANGUAGE_KEY).build();
80 | context.fileSystem().add(inputFileMetrics1);
81 | DefaultInputFile inputFileMetrics2 = new TestInputFileBuilder(context.module().key(), baseDir.getAbsoluteFile(), new File("src/test/resources/testmetrics2.cfm").getAbsoluteFile()).setLanguage(ColdFusionPlugin.LANGUAGE_KEY).build();
82 | context.fileSystem().add(inputFileMetrics2);
83 | DefaultInputFile inputFileMetrics3 = new TestInputFileBuilder(context.module().key(), baseDir.getAbsoluteFile(), new File("src/test/resources/EpisodeClaim.cfc").getAbsoluteFile()).setLanguage(ColdFusionPlugin.LANGUAGE_KEY).build();
84 | context.fileSystem().add(inputFileMetrics3);
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/src/test/java/com/stepstone/sonar/plugin/coldfusion/OSValidator.java:
--------------------------------------------------------------------------------
1 | package com.stepstone.sonar.plugin.coldfusion;
2 |
3 | public class OSValidator {
4 |
5 | private static String OS = System.getProperty("os.name").toLowerCase();
6 |
7 | public static boolean isWindows() {
8 | return (OS.contains("win"));
9 | }
10 |
11 | public static boolean isMac() {
12 | return (OS.contains("mac") );
13 | }
14 |
15 | public static boolean isUnix() {
16 | return (OS.contains("nix") || OS.contains("nux") || OS.contains("aix"));
17 | }
18 |
19 | public static boolean isSolaris() {
20 | return (OS.contains("sunos") );
21 | }
22 | public static String getOS(){
23 | if (isWindows()) {
24 | return "win";
25 | } else if (isMac()) {
26 | return "osx";
27 | } else if (isUnix()) {
28 | return "uni";
29 | } else if (isSolaris()) {
30 | return "sol";
31 | } else {
32 | return "err";
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/test/resources/EpisodeClaim.cfc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | if (local.InfusionTherapy is 1)
34 | {
35 | M0250 = M0250 + 14;
36 | }
37 | if (local.ParentalNutrition is 1)
38 | {
39 | M0250 = M0250 + 20;
40 | }
41 | if (local.EnteralNutrition is 1)
42 | {
43 | M0250 = M0250 + 24;
44 | }
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/test/resources/testmetrics1.cfm:
--------------------------------------------------------------------------------
1 |
2 | Hello #firstName#!
3 |
4 | This CFML tutorial was designed for
5 |
6 | you!
7 |
8 |
9 | the world to see.
10 |
11 |
12 |
13 | Nico!
14 |
15 | the world to see.
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/testmetrics2.cfm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 | Hello #firstName#!
7 | This CFML tutorial was designed for
8 |
9 | you!
10 |
11 |
15 |
16 | the world to see.
17 |
18 |
--------------------------------------------------------------------------------