diff --git a/java-frontend/src/main/java/org/sonar/java/JavaFrontend.java b/java-frontend/src/main/java/org/sonar/java/JavaFrontend.java index 1a5623c3227..5063ef5c138 100644 --- a/java-frontend/src/main/java/org/sonar/java/JavaFrontend.java +++ b/java-frontend/src/main/java/org/sonar/java/JavaFrontend.java @@ -32,6 +32,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; +import java.util.stream.StreamSupport; import javax.annotation.Nullable; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.utils.log.Logger; @@ -142,10 +143,7 @@ public void scan(Iterable sourceFiles, Iterable testFiles, successfullyScanned += testFilesScannedWithoutParsing.get(true).size(); total += testFilesScannedWithoutParsing.get(true).size() + testFilesScannedWithoutParsing.get(false).size(); - Map> generatedFilesScannedWithoutParsing = astScannerForGeneratedFiles.scanWithoutParsing(generatedFiles); - generatedFiles = generatedFilesScannedWithoutParsing.get(false); - successfullyScanned += generatedFilesScannedWithoutParsing.get(true).size(); - total += generatedFilesScannedWithoutParsing.get(true).size() + generatedFilesScannedWithoutParsing.get(false).size(); + total += StreamSupport.stream(generatedFiles.spliterator(), false).count(); LOG.info( "Server-side caching is enabled. The Java analyzer was able to leverage cached data from previous analyses for {} out of {} files. These files will not be parsed.", diff --git a/java-frontend/src/main/java/org/sonar/java/SonarComponents.java b/java-frontend/src/main/java/org/sonar/java/SonarComponents.java index 6dd0ad39b0e..cf06f9a2462 100644 --- a/java-frontend/src/main/java/org/sonar/java/SonarComponents.java +++ b/java-frontend/src/main/java/org/sonar/java/SonarComponents.java @@ -64,6 +64,7 @@ import org.sonar.java.classpath.ClasspathForMain; import org.sonar.java.classpath.ClasspathForTest; import org.sonar.java.exceptions.ApiMismatchException; +import org.sonar.java.model.GeneratedFile; import org.sonar.java.model.JProblem; import org.sonar.java.model.LineUtils; import org.sonar.java.reporting.AnalyzerMessage; @@ -451,6 +452,10 @@ public boolean canSkipUnchangedFiles() throws ApiMismatchException { public boolean fileCanBeSkipped(InputFile inputFile) { + if (inputFile instanceof GeneratedFile) { + // Generated files should not be skipped as we cannot assess the change status of the source file + return false; + } boolean canSkipInContext; try { canSkipInContext = canSkipUnchangedFiles(); diff --git a/java-frontend/src/test/java/org/sonar/java/SonarComponentsTest.java b/java-frontend/src/test/java/org/sonar/java/SonarComponentsTest.java index 7cab2d707f8..f47c9d372c8 100644 --- a/java-frontend/src/test/java/org/sonar/java/SonarComponentsTest.java +++ b/java-frontend/src/test/java/org/sonar/java/SonarComponentsTest.java @@ -23,6 +23,7 @@ import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; @@ -77,6 +78,7 @@ import org.sonar.java.classpath.ClasspathForMain; import org.sonar.java.classpath.ClasspathForTest; import org.sonar.java.exceptions.ApiMismatchException; +import org.sonar.java.model.GeneratedFile; import org.sonar.java.model.JParserTestUtils; import org.sonar.java.model.JavaTree; import org.sonar.java.reporting.AnalyzerMessage; @@ -714,6 +716,23 @@ void skipUnchangedFiles_throws_a_NoSuchMethodError_when_canSkipUnchangedFiles_no assertThat(error).hasCause(new NoSuchMethodError("API version mismatch :-(")); } + @Test + void fileCanBeSkipped_returns_false_when_the_file_is_a_generated_file() throws ApiMismatchException { + SensorContextTester sensorContextTester = SensorContextTester.create(new File("")); + SonarComponents sonarComponents = spy( + new SonarComponents( + fileLinesContextFactory, + sensorContextTester.fileSystem(), + mock(ClasspathForMain.class), + mock(ClasspathForTest.class), + checkFactory + ) + ); + InputFile inputFile = new GeneratedFile(Path.of("non-existing-generated-file.java")); + + assertThat(sonarComponents.fileCanBeSkipped(inputFile)).isFalse(); + } + @Test void fileCanBeSkipped_always_returns_false_when_skipUnchangedFiles_is_false() throws ApiMismatchException { diff --git a/java-frontend/src/test/java/org/sonar/java/model/VisitorsBridgeTest.java b/java-frontend/src/test/java/org/sonar/java/model/VisitorsBridgeTest.java index a3c2edea073..74b4cff5264 100644 --- a/java-frontend/src/test/java/org/sonar/java/model/VisitorsBridgeTest.java +++ b/java-frontend/src/test/java/org/sonar/java/model/VisitorsBridgeTest.java @@ -20,6 +20,7 @@ package org.sonar.java.model; import java.io.File; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -38,7 +39,6 @@ import org.sonar.api.utils.log.LoggerLevel; import org.sonar.java.AnalysisException; import org.sonar.java.CheckFailureException; -import org.sonar.plugins.java.api.internal.EndOfAnalysis; import org.sonar.java.JavaVersionAwareVisitor; import org.sonar.java.SonarComponents; import org.sonar.java.TestUtils; @@ -54,6 +54,7 @@ import org.sonar.plugins.java.api.JavaVersion; import org.sonar.plugins.java.api.ModuleScannerContext; import org.sonar.plugins.java.api.caching.CacheContext; +import org.sonar.plugins.java.api.internal.EndOfAnalysis; import org.sonar.plugins.java.api.tree.CompilationUnitTree; import org.sonar.plugins.java.api.tree.SyntaxToken; import org.sonar.plugins.java.api.tree.SyntaxTrivia; @@ -491,6 +492,21 @@ void scanWithoutParsing_returns_false_when_the_file_cannot_be_skipped() throws A assertThat(visitorsBridge.scanWithoutParsing(inputFile)).isFalse(); } + @Test + void scanWithoutParsing_returns_false_when_the_file_is_a_generated_file() throws ApiMismatchException { + InputFile inputFile = new GeneratedFile(Path.of("non-existing-generated-file.java")); + + SonarComponents sonarComponents = spy(new SonarComponents(null, null, null, null, null)); + doReturn(true).when(sonarComponents).canSkipUnchangedFiles(); + VisitorsBridge visitorsBridge = new VisitorsBridge( + Collections.singletonList(new EndOfAnalysisVisitor()), + Collections.emptyList(), + sonarComponents + ); + + assertThat(visitorsBridge.scanWithoutParsing(inputFile)).isFalse(); + } + @Test void scanWithoutParsing_returns_true_for_scanners_that_do_not_override_scanWithoutParsing() throws ApiMismatchException { JavaFileScanner scanner = new DefaultEndOfAnalysisCheck();