Skip to content

Commit 70ae02d

Browse files
author
Aurélien Baudet
committed
[FEATURE] Add TypeScript code quality analysis
1 parent a2c1718 commit 70ae02d

File tree

89 files changed

+3829
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+3829
-0
lines changed

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<module>sonar-web-frontend-angular-eslint</module>
4848
<module>sonar-duplication-cpd</module>
4949
<module>sonar-duplication-simian</module>
50+
<module>sonar-web-frontend-typescript</module>
5051
<module>sonar-web-frontend-plugin</module>
5152
</modules>
5253

sonar-web-frontend-plugin/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@
4545
<artifactId>sonar-web-frontend-angular-eslint</artifactId>
4646
<version>${project.version}</version>
4747
</dependency>
48+
<dependency>
49+
<groupId>fr.sii.sonar</groupId>
50+
<artifactId>sonar-web-frontend-typescript</artifactId>
51+
<version>${project.version}</version>
52+
</dependency>
4853
</dependencies>
4954

5055
<build>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
/target/*
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<parent>
6+
<groupId>fr.sii.sonar</groupId>
7+
<artifactId>sonar-sii-plugin-parent</artifactId>
8+
<version>2.0.1-SNAPSHOT</version>
9+
</parent>
10+
11+
<artifactId>sonar-web-frontend-typescript</artifactId>
12+
<packaging>sonar-plugin</packaging>
13+
14+
<name>SII web frontend plugin :: TypeScript</name>
15+
<description>Consume reports generated by tslint for code quality. Also consume reports for code duplication (either simian or cpd). Consumes the unit/integration tests reports (generated by Jasmin) coverage report (lcov generated by Istanbul). The information generated by reports are added in Sonar</description>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>fr.sii.sonar</groupId>
20+
<artifactId>sonar-report-core</artifactId>
21+
<version>${project.version}</version>
22+
</dependency>
23+
<dependency>
24+
<groupId>fr.sii.sonar</groupId>
25+
<artifactId>sonar-coverage-lcov</artifactId>
26+
<version>${project.version}</version>
27+
</dependency>
28+
<dependency>
29+
<groupId>fr.sii.sonar</groupId>
30+
<artifactId>sonar-test-junit</artifactId>
31+
<version>${project.version}</version>
32+
</dependency>
33+
<dependency>
34+
<groupId>fr.sii.sonar</groupId>
35+
<artifactId>sonar-duplication-cpd</artifactId>
36+
<version>${project.version}</version>
37+
</dependency>
38+
<dependency>
39+
<groupId>fr.sii.sonar</groupId>
40+
<artifactId>sonar-duplication-simian</artifactId>
41+
<version>${project.version}</version>
42+
</dependency>
43+
</dependencies>
44+
45+
<build>
46+
<plugins>
47+
<plugin>
48+
<groupId>org.codehaus.sonar</groupId>
49+
<artifactId>sonar-packaging-maven-plugin</artifactId>
50+
<version>${sonar.plugin.version}</version>
51+
<extensions>true</extensions>
52+
<configuration>
53+
<pluginClass>fr.sii.sonar.web.frontend.typescript.TypeScriptPlugin</pluginClass>
54+
</configuration>
55+
</plugin>
56+
</plugins>
57+
</build>
58+
59+
</project>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package fr.sii.sonar.web.frontend.typescript;
2+
3+
import org.sonar.api.config.Settings;
4+
5+
import fr.sii.sonar.report.core.common.language.ConfigurableLanguage;
6+
7+
public class TypeScript extends ConfigurableLanguage {
8+
9+
public TypeScript(Settings settings) {
10+
super(settings, TypeScriptLanguageConstants.LANGUAGE_KEY, TypeScriptLanguageConstants.FILE_SUFFIXES_KEY, TypeScriptLanguageConstants.FILE_SUFFIXES_DEFVALUE, "TS");
11+
}
12+
13+
14+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package fr.sii.sonar.web.frontend.typescript;
2+
3+
import fr.sii.sonar.report.core.common.ReportConstants;
4+
import fr.sii.sonar.report.core.common.language.LanguageConstants;
5+
6+
public abstract class TypeScriptLanguageConstants implements ReportConstants, LanguageConstants {
7+
public static final String FILE_SUFFIXES_KEY = "sonar.sii.ts.suffixes";
8+
public static final String FILE_SUFFIXES_DEFVALUE = ".ts";
9+
public static final String LANGUAGE_KEY = "ts";
10+
public static final String CATEGORY = "TypeScript";
11+
public static final String SUB_CATEGORY = "General";
12+
13+
public String getLanguageKey() {
14+
return LANGUAGE_KEY;
15+
}
16+
}
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
package fr.sii.sonar.web.frontend.typescript;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
6+
import org.sonar.api.SonarPlugin;
7+
import org.sonar.api.config.PropertyDefinition;
8+
import org.sonar.api.resources.Qualifiers;
9+
10+
import fr.sii.sonar.report.core.common.PluginDependencies;
11+
import fr.sii.sonar.web.frontend.typescript.coverage.LcovIntegrationCoverageConstants;
12+
import fr.sii.sonar.web.frontend.typescript.coverage.LcovIntegrationCoverageSensor;
13+
import fr.sii.sonar.web.frontend.typescript.coverage.LcovOverallCoverageConstants;
14+
import fr.sii.sonar.web.frontend.typescript.coverage.LcovOverallCoverageSensor;
15+
import fr.sii.sonar.web.frontend.typescript.coverage.LcovUnitCoverageConstants;
16+
import fr.sii.sonar.web.frontend.typescript.coverage.LcovUnitCoverageSensor;
17+
import fr.sii.sonar.web.frontend.typescript.duplication.TypeScriptDuplicationConstants;
18+
import fr.sii.sonar.web.frontend.typescript.duplication.TypeScriptDuplicationSensor;
19+
import fr.sii.sonar.web.frontend.typescript.quality.TslintQualityConstants;
20+
import fr.sii.sonar.web.frontend.typescript.quality.TslintQualitySensor;
21+
import fr.sii.sonar.web.frontend.typescript.quality.TslintProfileDefinition;
22+
import fr.sii.sonar.web.frontend.typescript.quality.TslintRulesDefinition;
23+
import fr.sii.sonar.web.frontend.typescript.test.JUnitConstants;
24+
import fr.sii.sonar.web.frontend.typescript.test.JUnitIntegrationConstants;
25+
import fr.sii.sonar.web.frontend.typescript.test.JUnitIntegrationReportSensor;
26+
import fr.sii.sonar.web.frontend.typescript.test.JUnitReportSensor;
27+
28+
/**
29+
* This class is the entry point for all extensions
30+
*/
31+
public final class TypeScriptPlugin extends SonarPlugin {
32+
33+
34+
// This is where you're going to declare all your Sonar extensions
35+
@SuppressWarnings({ "rawtypes" })
36+
public List getExtensions() {
37+
return Arrays.asList(
38+
// needed here for standalone version
39+
PluginDependencies.class,
40+
41+
// general configuration
42+
PropertyDefinition.builder(TypeScriptLanguageConstants.FILE_SUFFIXES_KEY)
43+
.defaultValue(TypeScriptLanguageConstants.FILE_SUFFIXES_DEFVALUE)
44+
.category(TypeScriptLanguageConstants.CATEGORY)
45+
.subCategory(TypeScriptLanguageConstants.SUB_CATEGORY)
46+
.name("File suffixes for TypeScript files")
47+
.description("Comma-separated list of suffixes for files to analyze.")
48+
.onQualifiers(Qualifiers.PROJECT)
49+
.build(),
50+
51+
TypeScript.class,
52+
53+
// Quality configuration
54+
PropertyDefinition.builder(TslintQualityConstants.REPORT_PATH_KEY)
55+
.defaultValue(TslintQualityConstants.REPORT_PATH_DEFVALUE)
56+
.category(TslintQualityConstants.CATEGORY)
57+
.subCategory(TslintQualityConstants.SUB_CATEGORY)
58+
.name("TypeScript quality report path")
59+
.description("The path to the TypeScript report file to load")
60+
.onQualifiers(Qualifiers.PROJECT)
61+
.build(),
62+
PropertyDefinition.builder(TslintQualityConstants.FAIL_MISSING_FILE_KEY)
63+
.defaultValue(TslintQualityConstants.FAIL_MISSING_FILE_DEFVALUE)
64+
.category(TslintQualityConstants.CATEGORY)
65+
.subCategory(TslintQualityConstants.SUB_CATEGORY)
66+
.name("Fail on missing source file")
67+
.description("True to stop analysis if a source file is not found")
68+
.onQualifiers(Qualifiers.PROJECT)
69+
.build(),
70+
PropertyDefinition.builder(TslintQualityConstants.SKIP_FILE_METRICS_KEY)
71+
.defaultValue(TslintQualityConstants.SKIP_FILE_METRICS_DEFVALUE)
72+
.category(TslintQualityConstants.CATEGORY)
73+
.subCategory(TslintQualityConstants.SUB_CATEGORY)
74+
.name("Skip save of file metrics")
75+
.description("If you have several plugins that are able to handle TypeScript, you may have an error (Can not add the same measure twice). Set it to true to let the other plugin save the metrics")
76+
.onQualifiers(Qualifiers.PROJECT)
77+
.build(),
78+
79+
TslintQualityConstants.class,
80+
TslintRulesDefinition.class,
81+
TslintProfileDefinition.class,
82+
TslintQualitySensor.class,
83+
84+
// Unit coverage configuration
85+
PropertyDefinition.builder(LcovUnitCoverageConstants.REPORT_PATH_KEY)
86+
.defaultValue(LcovUnitCoverageConstants.REPORT_PATH_DEFVALUE)
87+
.category(LcovUnitCoverageConstants.CATEGORY)
88+
.subCategory(LcovUnitCoverageConstants.SUB_CATEGORY)
89+
.name("TypeScript unit tests coverage report path")
90+
.description("The path to the TypeScript report file to load for unit tests coverage")
91+
.onQualifiers(Qualifiers.PROJECT)
92+
.build(),
93+
PropertyDefinition.builder(LcovUnitCoverageConstants.FAIL_MISSING_FILE_KEY)
94+
.defaultValue(LcovUnitCoverageConstants.FAIL_MISSING_FILE_DEFVALUE)
95+
.category(LcovUnitCoverageConstants.CATEGORY)
96+
.subCategory(LcovUnitCoverageConstants.SUB_CATEGORY)
97+
.name("Fail on missing source file")
98+
.description("True to stop analysis if a source file is not found")
99+
.onQualifiers(Qualifiers.PROJECT)
100+
.build()
101+
102+
// LcovUnitCoverageConstants.class,
103+
// LcovUnitCoverageSensor.class,
104+
//
105+
// // Integration coverage configuration
106+
// PropertyDefinition.builder(LcovIntegrationCoverageConstants.REPORT_PATH_KEY)
107+
// .defaultValue(LcovIntegrationCoverageConstants.REPORT_PATH_DEFVALUE)
108+
// .category(LcovIntegrationCoverageConstants.CATEGORY)
109+
// .subCategory(LcovIntegrationCoverageConstants.SUB_CATEGORY)
110+
// .name("TypeScript integration tests coverage report path")
111+
// .description("The path to the TypeScript report file to load for integration tests coverage")
112+
// .onQualifiers(Qualifiers.PROJECT)
113+
// .build(),
114+
// PropertyDefinition.builder(LcovIntegrationCoverageConstants.FAIL_MISSING_FILE_KEY)
115+
// .defaultValue(LcovIntegrationCoverageConstants.FAIL_MISSING_FILE_DEFVALUE)
116+
// .category(LcovIntegrationCoverageConstants.CATEGORY)
117+
// .subCategory(LcovIntegrationCoverageConstants.SUB_CATEGORY)
118+
// .name("Fail on missing source file")
119+
// .description("True to stop analysis if a source file is not found")
120+
// .onQualifiers(Qualifiers.PROJECT)
121+
// .build(),
122+
//
123+
// LcovIntegrationCoverageConstants.class,
124+
// LcovIntegrationCoverageSensor.class,
125+
//
126+
// // Overall coverage configuration
127+
// PropertyDefinition.builder(LcovOverallCoverageConstants.REPORT_PATH_KEY)
128+
// .defaultValue(LcovOverallCoverageConstants.REPORT_PATH_DEFVALUE)
129+
// .category(LcovOverallCoverageConstants.CATEGORY)
130+
// .subCategory(LcovOverallCoverageConstants.SUB_CATEGORY)
131+
// .name("TypeScript overall tests coverage report path")
132+
// .description("The path to the TypeScript report file to load for overall tests coverage")
133+
// .onQualifiers(Qualifiers.PROJECT)
134+
// .build(),
135+
// PropertyDefinition.builder(LcovOverallCoverageConstants.FAIL_MISSING_FILE_KEY)
136+
// .defaultValue(LcovOverallCoverageConstants.FAIL_MISSING_FILE_DEFVALUE)
137+
// .category(LcovOverallCoverageConstants.CATEGORY)
138+
// .subCategory(LcovOverallCoverageConstants.SUB_CATEGORY)
139+
// .name("Fail on missing source file")
140+
// .description("True to stop analysis if a source file is not found")
141+
// .onQualifiers(Qualifiers.PROJECT)
142+
// .build(),
143+
//
144+
// LcovOverallCoverageConstants.class,
145+
// LcovOverallCoverageSensor.class,
146+
//
147+
// // Unit testing configuration
148+
// PropertyDefinition.builder(JUnitConstants.REPORT_PATH_KEY)
149+
// .defaultValue(JUnitConstants.REPORT_PATH_DEFVALUE)
150+
// .category(JUnitConstants.CATEGORY)
151+
// .subCategory(JUnitConstants.SUB_CATEGORY)
152+
// .name("TypeScript junit unit test report path")
153+
// .description("The path to the TypeScript report file to load")
154+
// .onQualifiers(Qualifiers.PROJECT)
155+
// .build(),
156+
// PropertyDefinition.builder(JUnitConstants.FAIL_MISSING_FILE_KEY)
157+
// .defaultValue(JUnitConstants.FAIL_MISSING_FILE_DEFVALUE)
158+
// .category(JUnitConstants.CATEGORY)
159+
// .subCategory(JUnitConstants.SUB_CATEGORY)
160+
// .name("Fail on missing test file")
161+
// .description("True to stop analysis if a test file is not found")
162+
// .onQualifiers(Qualifiers.PROJECT)
163+
// .build(),
164+
//
165+
// JUnitConstants.class,
166+
// JUnitReportSensor.class,
167+
//
168+
// // Integration testing configuration
169+
// PropertyDefinition.builder(JUnitIntegrationConstants.REPORT_PATH_KEY)
170+
// .defaultValue(JUnitIntegrationConstants.REPORT_PATH_DEFVALUE)
171+
// .category(JUnitIntegrationConstants.CATEGORY)
172+
// .subCategory(JUnitIntegrationConstants.SUB_CATEGORY)
173+
// .name("TypeScript junit integration test report path")
174+
// .description("The path to the TypeScript report file to load")
175+
// .onQualifiers(Qualifiers.PROJECT)
176+
// .build(),
177+
// PropertyDefinition.builder(JUnitIntegrationConstants.FAIL_MISSING_FILE_KEY)
178+
// .defaultValue(JUnitIntegrationConstants.FAIL_MISSING_FILE_DEFVALUE)
179+
// .category(JUnitIntegrationConstants.CATEGORY)
180+
// .subCategory(JUnitIntegrationConstants.SUB_CATEGORY)
181+
// .name("Fail on missing test file")
182+
// .description("True to stop analysis if a test file is not found")
183+
// .onQualifiers(Qualifiers.PROJECT)
184+
// .build(),
185+
//
186+
// JUnitIntegrationConstants.class,
187+
// JUnitIntegrationReportSensor.class,
188+
//
189+
// // Duplication configuration
190+
// PropertyDefinition.builder(TypeScriptDuplicationConstants.REPORT_PATH_KEY)
191+
// .defaultValue(TypeScriptDuplicationConstants.REPORT_PATH_DEFVALUE)
192+
// .category(TypeScriptDuplicationConstants.CATEGORY)
193+
// .subCategory(TypeScriptDuplicationConstants.SUB_CATEGORY)
194+
// .name("TypeScript duplication report path")
195+
// .description("The path to the TypeScript report file to load")
196+
// .onQualifiers(Qualifiers.PROJECT)
197+
// .build(),
198+
// PropertyDefinition.builder(TypeScriptDuplicationConstants.FAIL_MISSING_FILE_KEY)
199+
// .defaultValue(TypeScriptDuplicationConstants.FAIL_MISSING_FILE_DEFVALUE)
200+
// .category(TypeScriptDuplicationConstants.CATEGORY)
201+
// .subCategory(TypeScriptDuplicationConstants.SUB_CATEGORY)
202+
// .name("Fail on missing source file")
203+
// .description("True to stop analysis if a source file is not found")
204+
// .onQualifiers(Qualifiers.PROJECT)
205+
// .build(),
206+
// PropertyDefinition.builder(TypeScriptDuplicationConstants.SKIP_DUPLICATION_KEY)
207+
// .defaultValue(TypeScriptDuplicationConstants.SKIP_DUPLICATION_DEFVAL)
208+
// .category(TypeScriptDuplicationConstants.CATEGORY)
209+
// .subCategory(TypeScriptDuplicationConstants.SUB_CATEGORY)
210+
// .name("Skip duplication analysis")
211+
// .description("True to skip code duplication analysis done by this plugin")
212+
// .onQualifiers(Qualifiers.PROJECT)
213+
// .build(),
214+
//
215+
// TypeScriptDuplicationConstants.class,
216+
// TypeScriptDuplicationSensor.class
217+
);
218+
}
219+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package fr.sii.sonar.web.frontend.typescript.coverage;
2+
3+
import fr.sii.sonar.report.core.common.ReportConstants;
4+
import fr.sii.sonar.report.core.coverage.CoverageConstants;
5+
import fr.sii.sonar.web.frontend.typescript.TypeScriptLanguageConstants;
6+
7+
public class LcovIntegrationCoverageConstants extends TypeScriptLanguageConstants implements ReportConstants, CoverageConstants {
8+
public static final String REPORT_PATH_KEY = "sonar.sii.coverage.it.ts.report.path";
9+
public static final String FAIL_MISSING_FILE_KEY = "sonar.sii.coverage.it.ts.file.missing.fail";
10+
public static final String REPORT_PATH_DEFVALUE = "/reports/sonar/ts-it.lcov";
11+
public static final String FAIL_MISSING_FILE_DEFVALUE = "true";
12+
public static final String SUB_CATEGORY = "Coverage";
13+
14+
public String getReportPathKey() {
15+
return REPORT_PATH_KEY;
16+
}
17+
18+
public String getMissingFileFailKey() {
19+
return FAIL_MISSING_FILE_KEY;
20+
}
21+
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package fr.sii.sonar.web.frontend.typescript.coverage;
2+
3+
import fr.sii.sonar.coverage.lcov.factory.LcovProviderFactory;
4+
import fr.sii.sonar.report.core.common.PluginDependencies;
5+
import fr.sii.sonar.report.core.common.ReportSensor;
6+
import fr.sii.sonar.report.core.coverage.domain.CoverageReport;
7+
import fr.sii.sonar.report.core.coverage.factory.IntegrationCoverageSaverFactory;
8+
9+
/**
10+
* Sensor specific to TypeScript code coverage for integration tests that loads LCOV report
11+
*
12+
* @author Aurélien Baudet
13+
*
14+
*/
15+
public class LcovIntegrationCoverageSensor extends ReportSensor<CoverageReport> {
16+
17+
public LcovIntegrationCoverageSensor(LcovIntegrationCoverageConstants constants, PluginDependencies pluginDependencies) {
18+
super(constants, pluginDependencies, new LcovProviderFactory(), new IntegrationCoverageSaverFactory());
19+
}
20+
21+
}

0 commit comments

Comments
 (0)