From e6b28c1ba4e7627f4599590ddfcc21875843ce87 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Tue, 1 Aug 2017 14:43:55 +0200 Subject: [PATCH] Store project relative path inside DefaultIndexedFile --- .../org/sonar/api/batch/fs/InputFile.java | 5 +- .../batch/fs/internal/DefaultIndexedFile.java | 38 +++++------ .../batch/fs/internal}/SensorStrategy.java | 2 +- .../fs/internal/TestInputFileBuilder.java | 2 +- .../fs/internal/DefaultInputFileTest.java | 66 ++++++++++++------- .../sonar/scanner/phases/SensorsExecutor.java | 2 +- .../scanner/scan/ModuleScanContainer.java | 2 +- .../scanner/scan/filesystem/FileIndexer.java | 7 +- .../scan/filesystem/InputFileBuilder.java | 16 ++++- .../filesystem/ModuleInputComponentStore.java | 5 +- .../sonar/scanner/cpd/CpdSettingsTest.java | 11 ++-- .../mediumtest/fs/FileSystemMediumTest.java | 19 ++++++ .../phases/CoverageExclusionsTest.java | 1 - .../scanner/phases/SensorsExecutorTest.java | 2 +- .../scan/ProjectReactorValidatorTest.java | 6 +- .../scan/filesystem/InputFileBuilderTest.java | 24 +++++-- .../ModuleInputComponentStoreTest.java | 2 +- 17 files changed, 135 insertions(+), 75 deletions(-) rename {sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor => sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal}/SensorStrategy.java (96%) diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java index 92253347869..951f8d8ecff 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java @@ -26,6 +26,7 @@ import java.nio.charset.Charset; import java.nio.file.Path; import javax.annotation.CheckForNull; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; +import org.sonar.api.batch.sensor.SensorDescriptor; /** * This layer over {@link java.io.File} adds information for code analyzers. @@ -54,8 +55,8 @@ public interface InputFile extends IndexedFile { } /** - * Path relative to module base directory. Path is unique and identifies file - * within given {@link FileSystem}. File separator is the forward + * Relative path to module (for normal Sensors) or project (for {@link SensorDescriptor#global() global} Sensors) base directory. + * File separator is the forward * slash ('/'), even on Microsoft Windows. *
* Returns src/main/java/com/Foo.java if module base dir is diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultIndexedFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultIndexedFile.java index a91ab8ad2aa..0d07003dce5 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultIndexedFile.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultIndexedFile.java @@ -37,37 +37,37 @@ import org.sonar.api.utils.PathUtils; */ @Immutable public class DefaultIndexedFile extends DefaultInputComponent implements IndexedFile { - private final String relativePath; + private final String projectRelativePath; + private final String moduleRelativePath; private final String moduleKey; - private final Path moduleBaseDir; private final String language; private final Type type; - private final Path path; + private final Path absolutePath; + private final SensorStrategy sensorStrategy; /** * Testing purposes only! */ - public DefaultIndexedFile(String moduleKey, Path moduleBaseDir, String relativePath, @Nullable String language) { - this(moduleKey, moduleBaseDir, relativePath, language, TestInputFileBuilder.nextBatchId()); + public DefaultIndexedFile(String moduleKey, Path baseDir, String relativePath, @Nullable String language) { + this(baseDir.resolve(relativePath), moduleKey, PathUtils.sanitize(relativePath), PathUtils.sanitize(relativePath), Type.MAIN, language, TestInputFileBuilder.nextBatchId(), + new SensorStrategy()); } - public DefaultIndexedFile(String moduleKey, Path moduleBaseDir, String relativePath, @Nullable String language, int batchId) { - this(moduleKey, moduleBaseDir, relativePath, Type.MAIN, language, batchId); - } - - public DefaultIndexedFile(String moduleKey, Path moduleBaseDir, String relativePath, Type type, @Nullable String language, int batchId) { + public DefaultIndexedFile(Path absolutePath, String moduleKey, String projectRelativePath, String moduleRelativePath, Type type, @Nullable String language, int batchId, + SensorStrategy sensorStrategy) { super(batchId); this.moduleKey = moduleKey; - this.relativePath = PathUtils.sanitize(relativePath); - this.moduleBaseDir = moduleBaseDir.normalize(); + this.projectRelativePath = projectRelativePath; + this.moduleRelativePath = moduleRelativePath; this.type = type; this.language = language; - this.path = this.moduleBaseDir.resolve(this.relativePath); + this.sensorStrategy = sensorStrategy; + this.absolutePath = absolutePath; } @Override public String relativePath() { - return relativePath; + return sensorStrategy.isGlobal() ? projectRelativePath : moduleRelativePath; } @Override @@ -82,7 +82,7 @@ public class DefaultIndexedFile extends DefaultInputComponent implements Indexed @Override public Path path() { - return path; + return absolutePath; } @Override @@ -106,7 +106,7 @@ public class DefaultIndexedFile extends DefaultInputComponent implements Indexed */ @Override public String key() { - return new StringBuilder().append(moduleKey).append(":").append(relativePath).toString(); + return new StringBuilder().append(moduleKey).append(":").append(moduleRelativePath).toString(); } public String moduleKey() { @@ -124,17 +124,17 @@ public class DefaultIndexedFile extends DefaultInputComponent implements Indexed } DefaultIndexedFile that = (DefaultIndexedFile) o; - return moduleKey.equals(that.moduleKey) && relativePath.equals(that.relativePath); + return projectRelativePath.equals(that.projectRelativePath); } @Override public int hashCode() { - return moduleKey.hashCode() + relativePath.hashCode() * 13; + return projectRelativePath.hashCode(); } @Override public String toString() { - return "[moduleKey=" + moduleKey + ", relative=" + relativePath + ", basedir=" + moduleBaseDir + "]"; + return projectRelativePath; } @Override diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorStrategy.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java similarity index 96% rename from sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorStrategy.java rename to sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java index ebdba341751..5e8b34eb86b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorStrategy.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.scanner.sensor; +package org.sonar.api.batch.fs.internal; /** * A shared, mutable object in the module container. diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java index df2bc17d5fa..671790bdf43 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java @@ -192,7 +192,7 @@ public class TestInputFileBuilder { } public DefaultInputFile build() { - DefaultIndexedFile indexedFile = new DefaultIndexedFile(moduleKey, moduleBaseDir, relativePath, type, language, id); + DefaultIndexedFile indexedFile = new DefaultIndexedFile(moduleBaseDir.resolve(relativePath), moduleKey, relativePath, relativePath, type, language, id, new SensorStrategy()); DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(new Metadata(lines, nonBlankLines, hash, originalLineOffsets, lastValidOffset)), contents); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java index cf66115c695..7d699d5bf39 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java @@ -34,6 +34,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.stream.Collectors; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -46,36 +47,52 @@ import static org.mockito.Mockito.mock; public class DefaultInputFileTest { + private static final String PROJECT_RELATIVE_PATH = "module1/src/Foo.php"; + private static final String MODULE_RELATIVE_PATH = "src/Foo.php"; + @Rule public TemporaryFolder temp = new TemporaryFolder(); + private DefaultIndexedFile indexedFile; + + private Path baseDir; + private SensorStrategy sensorStrategy; + + @Before + public void prepare() throws IOException { + baseDir = temp.newFolder().toPath(); + sensorStrategy = new SensorStrategy(); + indexedFile = new DefaultIndexedFile(baseDir.resolve(PROJECT_RELATIVE_PATH), "ABCDE", PROJECT_RELATIVE_PATH, MODULE_RELATIVE_PATH, InputFile.Type.TEST, "php", 0, + sensorStrategy); + } + @Test public void test() throws Exception { - Path baseDir = temp.newFolder().toPath(); Metadata metadata = new Metadata(42, 42, "", new int[0], 0); - DefaultIndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/Foo.php", InputFile.Type.TEST, "php", 0); DefaultInputFile inputFile = new DefaultInputFile(indexedFile, (f) -> f.setMetadata(metadata)) .setStatus(InputFile.Status.ADDED) .setCharset(StandardCharsets.ISO_8859_1); - assertThat(inputFile.relativePath()).isEqualTo("src/Foo.php"); + assertThat(inputFile.relativePath()).isEqualTo(MODULE_RELATIVE_PATH); assertThat(new File(inputFile.relativePath())).isRelative(); assertThat(inputFile.absolutePath()).endsWith("Foo.php"); assertThat(inputFile.filename()).isEqualTo("Foo.php"); - assertThat(inputFile.uri()).hasPath(baseDir.resolve("src/Foo.php").toUri().getPath()); + assertThat(inputFile.uri()).hasPath(baseDir.resolve(PROJECT_RELATIVE_PATH).toUri().getPath()); assertThat(new File(inputFile.absolutePath())).isAbsolute(); assertThat(inputFile.language()).isEqualTo("php"); assertThat(inputFile.status()).isEqualTo(InputFile.Status.ADDED); assertThat(inputFile.type()).isEqualTo(InputFile.Type.TEST); assertThat(inputFile.lines()).isEqualTo(42); assertThat(inputFile.charset()).isEqualTo(StandardCharsets.ISO_8859_1); + + sensorStrategy.setGlobal(true); + assertThat(inputFile.relativePath()).isEqualTo(PROJECT_RELATIVE_PATH); } @Test public void test_content() throws IOException { - Path baseDir = temp.newFolder().toPath(); - Path testFile = baseDir.resolve("src").resolve("Foo.php"); + Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH); Files.createDirectories(testFile.getParent()); String content = "test é string"; Files.write(testFile, content.getBytes(StandardCharsets.ISO_8859_1)); @@ -84,7 +101,7 @@ public class DefaultInputFileTest { Metadata metadata = new Metadata(42, 30, "", new int[0], 0); - DefaultInputFile inputFile = new DefaultInputFile(new DefaultIndexedFile("ABCDE", baseDir, "src/Foo.php", InputFile.Type.TEST, "php", 0), f -> f.setMetadata(metadata)) + DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata)) .setStatus(InputFile.Status.ADDED) .setCharset(StandardCharsets.ISO_8859_1); @@ -98,8 +115,7 @@ public class DefaultInputFileTest { @Test public void test_content_exclude_bom() throws IOException { - Path baseDir = temp.newFolder().toPath(); - Path testFile = baseDir.resolve("src").resolve("Foo.php"); + Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH); Files.createDirectories(testFile.getParent()); try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(testFile.toFile()), StandardCharsets.UTF_8))) { out.write('\ufeff'); @@ -111,7 +127,7 @@ public class DefaultInputFileTest { Metadata metadata = new Metadata(42, 30, "", new int[0], 0); - DefaultInputFile inputFile = new DefaultInputFile(new DefaultIndexedFile("ABCDE", baseDir, "src/Foo.php", InputFile.Type.TEST, "php", 0), f -> f.setMetadata(metadata)) + DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata)) .setStatus(InputFile.Status.ADDED) .setCharset(StandardCharsets.UTF_8); @@ -125,8 +141,8 @@ public class DefaultInputFileTest { @Test public void test_equals_and_hashcode() throws Exception { - DefaultInputFile f1 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php", null), (f) -> mock(Metadata.class)); - DefaultInputFile f1a = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php", null), (f) -> mock(Metadata.class)); + DefaultInputFile f1 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class)); + DefaultInputFile f1a = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class)); DefaultInputFile f2 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Bar.php", null), (f) -> mock(Metadata.class)); assertThat(f1).isEqualTo(f1); @@ -141,14 +157,14 @@ public class DefaultInputFileTest { @Test public void test_toString() throws Exception { - DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php", null), (f) -> mock(Metadata.class)); - assertThat(file.toString()).isEqualTo("[moduleKey=ABCDE, relative=src/Foo.php, basedir=module]"); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class)); + assertThat(file.toString()).isEqualTo(MODULE_RELATIVE_PATH); } @Test public void checkValidPointer() { Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, 15); - DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php", null), f -> f.setMetadata(metadata)); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata)); assertThat(file.newPointer(1, 0).line()).isEqualTo(1); assertThat(file.newPointer(1, 0).lineOffset()).isEqualTo(0); // Don't fail @@ -166,7 +182,7 @@ public class DefaultInputFileTest { file.newPointer(3, 1); fail(); } catch (Exception e) { - assertThat(e).hasMessage("3 is not a valid line for pointer. File [moduleKey=ABCDE, relative=src/Foo.php, basedir=module] has 2 line(s)"); + assertThat(e).hasMessage("3 is not a valid line for pointer. File src/Foo.php has 2 line(s)"); } try { file.newPointer(1, -1); @@ -178,14 +194,14 @@ public class DefaultInputFileTest { file.newPointer(1, 10); fail(); } catch (Exception e) { - assertThat(e).hasMessage("10 is not a valid line offset for pointer. File [moduleKey=ABCDE, relative=src/Foo.php, basedir=module] has 9 character(s) at line 1"); + assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1"); } } @Test public void checkValidPointerUsingGlobalOffset() { Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, 15); - DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php", null), f -> f.setMetadata(metadata)); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata)); assertThat(file.newPointer(0).line()).isEqualTo(1); assertThat(file.newPointer(0).lineOffset()).isEqualTo(0); @@ -209,14 +225,14 @@ public class DefaultInputFileTest { file.newPointer(16); fail(); } catch (Exception e) { - assertThat(e).hasMessage("16 is not a valid offset for file [moduleKey=ABCDE, relative=src/Foo.php, basedir=module]. Max offset is 15"); + assertThat(e).hasMessage("16 is not a valid offset for file src/Foo.php. Max offset is 15"); } } @Test public void checkValidRange() { Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde")); - DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php", null), f -> f.setMetadata(metadata)); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata)); assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 1)).start().line()).isEqualTo(1); // Don't fail @@ -235,14 +251,14 @@ public class DefaultInputFileTest { file.newRange(file.newPointer(1, 0), file.newPointer(1, 10)); fail(); } catch (Exception e) { - assertThat(e).hasMessage("10 is not a valid line offset for pointer. File [moduleKey=ABCDE, relative=src/Foo.php, basedir=module] has 9 character(s) at line 1"); + assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1"); } } @Test public void selectLine() { Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde\n\nabc")); - DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php", null), f -> f.setMetadata(metadata)); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata)); assertThat(file.selectLine(1).start().line()).isEqualTo(1); assertThat(file.selectLine(1).start().lineOffset()).isEqualTo(0); @@ -259,14 +275,14 @@ public class DefaultInputFileTest { file.selectLine(5); fail(); } catch (Exception e) { - assertThat(e).hasMessage("5 is not a valid line for pointer. File [moduleKey=ABCDE, relative=src/Foo.php, basedir=module] has 4 line(s)"); + assertThat(e).hasMessage("5 is not a valid line for pointer. File src/Foo.php has 4 line(s)"); } } @Test public void checkValidRangeUsingGlobalOffset() { Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, 15); - DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php", null), f -> f.setMetadata(metadata)); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata)); TextRange newRange = file.newRange(10, 13); assertThat(newRange.start().line()).isEqualTo(2); assertThat(newRange.start().lineOffset()).isEqualTo(0); @@ -277,7 +293,7 @@ public class DefaultInputFileTest { @Test public void testRangeOverlap() { Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, 15); - DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php", null), f -> f.setMetadata(metadata)); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata)); // Don't fail assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)))).isTrue(); assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isTrue(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java index 88158bfb065..78a596dcd92 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java @@ -28,10 +28,10 @@ import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.InputModuleHierarchy; +import org.sonar.api.batch.fs.internal.SensorStrategy; import org.sonar.api.resources.Project; import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; import org.sonar.scanner.events.EventBus; -import org.sonar.scanner.sensor.SensorStrategy; @ScannerSide public class SensorsExecutor { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java index b949f802e61..b9c7d779257 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java @@ -25,6 +25,7 @@ import org.sonar.api.batch.AnalysisMode; import org.sonar.api.batch.InstantiationStrategy; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.FileMetadata; +import org.sonar.api.batch.fs.internal.SensorStrategy; import org.sonar.api.batch.rule.CheckFactory; import org.sonar.api.resources.Project; import org.sonar.api.scan.filesystem.FileExclusions; @@ -70,7 +71,6 @@ import org.sonar.scanner.scan.filesystem.StatusDetectionFactory; import org.sonar.scanner.scan.report.IssuesReports; import org.sonar.scanner.sensor.DefaultSensorStorage; import org.sonar.scanner.sensor.SensorOptimizer; -import org.sonar.scanner.sensor.SensorStrategy; import org.sonar.scanner.source.HighlightableBuilder; import org.sonar.scanner.source.SymbolizableBuilder; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java index b120e1fd7a8..4b78ce2f6c6 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java @@ -163,8 +163,7 @@ public class FileIndexer { private Void indexFile(Path sourceFile, InputFile.Type type, Progress progress) throws IOException { // get case of real file without resolving link Path realAbsoluteFile = sourceFile.toRealPath(LinkOption.NOFOLLOW_LINKS).toAbsolutePath().normalize(); - String relativePathStr = PathResolver.relativePath(module.getBaseDir(), realAbsoluteFile); - if (relativePathStr == null) { + if (!realAbsoluteFile.startsWith(module.getBaseDir())) { LOG.warn("File '{}' is ignored. It is not located in module basedir '{}'.", realAbsoluteFile.toAbsolutePath(), module.getBaseDir()); return null; } @@ -178,7 +177,7 @@ public class FileIndexer { LOG.warn("File '{}' is ignored because it doesn't belong to the forced language '{}'", realAbsoluteFile.toAbsolutePath(), langDetection.forcedLanguage()); return null; } - DefaultInputFile inputFile = inputFileBuilder.create(type, relativePathStr, language); + DefaultInputFile inputFile = inputFileBuilder.create(type, realAbsoluteFile, language); if (!accept(inputFile)) { progress.increaseExcludedByPatternsCount(); return null; @@ -188,7 +187,7 @@ public class FileIndexer { indexFileAndParentDir(inputFile, parentRelativePath); progress.markAsIndexed(inputFile); } - LOG.debug("'{}' indexed {}with language '{}'", relativePathStr, type == Type.TEST ? "as test " : "", inputFile.language()); + LOG.debug("'{}' indexed {}with language '{}'", relativePath, type == Type.TEST ? "as test " : "", inputFile.language()); inputFileBuilder.checkMetadata(inputFile); return null; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java index d8980917519..aee7714e9fc 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java @@ -25,7 +25,10 @@ import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultIndexedFile; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; +import org.sonar.api.batch.fs.internal.InputModuleHierarchy; +import org.sonar.api.batch.fs.internal.SensorStrategy; import org.sonar.api.config.Configuration; +import org.sonar.api.utils.PathUtils; public class InputFileBuilder { public static final String PRELOAD_FILE_METADATA_KEY = "sonar.preloadFileMetadata"; @@ -35,9 +38,13 @@ public class InputFileBuilder { private final MetadataGenerator metadataGenerator; private final boolean preloadMetadata; private final ModuleFileSystemInitializer moduleFileSystemInitializer; + private final Path projectBaseDir; + private final SensorStrategy sensorStrategy; public InputFileBuilder(DefaultInputModule module, MetadataGenerator metadataGenerator, - BatchIdGenerator idGenerator, Configuration settings, ModuleFileSystemInitializer moduleFileSystemInitializer) { + BatchIdGenerator idGenerator, Configuration settings, ModuleFileSystemInitializer moduleFileSystemInitializer, InputModuleHierarchy hierarchy, SensorStrategy sensorStrategy) { + this.sensorStrategy = sensorStrategy; + this.projectBaseDir = hierarchy.root().getBaseDir(); this.moduleFileSystemInitializer = moduleFileSystemInitializer; this.moduleKey = module.key(); this.moduleBaseDir = module.getBaseDir(); @@ -46,8 +53,11 @@ public class InputFileBuilder { this.preloadMetadata = settings.getBoolean(PRELOAD_FILE_METADATA_KEY).orElse(false); } - DefaultInputFile create(InputFile.Type type, String relativePath, @Nullable String language) { - DefaultIndexedFile indexedFile = new DefaultIndexedFile(moduleKey, moduleBaseDir, relativePath, type, language, idGenerator.get()); + DefaultInputFile create(InputFile.Type type, Path absolutePath, @Nullable String language) { + DefaultIndexedFile indexedFile = new DefaultIndexedFile(absolutePath, moduleKey, + PathUtils.sanitize(projectBaseDir.relativize(absolutePath).toString()), + PathUtils.sanitize(moduleBaseDir.relativize(absolutePath).toString()), + type, language, idGenerator.get(), sensorStrategy); DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> metadataGenerator.setMetadata(f, moduleFileSystemInitializer.defaultEncoding())); if (language != null) { inputFile.setPublished(true); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java index cca6b49fb14..56c926c83e4 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java @@ -25,7 +25,7 @@ import org.sonar.api.batch.fs.InputDir; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.fs.internal.DefaultFileSystem; -import org.sonar.scanner.sensor.SensorStrategy; +import org.sonar.api.batch.fs.internal.SensorStrategy; @ScannerSide public class ModuleInputComponentStore extends DefaultFileSystem.Cache { @@ -91,7 +91,8 @@ public class ModuleInputComponentStore extends DefaultFileSystem.Cache { return inputComponentStore.getFilesByName(filename); } - @Override public Iterable getFilesByExtension(String extension) { + @Override + public Iterable getFilesByExtension(String extension) { return inputComponentStore.getFilesByExtension(extension); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdSettingsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdSettingsTest.java index c7774c750e9..111ddeebfc5 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdSettingsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdSettingsTest.java @@ -19,19 +19,18 @@ */ package org.sonar.scanner.cpd; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import java.util.Optional; - import org.junit.Before; import org.junit.Test; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.InputModuleHierarchy; import org.sonar.api.config.Configuration; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class CpdSettingsTest { private CpdSettings cpdSettings; private Configuration configuration; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java index a61330e3657..5f2add6955a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java @@ -712,4 +712,23 @@ public class FileSystemMediumTest { assertThat(result.inputFiles()).hasSize(1); } + + @Test + public void detectDuplicatedFilesInDifferentModules() throws IOException { + File srcDir = new File(baseDir, "module1/src"); + srcDir.mkdir(); + + File xooFile = new File(srcDir, "sample.xoo"); + FileUtils.write(xooFile, "Sample xoo\ncontent"); + + TaskResult result = tester.newTask() + .properties(builder + .put("sonar.sources", "module1/src") + .put("sonar.modules", "module1") + .put("module1.sonar.sources", "src") + .build()) + .execute(); + + assertThat(result.inputFiles()).hasSize(1); + } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/CoverageExclusionsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/CoverageExclusionsTest.java index 166964fcdc7..a6d208b35bb 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/CoverageExclusionsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/CoverageExclusionsTest.java @@ -26,7 +26,6 @@ import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.config.internal.MapSettings; import org.sonar.core.config.ExclusionProperties; -import org.sonar.scanner.phases.CoverageExclusions; import static org.assertj.core.api.Assertions.assertThat; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/SensorsExecutorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/SensorsExecutorTest.java index 2a68b02aa16..d56d2be32ed 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/SensorsExecutorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/SensorsExecutorTest.java @@ -30,11 +30,11 @@ import org.sonar.api.batch.SensorContext; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.InputModuleHierarchy; +import org.sonar.api.batch.fs.internal.SensorStrategy; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.resources.Project; import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; import org.sonar.scanner.events.EventBus; -import org.sonar.scanner.sensor.SensorStrategy; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java index 24fa9205c37..1b59e69bd18 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java @@ -19,9 +19,6 @@ */ package org.sonar.scanner.scan; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -32,6 +29,9 @@ import org.sonar.api.batch.bootstrap.ProjectReactor; import org.sonar.api.utils.MessageException; import org.sonar.scanner.analysis.DefaultAnalysisMode; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class ProjectReactorValidatorTest { @Rule diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java index a4c6a32b6dd..6611f15302b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java @@ -30,7 +30,9 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.InputFile.Type; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; +import org.sonar.api.batch.fs.internal.SensorStrategy; import org.sonar.api.config.internal.MapSettings; +import org.sonar.scanner.scan.DefaultInputModuleHierarchy; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -44,13 +46,19 @@ public class InputFileBuilderTest { private Path workDir; private InputFileBuilder builder; + private SensorStrategy sensorStrategy; + @Before public void setUp() throws IOException { baseDir = temp.newFolder().toPath(); workDir = temp.newFolder().toPath(); - DefaultInputModule module = new DefaultInputModule(ProjectDefinition.create() + DefaultInputModule root = new DefaultInputModule(ProjectDefinition.create() .setBaseDir(baseDir.toFile()) .setWorkDir(workDir.toFile()) + .setKey("root"), 0); + DefaultInputModule module = new DefaultInputModule(ProjectDefinition.create() + .setBaseDir(baseDir.resolve("module1").toFile()) + .setWorkDir(workDir.toFile()) .setKey("module1"), 0); MetadataGenerator metadataGenerator = mock(MetadataGenerator.class); @@ -58,17 +66,25 @@ public class InputFileBuilderTest { MapSettings settings = new MapSettings(); ModuleFileSystemInitializer moduleFileSystemInitializer = mock(ModuleFileSystemInitializer.class); when(moduleFileSystemInitializer.defaultEncoding()).thenReturn(StandardCharsets.UTF_8); - builder = new InputFileBuilder(module, metadataGenerator, idGenerator, settings.asConfig(), moduleFileSystemInitializer); + sensorStrategy = new SensorStrategy(); + builder = new InputFileBuilder(module, metadataGenerator, idGenerator, settings.asConfig(), moduleFileSystemInitializer, new DefaultInputModuleHierarchy(root), + sensorStrategy); } @Test public void testBuild() { - Path filePath = baseDir.resolve("src/File1.xoo"); - DefaultInputFile inputFile = builder.create(Type.MAIN, "src/File1.xoo", null); + Path filePath = baseDir.resolve("module1/src/File1.xoo"); + DefaultInputFile inputFile = builder.create(Type.MAIN, filePath, null); assertThat(inputFile.moduleKey()).isEqualTo("module1"); assertThat(inputFile.absolutePath()).isEqualTo(filePath.toString().replaceAll("\\\\", "/")); + assertThat(inputFile.relativePath()).isEqualTo("src/File1.xoo"); + assertThat(inputFile.path()).isEqualTo(filePath); assertThat(inputFile.key()).isEqualTo("module1:src/File1.xoo"); assertThat(inputFile.isPublished()).isFalse(); + + sensorStrategy.setGlobal(true); + + assertThat(inputFile.relativePath()).isEqualTo("module1/src/File1.xoo"); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java index 4d2e97d0c23..ff1f957bccf 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java @@ -27,8 +27,8 @@ import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.fs.internal.DefaultInputModule; +import org.sonar.api.batch.fs.internal.SensorStrategy; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; -import org.sonar.scanner.sensor.SensorStrategy; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; -- 2.39.5