diff options
11 files changed, 87 insertions, 91 deletions
diff --git a/build.gradle b/build.gradle index 9a633c1b746..8674648effb 100644 --- a/build.gradle +++ b/build.gradle @@ -314,22 +314,22 @@ subprojects { dependency 'org.sonarsource.html:sonar-html-plugin:3.19.0.5695' dependency 'org.sonarsource.jacoco:sonar-jacoco-plugin:1.3.0.1538' dependency 'org.sonarsource.java:sonar-java-plugin:8.15.0.39343' - dependency 'org.sonarsource.java:sonar-java-symbolic-execution-plugin:8.15.0.39343' + dependency 'org.sonarsource.java:sonar-java-symbolic-execution-plugin:8.16.0.131' dependency 'org.sonarsource.javascript:sonar-javascript-plugin:10.23.0.32711' dependency 'org.sonarsource.php:sonar-php-plugin:3.46.0.13151' dependency 'org.sonarsource.plugins.cayc:sonar-cayc-plugin:2.4.0.2018' - dependency 'org.sonarsource.python:sonar-python-plugin:5.4.0.22255' + dependency 'org.sonarsource.python:sonar-python-plugin:5.5.0.23291' dependency 'org.sonarsource.rust:sonar-rust-plugin:1.0.3.786' - dependency 'com.sonarsource.python:sonar-python-enterprise-plugin:5.4.0.22255' + dependency 'com.sonarsource.python:sonar-python-enterprise-plugin:5.5.0.23291' dependency 'org.sonarsource.kotlin:sonar-kotlin-plugin:3.2.0.7239' dependency "org.sonarsource.api.plugin:sonar-plugin-api:$pluginApiVersion" dependency "org.sonarsource.api.plugin:sonar-plugin-api-test-fixtures:$pluginApiVersion" dependency 'org.sonarsource.xml:sonar-xml-plugin:2.13.0.5938' dependency 'org.sonarsource.iac:sonar-iac-plugin:1.47.0.15287' dependency 'com.sonarsource.iac:sonar-iac-enterprise-plugin:1.47.0.15287' - dependency 'org.sonarsource.text:sonar-text-plugin:2.24.1.6530' - dependency 'com.sonarsource.text:sonar-text-developer-plugin:2.24.1.6530' - dependency 'com.sonarsource.text:sonar-text-enterprise-plugin:2.24.1.6530' + dependency 'org.sonarsource.text:sonar-text-plugin:2.24.2.6631' + dependency 'com.sonarsource.text:sonar-text-developer-plugin:2.24.2.6631' + dependency 'com.sonarsource.text:sonar-text-enterprise-plugin:2.24.2.6631' dependency 'com.sonarsource.jcl:sonar-jcl-plugin:1.4.1.1493' dependency 'com.sonarsource.architecture:sonar-architecture-plugin:1.11.0.5805' dependency 'com.sonarsource.architecture:sonar-architecture-java-frontend-plugin:1.11.0.5805' diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/ChangedFilePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/ChangedFilePredicate.java index 7e981e82f77..c3c38969ce4 100644 --- a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/ChangedFilePredicate.java +++ b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/ChangedFilePredicate.java @@ -24,15 +24,9 @@ import org.sonar.api.batch.fs.InputFile; public class ChangedFilePredicate implements FilePredicate { - private final FilePredicate originalPredicate; - - public ChangedFilePredicate(FilePredicate originalPredicate) { - this.originalPredicate = originalPredicate; - } - @Override public boolean apply(InputFile inputFile) { - return originalPredicate.apply(inputFile) && InputFile.Status.SAME != inputFile.status(); + return InputFile.Status.SAME != inputFile.status(); } } diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicate.java index 29e387b97b2..91ca9258621 100644 --- a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicate.java +++ b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicate.java @@ -59,4 +59,9 @@ public class FileExtensionPredicate extends AbstractFilePredicate { private static String lowercase(String extension) { return extension.toLowerCase(Locale.ENGLISH); } + + @Override + public int priority() { + return USE_INDEX; + } } diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicate.java index 39856a3583e..a32f3c88cb9 100644 --- a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicate.java +++ b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicate.java @@ -42,4 +42,8 @@ public class FilenamePredicate extends AbstractFilePredicate { return index.getFilesByName(filename); } + @Override + public int priority() { + return USE_INDEX; + } } diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/HiddenFilesPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/NonHiddenFilesPredicate.java index ab166cd0bbd..4b467e6dba5 100644 --- a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/HiddenFilesPredicate.java +++ b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/NonHiddenFilesPredicate.java @@ -22,18 +22,11 @@ package org.sonar.api.batch.fs.internal.predicates; import org.sonar.api.batch.fs.FilePredicate; import org.sonar.api.batch.fs.InputFile; -public class HiddenFilesPredicate implements FilePredicate { - - private final FilePredicate originalPredicate; - - public HiddenFilesPredicate(FilePredicate originalPredicate) { - this.originalPredicate = originalPredicate; - } +public class NonHiddenFilesPredicate implements FilePredicate { @Override public boolean apply(InputFile inputFile) { - // isHidden() will be known during scanning, evaluation should be done before other predicates - return !inputFile.isHidden() && originalPredicate.apply(inputFile); + return !inputFile.isHidden(); } } diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/ChangedFilePredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/ChangedFilePredicateTest.java index 50b9972848b..33f085344d2 100644 --- a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/ChangedFilePredicateTest.java +++ b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/ChangedFilePredicateTest.java @@ -21,62 +21,42 @@ package org.sonar.api.batch.fs.internal.predicates; import org.assertj.core.api.Assertions; import org.junit.Test; -import org.sonar.api.batch.fs.FilePredicate; import org.sonar.api.batch.fs.InputFile; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class ChangedFilePredicateTest { - private final FilePredicate predicate = mock(FilePredicate.class); private final InputFile inputFile = mock(InputFile.class); - private final ChangedFilePredicate underTest = new ChangedFilePredicate(predicate); + private final ChangedFilePredicate underTest = new ChangedFilePredicate(); @Test - public void apply_when_file_is_changed_and_predicate_is_true() { + public void apply_when_file_is_changed() { when(inputFile.status()).thenReturn(InputFile.Status.CHANGED); - when(predicate.apply(inputFile)).thenReturn(true); Assertions.assertThat(underTest.apply(inputFile)).isTrue(); - verify(predicate, times(1)).apply(any()); - verify(inputFile, times(1)).status(); + verify(inputFile).status(); } @Test - public void apply_when_file_is_added_and_predicate_is_true() { + public void apply_when_file_is_added() { when(inputFile.status()).thenReturn(InputFile.Status.ADDED); - when(predicate.apply(inputFile)).thenReturn(true); Assertions.assertThat(underTest.apply(inputFile)).isTrue(); - verify(predicate, times(1)).apply(any()); - verify(inputFile, times(1)).status(); + verify(inputFile).status(); } @Test - public void do_not_apply_when_file_is_same_and_predicate_is_true() { + public void do_not_apply_when_file_is_same() { when(inputFile.status()).thenReturn(InputFile.Status.SAME); - when(predicate.apply(inputFile)).thenReturn(true); Assertions.assertThat(underTest.apply(inputFile)).isFalse(); - verify(predicate, times(1)).apply(any()); - verify(inputFile, times(1)).status(); - } - - @Test - public void predicate_is_evaluated_before_file_status() { - when(predicate.apply(inputFile)).thenReturn(false); - - Assertions.assertThat(underTest.apply(inputFile)).isFalse(); - - verify(inputFile, never()).status(); + verify(inputFile).status(); } } diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicateTest.java index 83ccb9da164..392d823e541 100644 --- a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicateTest.java +++ b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicateTest.java @@ -19,7 +19,6 @@ */ package org.sonar.api.batch.fs.internal.predicates; -import java.io.IOException; import org.junit.Test; import org.sonar.api.batch.fs.InputFile; @@ -31,14 +30,14 @@ import static org.sonar.api.batch.fs.internal.predicates.FileExtensionPredicate. public class FileExtensionPredicateTest { @Test - public void should_match_correct_extension() throws IOException { + public void should_match_correct_extension() { FileExtensionPredicate predicate = new FileExtensionPredicate("bat"); assertThat(predicate.apply(mockWithName("prog.bat"))).isTrue(); assertThat(predicate.apply(mockWithName("prog.bat.bat"))).isTrue(); } @Test - public void should_not_match_incorrect_extension() throws IOException { + public void should_not_match_incorrect_extension() { FileExtensionPredicate predicate = new FileExtensionPredicate("bat"); assertThat(predicate.apply(mockWithName("prog.batt"))).isFalse(); assertThat(predicate.apply(mockWithName("prog.abat"))).isFalse(); @@ -49,7 +48,7 @@ public class FileExtensionPredicateTest { } @Test - public void should_match_correct_extension_case_insensitively() throws IOException { + public void should_match_correct_extension_case_insensitively() { FileExtensionPredicate predicate = new FileExtensionPredicate("jAVa"); assertThat(predicate.apply(mockWithName("Program.java"))).isTrue(); assertThat(predicate.apply(mockWithName("Program.JAVA"))).isTrue(); @@ -64,7 +63,12 @@ public class FileExtensionPredicateTest { assertThat(getExtension(".")).isEmpty(); } - private InputFile mockWithName(String filename) throws IOException { + @Test + public void should_have_use_index_priority() { + assertThat(new FileExtensionPredicate("bat").priority()).isEqualTo(AbstractFilePredicate.USE_INDEX); + } + + private InputFile mockWithName(String filename) { InputFile inputFile = mock(InputFile.class); when(inputFile.filename()).thenReturn(filename); return inputFile; diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicateTest.java index 2393d9cfa9e..30bc1e5f61e 100644 --- a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicateTest.java +++ b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicateTest.java @@ -59,4 +59,12 @@ public class FilenamePredicateTest { assertThat(new FilenamePredicate(filename).get(index)).containsOnly(inputFile); } + @Test + public void should_have_use_index_priority() { + String filename = "some name"; + InputFile inputFile = mock(InputFile.class); + when(inputFile.filename()).thenReturn(filename); + + assertThat(new FilenamePredicate(filename).priority()).isEqualTo(AbstractFilePredicate.USE_INDEX); + } } diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/HiddenFilesPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/NonHiddenFilesPredicateTest.java index b14a995515a..a5a09a97567 100644 --- a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/HiddenFilesPredicateTest.java +++ b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/NonHiddenFilesPredicateTest.java @@ -21,61 +21,33 @@ package org.sonar.api.batch.fs.internal.predicates; import org.assertj.core.api.Assertions; import org.junit.Test; -import org.sonar.api.batch.fs.FilePredicate; import org.sonar.api.batch.fs.InputFile; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -public class HiddenFilesPredicateTest { +public class NonHiddenFilesPredicateTest { - private final FilePredicate predicate = mock(FilePredicate.class); private final InputFile inputFile = mock(InputFile.class); - private final HiddenFilesPredicate underTest = new HiddenFilesPredicate(predicate); + private final NonHiddenFilesPredicate underTest = new NonHiddenFilesPredicate(); @Test - public void apply_when_file_is_not_hidden_and_predicate_is_true() { + public void apply_when_file_is_not_hidden() { when(inputFile.isHidden()).thenReturn(false); - when(predicate.apply(inputFile)).thenReturn(true); Assertions.assertThat(underTest.apply(inputFile)).isTrue(); - verify(predicate).apply(any()); verify(inputFile).isHidden(); } @Test - public void do_not_apply_when_file_is_not_hidden_and_predicate_is_false() { - when(inputFile.isHidden()).thenReturn(false); - when(predicate.apply(inputFile)).thenReturn(false); - - Assertions.assertThat(underTest.apply(inputFile)).isFalse(); - - verify(predicate).apply(any()); - verify(inputFile).isHidden(); - } - - @Test - public void do_not_apply_when_file_is_hidden_and_predicate_is_true() { + public void do_not_apply_when_file_is_hidden() { when(inputFile.isHidden()).thenReturn(true); - when(predicate.apply(inputFile)).thenReturn(true); Assertions.assertThat(underTest.apply(inputFile)).isFalse(); verify(inputFile).isHidden(); - verify(predicate, never()).apply(any()); - } - - @Test - public void predicate_is_evaluated_after_file_visibility() { - when(inputFile.isHidden()).thenReturn(true); - - Assertions.assertThat(underTest.apply(inputFile)).isFalse(); - - verify(predicate, never()).apply(any()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MutableFileSystem.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MutableFileSystem.java index 95d1e3ccf60..9c969f6ae20 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MutableFileSystem.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MutableFileSystem.java @@ -25,7 +25,7 @@ import org.sonar.api.batch.fs.FilePredicates; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.batch.fs.internal.predicates.ChangedFilePredicate; -import org.sonar.api.batch.fs.internal.predicates.HiddenFilesPredicate; +import org.sonar.api.batch.fs.internal.predicates.NonHiddenFilesPredicate; public class MutableFileSystem extends DefaultFileSystem { @@ -36,7 +36,7 @@ public class MutableFileSystem extends DefaultFileSystem { super(baseDir, cache, filePredicates); } - public MutableFileSystem(Path baseDir) { + MutableFileSystem(Path baseDir) { super(baseDir); } @@ -58,12 +58,12 @@ public class MutableFileSystem extends DefaultFileSystem { if (allowHiddenFileAnalysis) { return predicate; } - return new HiddenFilesPredicate(predicate); + return predicates().and(new NonHiddenFilesPredicate(), predicate); } private FilePredicate applyChangedFilePredicate(FilePredicate predicate) { if (restrictToChangedFiles) { - return new ChangedFilePredicate(predicate); + return predicates().and(new ChangedFilePredicate(), predicate); } return predicate; } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MutableFileSystemTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MutableFileSystemTest.java index 6cdf497a7c8..485708c9936 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MutableFileSystemTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MutableFileSystemTest.java @@ -28,6 +28,9 @@ import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; public class MutableFileSystemTest { @@ -95,6 +98,39 @@ public class MutableFileSystemTest { assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(false)))).isNotNull(); } + @Test + public void hidden_file_predicate_should_preserve_predicate_optimization() { + addFilesWithVisibility(); + var anotherHiddenFile = spy(new TestInputFileBuilder("foo", String.format("src/%s", ".myHiddenFile.txt")) + .setLanguage(LANGUAGE).setStatus(InputFile.Status.ADDED).setHidden(true).build()); + underTest.add(anotherHiddenFile); + underTest.setAllowHiddenFileAnalysis(false); + + assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(true)))).isNull(); + assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(false)))).isNotNull(); + // Verify that predicate optimization is still effective + verify(anotherHiddenFile, never()).isHidden(); + + // This predicate can't be optimized + assertThat(underTest.inputFiles(underTest.predicates().all())).hasSize(1); + verify(anotherHiddenFile).isHidden(); + } + + @Test + public void hidden_file_predicate_should_be_applied_first_for_non_optimized_predicates() { + // Checking the file type is not very costly, but it is not optimized. In real life, something more costly would be reading the file + // content, for example. + addFilesWithVisibility(); + var anotherHiddenFile = spy(new TestInputFileBuilder("foo", String.format("src/%s", ".myHiddenFile." + LANGUAGE)) + .setLanguage(LANGUAGE).setType(InputFile.Type.MAIN).setStatus(InputFile.Status.ADDED).setHidden(true).build()); + underTest.add(anotherHiddenFile); + underTest.setAllowHiddenFileAnalysis(false); + + assertThat(underTest.inputFiles(underTest.predicates().hasType(InputFile.Type.MAIN))).hasSize(1); + // Verify that the file type has not been evaluated + verify(anotherHiddenFile, never()).type(); + } + private void addFilesWithVisibility() { addFile(true); addFile(false); @@ -116,7 +152,7 @@ public class MutableFileSystemTest { private void addFile(InputFile.Status status, boolean hidden) { underTest.add(new TestInputFileBuilder("foo", String.format("src/%s", generateFilename(status, hidden))) - .setLanguage(LANGUAGE).setStatus(status).setHidden(hidden).build()); + .setLanguage(LANGUAGE).setType(InputFile.Type.MAIN).setStatus(status).setHidden(hidden).build()); } private String generateFilename(boolean hidden) { |