Skip to content

Commit f684952

Browse files
SONARJAVA-5698 Report Eclipse parser type errors (#5261)
1 parent 2214434 commit f684952

6 files changed

Lines changed: 77 additions & 28 deletions

File tree

its/plugin/tests/src/test/java/com/sonar/it/java/JspTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,13 @@ public void should_transpile_jsp() throws Exception {
9696
.matches(patternWithLiteralDot("""
9797
Telemetry java.analysis.generated.success.size_chars: \\d{5}
9898
Telemetry java.analysis.generated.success.time_ms: \\d+
99+
Telemetry java.analysis.generated.success.type_error_count: 0
99100
Telemetry java.analysis.main.success.size_chars: 969
100101
Telemetry java.analysis.main.success.time_ms: \\d+
102+
Telemetry java.analysis.main.success.type_error_count: 0
101103
Telemetry java.analysis.test.success.size_chars: 20
102104
Telemetry java.analysis.test.success.time_ms: \\d+
105+
Telemetry java.analysis.test.success.type_error_count: 0
103106
Telemetry java.dependency.lombok: absent
104107
Telemetry java.dependency.spring-boot: absent
105108
Telemetry java.dependency.spring-web: absent

its/plugin/tests/src/test/java/com/sonar/it/java/suite/JavaTutorialTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ private void executeAndAssertBuild(MavenBuild build, String projectKey) {
7575
.matches(patternWithLiteralDot("""
7676
Telemetry java.analysis.main.success.size_chars: \\d{4}
7777
Telemetry java.analysis.main.success.time_ms: \\d+
78+
Telemetry java.analysis.main.success.type_error_count: 0
7879
Telemetry java.dependency.lombok: absent
7980
Telemetry java.dependency.spring-boot: absent
8081
Telemetry java.dependency.spring-web: 5.3.18

java-frontend/src/main/java/org/sonar/java/ast/JavaAstScanner.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,11 @@ public void simpleScan(InputFile inputFile, JParserConfig.Result result, Consume
168168
modifyCompilationUnit.accept(ast);
169169
visitor.visitFile(ast, sonarComponents != null && sonarComponents.fileCanBeSkipped(inputFile));
170170
String path = inputFile.toString();
171-
collectUndefinedTypes(path, ast.sema.undefinedTypes());
171+
Set<JProblem> undefinedTypes = ast.sema.undefinedTypes();
172+
collectUndefinedTypes(path, undefinedTypes);
172173
cleanUp.accept(ast);
173174
telemetryAnalysisKeys = javaAnalysisKeys.success();
175+
telemetry.aggregateAsCounter(javaAnalysisKeys.success().typeErrorCountKey(), undefinedTypes.size());
174176
} catch (RecognitionException e) {
175177
checkInterrupted(e);
176178
LOG.error(String.format(LOG_ERROR_UNABLE_TO_PARSE_FILE, inputFile));

java-frontend/src/main/java/org/sonar/java/telemetry/TelemetryKey.java

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,21 @@ public enum TelemetryKey {
2525
JAVA_IS_AUTOSCAN("java.is_autoscan"),
2626
JAVA_ANALYSIS_MAIN_SUCCESS_SIZE_CHARS("java.analysis.main.success.size_chars"),
2727
JAVA_ANALYSIS_MAIN_SUCCESS_TIME_MS("java.analysis.main.success.time_ms"),
28+
JAVA_ANALYSIS_MAIN_SUCCESS_TYPE_ERROR_COUNT("java.analysis.main.success.type_error_count"),
2829
JAVA_ANALYSIS_MAIN_PARSE_ERRORS_SIZE_CHARS("java.analysis.main.parse_errors.size_chars"),
2930
JAVA_ANALYSIS_MAIN_PARSE_ERRORS_TIME_MS("java.analysis.main.parse_errors.time_ms"),
3031
JAVA_ANALYSIS_MAIN_EXCEPTIONS_SIZE_CHARS("java.analysis.main.exceptions.size_chars"),
3132
JAVA_ANALYSIS_MAIN_EXCEPTIONS_TIME_MS("java.analysis.main.exceptions.time_ms"),
3233
JAVA_ANALYSIS_TEST_SUCCESS_SIZE_CHARS("java.analysis.test.success.size_chars"),
3334
JAVA_ANALYSIS_TEST_SUCCESS_TIME_MS("java.analysis.test.success.time_ms"),
35+
JAVA_ANALYSIS_TEST_SUCCESS_TYPE_ERROR_COUNT("java.analysis.test.success.type_error_count"),
3436
JAVA_ANALYSIS_TEST_PARSE_ERRORS_SIZE_CHARS("java.analysis.test.parse_errors.size_chars"),
3537
JAVA_ANALYSIS_TEST_PARSE_ERRORS_TIME_MS("java.analysis.test.parse_errors.time_ms"),
3638
JAVA_ANALYSIS_TEST_EXCEPTIONS_SIZE_CHARS("java.analysis.test.exceptions.size_chars"),
3739
JAVA_ANALYSIS_TEST_EXCEPTIONS_TIME_MS("java.analysis.test.exceptions.time_ms"),
3840
JAVA_ANALYSIS_GENERATED_SUCCESS_SIZE_CHARS("java.analysis.generated.success.size_chars"),
3941
JAVA_ANALYSIS_GENERATED_SUCCESS_TIME_MS("java.analysis.generated.success.time_ms"),
42+
JAVA_ANALYSIS_GENERATED_SUCCESS_TYPE_ERROR_COUNT("java.analysis.generated.success.type_error_count"),
4043
JAVA_ANALYSIS_GENERATED_PARSE_ERRORS_SIZE_CHARS("java.analysis.generated.parse_errors.size_chars"),
4144
JAVA_ANALYSIS_GENERATED_PARSE_ERRORS_TIME_MS("java.analysis.generated.parse_errors.time_ms"),
4245
JAVA_ANALYSIS_GENERATED_EXCEPTIONS_SIZE_CHARS("java.analysis.generated.exceptions.size_chars"),
@@ -48,26 +51,38 @@ public enum TelemetryKey {
4851
JAVA_DEPENDENCY_SPRING_BOOT("java.dependency.spring-boot"),
4952
JAVA_DEPENDENCY_SPRING_WEB("java.dependency.spring-web");
5053

51-
public record SpeedKeys(TelemetryKey sizeCharsKey, TelemetryKey timeMsKey) {
54+
public interface SpeedKeys {
55+
TelemetryKey sizeCharsKey();
56+
57+
TelemetryKey timeMsKey();
58+
}
59+
60+
public record SizeAndTimeKeys(TelemetryKey sizeCharsKey, TelemetryKey timeMsKey) implements SpeedKeys {
61+
}
62+
63+
public record SizeTimeAndTypeErrorKeys(TelemetryKey sizeCharsKey, TelemetryKey timeMsKey, TelemetryKey typeErrorCountKey) implements SpeedKeys {
5264
}
5365

54-
public record JavaAnalysisKeys(SpeedKeys success, SpeedKeys parseErrors, SpeedKeys exceptions) {
66+
public record JavaAnalysisKeys(SizeTimeAndTypeErrorKeys success, SpeedKeys parseErrors, SpeedKeys exceptions) {
5567
}
5668

5769
public static final JavaAnalysisKeys JAVA_ANALYSIS_MAIN = new JavaAnalysisKeys(
58-
new SpeedKeys(JAVA_ANALYSIS_MAIN_SUCCESS_SIZE_CHARS, JAVA_ANALYSIS_MAIN_SUCCESS_TIME_MS),
59-
new SpeedKeys(JAVA_ANALYSIS_MAIN_PARSE_ERRORS_SIZE_CHARS, JAVA_ANALYSIS_MAIN_PARSE_ERRORS_TIME_MS),
60-
new SpeedKeys(JAVA_ANALYSIS_MAIN_EXCEPTIONS_SIZE_CHARS, JAVA_ANALYSIS_MAIN_EXCEPTIONS_TIME_MS));
70+
new SizeTimeAndTypeErrorKeys(JAVA_ANALYSIS_MAIN_SUCCESS_SIZE_CHARS, JAVA_ANALYSIS_MAIN_SUCCESS_TIME_MS,
71+
JAVA_ANALYSIS_MAIN_SUCCESS_TYPE_ERROR_COUNT),
72+
new SizeAndTimeKeys(JAVA_ANALYSIS_MAIN_PARSE_ERRORS_SIZE_CHARS, JAVA_ANALYSIS_MAIN_PARSE_ERRORS_TIME_MS),
73+
new SizeAndTimeKeys(JAVA_ANALYSIS_MAIN_EXCEPTIONS_SIZE_CHARS, JAVA_ANALYSIS_MAIN_EXCEPTIONS_TIME_MS));
6174

6275
public static final JavaAnalysisKeys JAVA_ANALYSIS_TEST = new JavaAnalysisKeys(
63-
new SpeedKeys(JAVA_ANALYSIS_TEST_SUCCESS_SIZE_CHARS, JAVA_ANALYSIS_TEST_SUCCESS_TIME_MS),
64-
new SpeedKeys(JAVA_ANALYSIS_TEST_PARSE_ERRORS_SIZE_CHARS, JAVA_ANALYSIS_TEST_PARSE_ERRORS_TIME_MS),
65-
new SpeedKeys(JAVA_ANALYSIS_TEST_EXCEPTIONS_SIZE_CHARS, JAVA_ANALYSIS_TEST_EXCEPTIONS_TIME_MS));
76+
new SizeTimeAndTypeErrorKeys(JAVA_ANALYSIS_TEST_SUCCESS_SIZE_CHARS, JAVA_ANALYSIS_TEST_SUCCESS_TIME_MS,
77+
JAVA_ANALYSIS_TEST_SUCCESS_TYPE_ERROR_COUNT),
78+
new SizeAndTimeKeys(JAVA_ANALYSIS_TEST_PARSE_ERRORS_SIZE_CHARS, JAVA_ANALYSIS_TEST_PARSE_ERRORS_TIME_MS),
79+
new SizeAndTimeKeys(JAVA_ANALYSIS_TEST_EXCEPTIONS_SIZE_CHARS, JAVA_ANALYSIS_TEST_EXCEPTIONS_TIME_MS));
6680

6781
public static final JavaAnalysisKeys JAVA_ANALYSIS_GENERATED = new JavaAnalysisKeys(
68-
new SpeedKeys(JAVA_ANALYSIS_GENERATED_SUCCESS_SIZE_CHARS, JAVA_ANALYSIS_GENERATED_SUCCESS_TIME_MS),
69-
new SpeedKeys(JAVA_ANALYSIS_GENERATED_PARSE_ERRORS_SIZE_CHARS, JAVA_ANALYSIS_GENERATED_PARSE_ERRORS_TIME_MS),
70-
new SpeedKeys(JAVA_ANALYSIS_GENERATED_EXCEPTIONS_SIZE_CHARS, JAVA_ANALYSIS_GENERATED_EXCEPTIONS_TIME_MS));
82+
new SizeTimeAndTypeErrorKeys(JAVA_ANALYSIS_GENERATED_SUCCESS_SIZE_CHARS, JAVA_ANALYSIS_GENERATED_SUCCESS_TIME_MS,
83+
JAVA_ANALYSIS_GENERATED_SUCCESS_TYPE_ERROR_COUNT),
84+
new SizeAndTimeKeys(JAVA_ANALYSIS_GENERATED_PARSE_ERRORS_SIZE_CHARS, JAVA_ANALYSIS_GENERATED_PARSE_ERRORS_TIME_MS),
85+
new SizeAndTimeKeys(JAVA_ANALYSIS_GENERATED_EXCEPTIONS_SIZE_CHARS, JAVA_ANALYSIS_GENERATED_EXCEPTIONS_TIME_MS));
7186

7287
private final String key;
7388

java-frontend/src/test/java/org/sonar/java/telemetry/TelemetryKeyTest.java

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.sonar.java.telemetry;
1818

1919
import java.util.List;
20+
import java.util.Locale;
2021
import java.util.Map;
2122
import java.util.function.Function;
2223
import org.junit.jupiter.api.Test;
@@ -31,24 +32,33 @@
3132
class TelemetryKeyTest {
3233

3334
@Test
34-
void testKey() {
35-
assertThat(TelemetryKey.JAVA_LANGUAGE_VERSION.key()).isEqualTo("java.language.version");
35+
void test_TelemetryKey_names() {
36+
for (TelemetryKey enumEntry : TelemetryKey.values()) {
37+
assertThat(enumEntry.name()).isEqualTo(enumNameFromTelemetryName(enumEntry.key()));
38+
}
3639
}
3740

3841
@Test
3942
void testCompoundKeys() {
4043
for (String artifact : List.of("main.", "test.", "generated.")) {
4144
for (String result : List.of("success.", "parse_errors.", "exceptions.")) {
4245
for (String metric : List.of("size_chars", "time_ms")) {
43-
String telemetryName = "java.analysis." + artifact + result + metric;
44-
String javaName = telemetryName.toUpperCase().replace(".", "_");
45-
TelemetryKey key = TelemetryKey.valueOf(javaName);
46-
assertThat(key.key()).isEqualTo(telemetryName);
46+
assertTelemetryNameExists("java.analysis." + artifact + result + metric);
4747
}
4848
}
49+
assertTelemetryNameExists("java.analysis." + artifact + "success.type_error_count");
4950
}
5051
}
5152

53+
private static String enumNameFromTelemetryName(String telemetryName) {
54+
return telemetryName.toUpperCase(Locale.ROOT).replaceAll("[.\\-]", "_");
55+
}
56+
57+
private static void assertTelemetryNameExists(String telemetryName) {
58+
TelemetryKey enumEntry = TelemetryKey.valueOf(enumNameFromTelemetryName(telemetryName));
59+
assertThat(enumEntry.key()).isEqualTo(telemetryName);
60+
}
61+
5262
@Test
5363
void testAnalysisKeys() {
5464
Map<String, JavaAnalysisKeys> artifacts = Map.of(
@@ -61,17 +71,21 @@ void testAnalysisKeys() {
6171
"parse_errors.", JavaAnalysisKeys::parseErrors,
6272
"exceptions.", JavaAnalysisKeys::exceptions
6373
);
64-
Map<String, Function<SpeedKeys,TelemetryKey>> metrics = Map.of(
74+
Map<String, Function<SpeedKeys, TelemetryKey>> metrics = Map.of(
6575
"size_chars", SpeedKeys::sizeCharsKey,
6676
"time_ms", SpeedKeys::timeMsKey
6777
);
68-
artifacts.forEach((artifactName, artifact) -> results.forEach(
69-
(resultName, result) -> metrics.forEach((
70-
metricName, metric) -> {
71-
String telemetryName = artifactName + resultName + metricName;
72-
TelemetryKey tk = metric.apply(result.apply(artifact));
73-
assertThat(tk.key()).isEqualTo(telemetryName);
74-
})));
78+
artifacts.forEach((artifactName, artifact) -> {
79+
String typeErrorName = artifactName + "success.type_error_count";
80+
assertThat(artifact.success().typeErrorCountKey().key()).isEqualTo(typeErrorName);
81+
results.forEach(
82+
(resultName, result) -> metrics.forEach((
83+
metricName, metric) -> {
84+
String telemetryName = artifactName + resultName + metricName;
85+
TelemetryKey tk = metric.apply(result.apply(artifact));
86+
assertThat(tk.key()).isEqualTo(telemetryName);
87+
}));
88+
});
7589
}
7690

7791
}

sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaSensorTest.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.slf4j.event.Level;
3434
import org.sonar.api.SonarEdition;
3535
import org.sonar.api.SonarQubeSide;
36+
import org.sonar.api.batch.fs.FileSystem;
3637
import org.sonar.api.batch.fs.InputFile;
3738
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
3839
import org.sonar.api.batch.fs.internal.DefaultInputFile;
@@ -123,6 +124,7 @@ void test_issues_creation_on_main_file() throws IOException {
123124
assertThat(telemetryMap).containsOnlyKeys(
124125
"java.analysis.main.success.size_chars",
125126
"java.analysis.main.success.time_ms",
127+
"java.analysis.main.success.type_error_count",
126128
"java.dependency.lombok",
127129
"java.dependency.spring-boot",
128130
"java.dependency.spring-web",
@@ -132,16 +134,19 @@ void test_issues_creation_on_main_file() throws IOException {
132134
"java.scanner_app");
133135
assertThat(telemetryMap.get("java.analysis.main.success.size_chars")).matches("\\d{5}");
134136
assertThat(telemetryMap.get("java.analysis.main.success.time_ms")).matches("\\d+");
137+
assertThat(telemetryMap).containsEntry("java.analysis.main.success.type_error_count", "199");
135138
}
136139

137140
@Test
141+
// Renaming this method will break lineNumberOfTheMethodWithNoSonar(fs). The name is used to locate the line number.
138142
void test_issues_creation_on_test_file() throws IOException { // NOSONAR required to test NOSONAR reporting on test files
139143
testIssueCreation(InputFile.Type.TEST, 0);
140144

141145
Map<String, String> telemetryMap = telemetry.toMap();
142146
assertThat(telemetryMap).containsOnlyKeys(
143147
"java.analysis.test.success.size_chars",
144148
"java.analysis.test.success.time_ms",
149+
"java.analysis.test.success.type_error_count",
145150
"java.dependency.lombok",
146151
"java.dependency.spring-boot",
147152
"java.dependency.spring-web",
@@ -151,6 +156,15 @@ void test_issues_creation_on_test_file() throws IOException { // NOSONAR require
151156
"java.scanner_app");
152157
assertThat(telemetryMap.get("java.analysis.test.success.size_chars")).matches("\\d{5}");
153158
assertThat(telemetryMap.get("java.analysis.test.success.time_ms")).matches("\\d+");
159+
assertThat(telemetryMap).containsEntry("java.analysis.test.success.type_error_count", "199");
160+
}
161+
162+
private static int lineNumberOfTheMethodWithNoSonar(FileSystem fs) throws IOException {
163+
String[] lines = fs.inputFile(fs.predicates().hasPath("org/sonar/plugins/java/JavaSensorTest.java")).contents().split("\n");
164+
int zeroBasedLineIndex = (int) Stream.of(lines)
165+
.takeWhile(line -> !line.contains("test_issues_creation_on_test_file"))
166+
.count();
167+
return zeroBasedLineIndex + 1;
154168
}
155169

156170
private void testIssueCreation(InputFile.Type onType, int expectedIssues) throws IOException {
@@ -169,8 +183,8 @@ private void testIssueCreation(InputFile.Type onType, int expectedIssues) throws
169183
JavaSensor jss = new JavaSensor(sonarComponents, fs, javaResourceLocator, settings.asConfig(), noSonarFilter, null, telemetry);
170184

171185
jss.execute(context);
172-
// argument 138 refers to the comment on line #138 in this file, each time this file changes, this argument should be updated
173-
verify(noSonarFilter, times(1)).noSonarInFile(fs.inputFiles().iterator().next(), Collections.singleton(138));
186+
int expectedNoSonarLine = lineNumberOfTheMethodWithNoSonar(fs);
187+
verify(noSonarFilter, times(1)).noSonarInFile(fs.inputFiles().iterator().next(), Collections.singleton(expectedNoSonarLine));
174188
verify(sonarComponents, times(expectedIssues)).reportIssue(any(AnalyzerMessage.class));
175189

176190
// There are additional entries, but we do not test them.

0 commit comments

Comments
 (0)