From e606937326a6f2c9d83d7d2509d73bb237a94356 Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Mon, 23 Jan 2017 11:22:39 +0100 Subject: [PATCH] SONAR-8631 Only publish input files used by sensors --- .../java/it/analysis/MultiLanguageTest.java | 3 +- .../sonar/core/component/ComponentKeys.java | 1 - .../java/org/sonar/api/CoreProperties.java | 2 + .../org/sonar/api/batch/fs/FilePredicate.java | 2 +- .../fs/internal/AbsolutePathPredicate.java | 3 +- .../fs/internal/AbstractFilePredicate.java | 3 +- .../api/batch/fs/internal/AndPredicate.java | 3 +- .../batch/fs/internal/DefaultFileSystem.java | 8 +- .../batch/fs/internal/DefaultIndexedFile.java | 5 +- .../batch/fs/internal/DefaultInputDir.java | 2 +- .../batch/fs/internal/DefaultInputFile.java | 19 +- .../batch/fs/internal/DefaultInputModule.java | 5 +- .../api/batch/fs/internal/FalsePredicate.java | 3 +- .../batch/fs/internal/InputComponentTree.java | 4 +- .../batch/fs/internal/InputFilePredicate.java | 27 --- .../batch/fs/internal/LanguagePredicate.java | 4 +- .../api/batch/fs/internal/NotPredicate.java | 4 +- .../OptimizedFilePredicateAdapter.java | 4 +- .../api/batch/fs/internal/OrPredicate.java | 4 +- .../fs/internal/PathPatternPredicate.java | 4 +- .../fs/internal/RelativePathPredicate.java | 3 +- .../fs/internal/TestInputFileBuilder.java | 15 +- .../api/batch/fs/internal/TruePredicate.java | 3 +- .../api/batch/fs/internal/TypePredicate.java | 3 +- .../internal/DefaultFilePredicatesTest.java | 9 +- .../fs/internal/DefaultInputFileTest.java | 16 +- .../foo/src/ManyStatements.java | 11 -- .../scanner/bootstrap/BatchComponents.java | 6 +- .../ScannerExtensionDictionnary.java | 2 +- .../deprecated/DeprecatedSensorContext.java | 12 +- .../perspectives/ScannerPerspectives.java | 22 +-- .../deprecated/test/TestPlanBuilder.java | 4 +- .../org/sonar/scanner/index/DefaultIndex.java | 1 - .../org/sonar/scanner/issue/ModuleIssues.java | 34 ++-- .../scanner/phases/AbstractPhaseExecutor.java | 8 +- .../scanner/phases/IssuesPhaseExecutor.java | 1 + .../scanner/phases/PublishPhaseExecutor.java | 10 +- .../scanner/report/ComponentsPublisher.java | 52 +++++- .../scanner/report/MeasuresPublisher.java | 2 +- .../scanner/rule/RuleFinderCompatibility.java | 2 - .../scanner/scan/DefaultComponentTree.java | 5 + .../scan/DefaultInputModuleHierarchy.java | 49 ++--- .../sonar/scanner/scan/LanguageVerifier.java | 69 -------- .../org/sonar/scanner/scan/ModuleIndexer.java | 61 +++++++ .../scanner/scan/ModuleScanContainer.java | 16 +- .../scanner/scan/ProjectScanContainer.java | 1 + .../filesystem/AdditionalFilePredicates.java | 4 +- .../scanner/scan/filesystem/FileIndexer.java | 24 ++- .../IndexedFileBuilderProvider.java | 34 ---- ...FileBuilder.java => InputFileBuilder.java} | 29 +-- .../scan/filesystem/LanguageDetection.java | 13 +- .../filesystem/LanguageDetectionFactory.java | 39 ---- .../scan/filesystem/MetadataGenerator.java | 11 +- .../filesystem/MetadataGeneratorProvider.java | 5 +- .../filesystem/SameInputFilePredicate.java | 7 +- .../scm/{ScmSensor.java => ScmPublisher.java} | 66 +++---- .../scanner/sensor/DefaultSensorContext.java | 4 +- .../scanner/sensor/DefaultSensorStorage.java | 30 +++- .../org/sonar/scanner/source/LinesSensor.java | 68 ------- .../deprecated/JavaCpdBlockIndexerTest.java | 4 +- .../sonar/scanner/index/DefaultIndexTest.java | 142 +++++++-------- .../mediumtest/branch/BranchMediumTest.java | 4 + .../coverage/GenericCoverageMediumTest.java | 4 - .../scanner/mediumtest/cpd/CpdMediumTest.java | 4 + .../measures/MeasuresMediumTest.java | 68 +------ .../scanner/mediumtest/scm/ScmMediumTest.java | 7 +- .../PhasesSumUpTimeProfilerTest.java | 43 ----- .../report/ComponentsPublisherTest.java | 71 +++++++- .../scanner/report/MeasuresPublisherTest.java | 15 +- .../scanner/report/MetadataPublisherTest.java | 2 +- .../scanner/rule/ActiveRulesProviderTest.java | 2 - .../scan/DefaultComponentTreeTest.java | 59 +++++++ .../scan/DefaultInputModuleHierarchyTest.java | 61 +++++++ .../scanner/scan/LanguageVerifierTest.java | 100 ----------- .../sonar/scanner/scan/ModuleIndexerTest.java | 67 +++++++ .../AdditionalFilePredicatesTest.java | 14 +- .../scan/filesystem/InputFileBuilderTest.java | 70 ++++++++ .../LanguageDetectionFactoryTest.java | 41 ----- .../filesystem/LanguageDetectionTest.java | 2 +- .../MetadataGeneratorProviderTest.java | 3 +- .../filesystem/MetadataGeneratorTest.java | 167 +++++++----------- .../scanner/scan/report/JSONReportTest.java | 2 +- .../sensor/DefaultSensorStorageTest.java | 3 - .../protocol/output/FileStructure.java | 4 + 84 files changed, 866 insertions(+), 954 deletions(-) delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputFilePredicate.java delete mode 100644 sonar-scanner-engine/foo/src/ManyStatements.java delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguageVerifier.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilderProvider.java rename sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/{IndexedFileBuilder.java => InputFileBuilder.java} (64%) delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactory.java rename sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/{ScmSensor.java => ScmPublisher.java} (64%) delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/source/LinesSensor.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultComponentTreeTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java delete mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/LanguageVerifierTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java delete mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactoryTest.java diff --git a/it/it-tests/src/test/java/it/analysis/MultiLanguageTest.java b/it/it-tests/src/test/java/it/analysis/MultiLanguageTest.java index c9b1b6ff929..8ff7baf6102 100644 --- a/it/it-tests/src/test/java/it/analysis/MultiLanguageTest.java +++ b/it/it-tests/src/test/java/it/analysis/MultiLanguageTest.java @@ -61,7 +61,8 @@ public class MultiLanguageTest { SonarScanner build = SonarScanner.create().setProjectDir(ItUtils.projectDir("analysis/xoo-multi-languages")); BuildResult result = orchestrator.executeBuild(build); - assertThat(result.getLogs()).contains("2 files indexed"); + // 4 files: 1 .xoo, 1.xoo2, 2 .measures + assertThat(result.getLogs()).contains("4 files indexed"); assertThat(result.getLogs()).contains("Quality profile for xoo: one-issue-per-line"); assertThat(result.getLogs()).contains("Quality profile for xoo2: one-issue-per-line-xoo2"); diff --git a/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java b/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java index 302d15ac4d0..0c5788180fd 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java +++ b/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java @@ -22,7 +22,6 @@ package org.sonar.core.component; import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; import org.sonar.api.batch.fs.InputPath; -import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.resources.Scopes; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java index c62cdb26c60..b4eb78e6721 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java @@ -488,7 +488,9 @@ public interface CoreProperties { /** * @since 5.1 + * @deprecated since 6.3. No longer taken into consideration as all files are always imported. */ + @Deprecated String IMPORT_UNKNOWN_FILES_KEY = "sonar.import_unknown_files"; /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java index 045b2fd5319..4007b74d145 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicate.java @@ -29,6 +29,6 @@ public interface FilePredicate { /** * Test if provided file is valid for this predicate */ - boolean apply(IndexedFile inputFile); + boolean apply(InputFile inputFile); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java index b6e549d28ad..2e5362c1943 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbsolutePathPredicate.java @@ -20,7 +20,6 @@ package org.sonar.api.batch.fs.internal; import org.sonar.api.batch.fs.FileSystem.Index; -import org.sonar.api.batch.fs.IndexedFile; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.scan.filesystem.PathResolver; import org.sonar.api.utils.PathUtils; @@ -44,7 +43,7 @@ class AbsolutePathPredicate extends AbstractFilePredicate { } @Override - public boolean apply(IndexedFile f) { + public boolean apply(InputFile f) { return path.equals(f.absolutePath()); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbstractFilePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbstractFilePredicate.java index 2aff265bcf1..f58a5a2f5e1 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbstractFilePredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbstractFilePredicate.java @@ -20,12 +20,11 @@ package org.sonar.api.batch.fs.internal; import com.google.common.collect.Iterables; -import org.sonar.api.batch.fs.FilePredicate; import org.sonar.api.batch.fs.FileSystem.Index; import org.sonar.api.batch.fs.InputFile; /** - * Partial implementation of {@link FilePredicate}. + * Partial implementation of {@link OptimizedFilePredicate}. * @since 5.1 */ public abstract class AbstractFilePredicate implements OptimizedFilePredicate { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java index e000fd1a1b6..e7afc7600a3 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AndPredicate.java @@ -22,7 +22,6 @@ package org.sonar.api.batch.fs.internal; import com.google.common.annotations.VisibleForTesting; import org.sonar.api.batch.fs.FilePredicate; import org.sonar.api.batch.fs.FileSystem.Index; -import org.sonar.api.batch.fs.IndexedFile; import org.sonar.api.batch.fs.InputFile; import java.util.ArrayList; @@ -61,7 +60,7 @@ class AndPredicate extends AbstractFilePredicate { } @Override - public boolean apply(IndexedFile f) { + public boolean apply(InputFile f) { for (OptimizedFilePredicate predicate : predicates) { if (!predicate.apply(f)) { return false; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java index c58d668515b..7c7632df8d8 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java @@ -32,6 +32,7 @@ import java.util.Iterator; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; +import java.util.function.Predicate; import java.util.stream.StreamSupport; import javax.annotation.Nullable; @@ -55,7 +56,7 @@ public class DefaultFileSystem implements FileSystem { private Path workDir; private Charset encoding; protected final FilePredicates predicates; - private InputFilePredicate defaultPredicate; + private Predicate defaultPredicate; /** * Only for testing @@ -110,7 +111,7 @@ public class DefaultFileSystem implements FileSystem { return this; } - public DefaultFileSystem setDefaultPredicate(@Nullable InputFilePredicate predicate) { + public DefaultFileSystem setDefaultPredicate(@Nullable Predicate predicate) { this.defaultPredicate = predicate; return this; } @@ -161,7 +162,7 @@ public class DefaultFileSystem implements FileSystem { Iterable iterable = OptimizedFilePredicateAdapter.create(predicate).get(cache); if (defaultPredicate != null) { return StreamSupport.stream(iterable.spliterator(), false) - .filter(defaultPredicate::apply)::iterator; + .filter(defaultPredicate::test)::iterator; } return iterable; } @@ -279,6 +280,7 @@ public class DefaultFileSystem implements FileSystem { return dirMap.get(relativePath); } + @Override public InputModule module() { return module; } 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 642b6e1176b..d29b42c8b59 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 @@ -36,8 +36,11 @@ public class DefaultIndexedFile extends DefaultInputComponent implements Indexed private String language; private final Type type; + /** + * Testing purposes only! + */ public DefaultIndexedFile(String moduleKey, Path moduleBaseDir, String relativePath) { - this(moduleKey, moduleBaseDir, relativePath, TestInputFileBuilder.batchId++); + this(moduleKey, moduleBaseDir, relativePath, TestInputFileBuilder.nextBatchId()); } public DefaultIndexedFile(String moduleKey, Path moduleBaseDir, String relativePath, int batchId) { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java index b845be0865b..36444b4ecb8 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java @@ -35,7 +35,7 @@ public class DefaultInputDir extends DefaultInputComponent implements InputDir { private Path moduleBaseDir; public DefaultInputDir(String moduleKey, String relativePath) { - this(moduleKey, relativePath, TestInputFileBuilder.batchId++); + this(moduleKey, relativePath, TestInputFileBuilder.nextBatchId()); } public DefaultInputDir(String moduleKey, String relativePath, int batchId) { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java index a2c97b8c954..cecc2e410d7 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java @@ -24,7 +24,7 @@ import java.io.File; import java.nio.charset.Charset; import java.nio.file.Path; import java.util.Arrays; -import java.util.function.Function; +import java.util.function.Consumer; import javax.annotation.CheckForNull; import org.sonar.api.batch.fs.InputFile; @@ -36,12 +36,13 @@ import org.sonar.api.batch.fs.TextRange; */ public class DefaultInputFile extends DefaultInputComponent implements InputFile { private final DefaultIndexedFile indexedFile; - private final Function metadataGenerator; + private final Consumer metadataGenerator; private Status status; private Charset charset; private Metadata metadata; + private boolean publish = false; - public DefaultInputFile(DefaultIndexedFile indexedFile, Function metadataGenerator) { + public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer metadataGenerator) { super(indexedFile.batchId()); this.indexedFile = indexedFile; this.metadataGenerator = metadataGenerator; @@ -50,10 +51,18 @@ public class DefaultInputFile extends DefaultInputComponent implements InputFile private void checkMetadata() { if (metadata == null) { - setMetadata(metadataGenerator.apply(this)); + metadataGenerator.accept(this); } } + public void setPublish(boolean publish) { + this.publish = publish; + } + + public boolean publish() { + return publish; + } + @Override public String relativePath() { return indexedFile.relativePath(); @@ -253,7 +262,7 @@ public class DefaultInputFile extends DefaultInputComponent implements InputFile return Math.abs(Arrays.binarySearch(originalLineOffsets(), globalOffset) + 1); } - private DefaultInputFile setMetadata(Metadata metadata) { + public DefaultInputFile setMetadata(Metadata metadata) { this.metadata = metadata; return this; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java index 54f315b3427..368f4f91566 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java @@ -30,8 +30,11 @@ public class DefaultInputModule extends DefaultInputComponent implements InputMo private final String moduleKey; private final ProjectDefinition definition; + /** + * For testing only! + */ public DefaultInputModule(String moduleKey) { - this(ProjectDefinition.create().setKey(moduleKey), TestInputFileBuilder.batchId++); + this(ProjectDefinition.create().setKey(moduleKey), TestInputFileBuilder.nextBatchId()); } public DefaultInputModule(ProjectDefinition definition, int batchId) { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java index 1acaf7b2df3..3fac4b9e6ef 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FalsePredicate.java @@ -21,7 +21,6 @@ package org.sonar.api.batch.fs.internal; import org.sonar.api.batch.fs.FilePredicate; import org.sonar.api.batch.fs.FileSystem.Index; -import org.sonar.api.batch.fs.IndexedFile; import org.sonar.api.batch.fs.InputFile; import java.util.Collections; @@ -31,7 +30,7 @@ class FalsePredicate extends AbstractFilePredicate { static final FilePredicate FALSE = new FalsePredicate(); @Override - public boolean apply(IndexedFile inputFile) { + public boolean apply(InputFile inputFile) { return false; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputComponentTree.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputComponentTree.java index 782a379ef72..f083f151063 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputComponentTree.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputComponentTree.java @@ -24,7 +24,7 @@ import java.util.Collection; import org.sonar.api.batch.fs.InputComponent; public interface InputComponentTree { - public Collection getChildren(InputComponent module); + Collection getChildren(InputComponent module); - public InputComponent getParent(InputComponent module); + InputComponent getParent(InputComponent module); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputFilePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputFilePredicate.java deleted file mode 100644 index eacd05b625c..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/InputFilePredicate.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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.api.batch.fs.internal; - -import org.sonar.api.batch.fs.InputFile; - -@FunctionalInterface -public interface InputFilePredicate { - boolean apply(InputFile inputFile); -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java index 52930c6e2b6..b7f7c78fd4c 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/LanguagePredicate.java @@ -19,7 +19,7 @@ */ package org.sonar.api.batch.fs.internal; -import org.sonar.api.batch.fs.IndexedFile; +import org.sonar.api.batch.fs.InputFile; /** * @since 4.2 @@ -32,7 +32,7 @@ class LanguagePredicate extends AbstractFilePredicate { } @Override - public boolean apply(IndexedFile f) { + public boolean apply(InputFile f) { return language.equals(f.language()); } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java index d51f79d2e13..2a179713f9b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/NotPredicate.java @@ -20,7 +20,7 @@ package org.sonar.api.batch.fs.internal; import org.sonar.api.batch.fs.FilePredicate; -import org.sonar.api.batch.fs.IndexedFile; +import org.sonar.api.batch.fs.InputFile; /** * @since 4.2 @@ -34,7 +34,7 @@ class NotPredicate extends AbstractFilePredicate { } @Override - public boolean apply(IndexedFile f) { + public boolean apply(InputFile f) { return !predicate.apply(f); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OptimizedFilePredicateAdapter.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OptimizedFilePredicateAdapter.java index 35fa0a183f3..636ac426067 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OptimizedFilePredicateAdapter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OptimizedFilePredicateAdapter.java @@ -20,7 +20,7 @@ package org.sonar.api.batch.fs.internal; import org.sonar.api.batch.fs.FilePredicate; -import org.sonar.api.batch.fs.IndexedFile; +import org.sonar.api.batch.fs.InputFile; class OptimizedFilePredicateAdapter extends AbstractFilePredicate { @@ -31,7 +31,7 @@ class OptimizedFilePredicateAdapter extends AbstractFilePredicate { } @Override - public boolean apply(IndexedFile inputFile) { + public boolean apply(InputFile inputFile) { return unoptimizedPredicate.apply(inputFile); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java index e539d05a83d..644c33b8224 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/OrPredicate.java @@ -21,7 +21,7 @@ package org.sonar.api.batch.fs.internal; import com.google.common.annotations.VisibleForTesting; import org.sonar.api.batch.fs.FilePredicate; -import org.sonar.api.batch.fs.IndexedFile; +import org.sonar.api.batch.fs.InputFile; import java.util.ArrayList; import java.util.Collection; @@ -56,7 +56,7 @@ class OrPredicate extends AbstractFilePredicate { } @Override - public boolean apply(IndexedFile f) { + public boolean apply(InputFile f) { for (FilePredicate predicate : predicates) { if (predicate.apply(f)) { return true; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java index 299fb6c9821..86cd285f74c 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPatternPredicate.java @@ -19,7 +19,7 @@ */ package org.sonar.api.batch.fs.internal; -import org.sonar.api.batch.fs.IndexedFile; +import org.sonar.api.batch.fs.InputFile; /** * @since 4.2 @@ -33,7 +33,7 @@ class PathPatternPredicate extends AbstractFilePredicate { } @Override - public boolean apply(IndexedFile f) { + public boolean apply(InputFile f) { return pattern.match(f); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java index f7e727f45b5..155a8b6a3ab 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/RelativePathPredicate.java @@ -20,7 +20,6 @@ package org.sonar.api.batch.fs.internal; import org.sonar.api.batch.fs.FileSystem.Index; -import org.sonar.api.batch.fs.IndexedFile; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.utils.PathUtils; @@ -43,7 +42,7 @@ public class RelativePathPredicate extends AbstractFilePredicate { } @Override - public boolean apply(IndexedFile f) { + public boolean apply(InputFile f) { return path.equals(f.relativePath()); } 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 5da96484421..95890adeab0 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 @@ -29,7 +29,7 @@ import org.sonar.api.batch.fs.InputFile; import org.sonar.api.utils.PathUtils; public class TestInputFileBuilder { - public static int batchId = 1; + private static int batchId = 1; private final int id; private final String relativePath; @@ -44,6 +44,7 @@ public class TestInputFileBuilder { private String hash; private int nonBlankLines; private int[] originalLineOffsets; + private boolean publish = true; public TestInputFileBuilder(String moduleKey, String relativePath) { this(moduleKey, relativePath, batchId++); @@ -56,6 +57,10 @@ public class TestInputFileBuilder { this.id = id; } + public static int nextBatchId() { + return batchId++; + } + public TestInputFileBuilder setModuleBaseDir(Path moduleBaseDir) { this.moduleBaseDir = moduleBaseDir.normalize(); return this; @@ -106,6 +111,11 @@ public class TestInputFileBuilder { return this; } + public TestInputFileBuilder setPublish(boolean publish) { + this.publish = publish; + return this; + } + public TestInputFileBuilder setMetadata(Metadata metadata) { this.setLines(metadata.lines()); this.setLastValidOffset(metadata.lastValidOffset()); @@ -122,9 +132,10 @@ public class TestInputFileBuilder { public DefaultInputFile build() { DefaultIndexedFile indexedFile = new DefaultIndexedFile(moduleKey, moduleBaseDir, relativePath, type, id); indexedFile.setLanguage(language); - DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> new Metadata(lines, nonBlankLines, hash, originalLineOffsets, lastValidOffset)); + DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(new Metadata(lines, nonBlankLines, hash, originalLineOffsets, lastValidOffset))); inputFile.setStatus(status); inputFile.setCharset(charset); + inputFile.setPublish(publish); return inputFile; } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java index c7a58946749..c8ca4d9163b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TruePredicate.java @@ -21,7 +21,6 @@ package org.sonar.api.batch.fs.internal; import org.sonar.api.batch.fs.FilePredicate; import org.sonar.api.batch.fs.FileSystem.Index; -import org.sonar.api.batch.fs.IndexedFile; import org.sonar.api.batch.fs.InputFile; class TruePredicate extends AbstractFilePredicate { @@ -29,7 +28,7 @@ class TruePredicate extends AbstractFilePredicate { static final FilePredicate TRUE = new TruePredicate(); @Override - public boolean apply(IndexedFile inputFile) { + public boolean apply(InputFile inputFile) { return true; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java index c3d9fbf0bc1..36fefb2fd29 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/TypePredicate.java @@ -19,7 +19,6 @@ */ package org.sonar.api.batch.fs.internal; -import org.sonar.api.batch.fs.IndexedFile; import org.sonar.api.batch.fs.InputFile; /** @@ -34,7 +33,7 @@ class TypePredicate extends AbstractFilePredicate { } @Override - public boolean apply(IndexedFile f) { + public boolean apply(InputFile f) { return type == f.type(); } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java index e06847c27e3..b1befd9e62b 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java @@ -25,7 +25,6 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.fs.FilePredicate; import org.sonar.api.batch.fs.FilePredicates; -import org.sonar.api.batch.fs.IndexedFile; import org.sonar.api.batch.fs.InputFile; import java.io.File; @@ -48,14 +47,16 @@ public class DefaultFilePredicatesTest { moduleBasePath = temp.newFolder().toPath(); } - IndexedFile javaFile; + InputFile javaFile; FilePredicates predicates; @Before public void before() throws IOException { predicates = new DefaultFilePredicates(temp.newFolder().toPath()); - javaFile = new DefaultIndexedFile("foo", moduleBasePath, "src/main/java/struts/Action.java") - .setLanguage("java"); + javaFile = new TestInputFileBuilder("foo", "src/main/java/struts/Action.java") + .setModuleBaseDir(moduleBasePath) + .setLanguage("java") + .build(); } @Test 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 e581552aa76..94e8a469cfd 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 @@ -52,7 +52,7 @@ public class DefaultInputFileTest { Metadata metadata = new Metadata(42, 42, "", new int[0], 0); DefaultIndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/Foo.php", InputFile.Type.TEST, 0).setLanguage("php"); - DefaultInputFile inputFile = new DefaultInputFile(indexedFile, (f) -> metadata) + DefaultInputFile inputFile = new DefaultInputFile(indexedFile, (f) -> f.setMetadata(metadata)) .setStatus(InputFile.Status.ADDED) .setCharset(StandardCharsets.ISO_8859_1); @@ -76,7 +76,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, 0) - .setLanguage("php"), f -> metadata) + .setLanguage("php"), f -> f.setMetadata(metadata)) .setStatus(InputFile.Status.ADDED) .setCharset(StandardCharsets.ISO_8859_1); @@ -113,7 +113,7 @@ public class DefaultInputFileTest { @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"), (f) -> metadata); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata)); assertThat(file.newPointer(1, 0).line()).isEqualTo(1); assertThat(file.newPointer(1, 0).lineOffset()).isEqualTo(0); // Don't fail @@ -150,7 +150,7 @@ public class DefaultInputFileTest { @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"), (f) -> metadata); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata)); assertThat(file.newPointer(0).line()).isEqualTo(1); assertThat(file.newPointer(0).lineOffset()).isEqualTo(0); @@ -181,7 +181,7 @@ public class DefaultInputFileTest { @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"), (f) -> metadata); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata)); assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 1)).start().line()).isEqualTo(1); // Don't fail @@ -207,7 +207,7 @@ public class DefaultInputFileTest { @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"), (f) -> metadata); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata)); assertThat(file.selectLine(1).start().line()).isEqualTo(1); assertThat(file.selectLine(1).start().lineOffset()).isEqualTo(0); @@ -231,7 +231,7 @@ public class DefaultInputFileTest { @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"), (f) -> metadata); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), f -> f.setMetadata(metadata)); TextRange newRange = file.newRange(10, 13); assertThat(newRange.start().line()).isEqualTo(2); assertThat(newRange.start().lineOffset()).isEqualTo(0); @@ -242,7 +242,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"), (f) -> metadata); + DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Foo.php"), 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/foo/src/ManyStatements.java b/sonar-scanner-engine/foo/src/ManyStatements.java deleted file mode 100644 index ed2297068e4..00000000000 --- a/sonar-scanner-engine/foo/src/ManyStatements.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.foo; - -public class ManyStatements { - - void foo() { - int A1 = 0; int B = 0; int C = 0; int D = 0; int E = 0; int F = 0; int G = 0; int H = 0; int I = 0; int J = 0; int K = 0; - int A2 = 0; int B = 0; int C = 0; int D = 0; int E = 0; int F = 0; int G = 0; int H = 0; int I = 0; int J = 0; int K = 0; - int A1 = 0; int B = 0; int C = 0; int D = 0; int E = 0; int F = 0; int G = 0; int H = 0; int I = 0; int J = 0; int K = 0; - } - -} \ No newline at end of file diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchComponents.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchComponents.java index d619a516cac..a10e79eaf3d 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchComponents.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchComponents.java @@ -38,9 +38,8 @@ import org.sonar.scanner.scan.report.JSONReport; import org.sonar.scanner.scan.report.RuleNameProvider; import org.sonar.scanner.scan.report.SourceProvider; import org.sonar.scanner.scm.ScmConfiguration; -import org.sonar.scanner.scm.ScmSensor; +import org.sonar.scanner.scm.ScmPublisher; import org.sonar.scanner.source.CodeColorizerSensor; -import org.sonar.scanner.source.LinesSensor; import org.sonar.scanner.source.ZeroCoverageSensor; import org.sonar.scanner.task.ListTask; import org.sonar.scanner.task.ScanTask; @@ -65,9 +64,8 @@ public class BatchComponents { if (!analysisMode.isIssues()) { // SCM components.add(ScmConfiguration.class); - components.add(ScmSensor.class); + components.add(ScmPublisher.class); - components.add(LinesSensor.class); components.add(ZeroCoverageSensor.class); components.add(CodeColorizerSensor.class); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java index 1fbeed00db8..446edb161ef 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java @@ -255,7 +255,7 @@ public class ScannerExtensionDictionnary { } } - private boolean shouldKeep(Class type, Object extension, @Nullable DefaultInputModule module, @Nullable ExtensionMatcher matcher) { + private static boolean shouldKeep(Class type, Object extension, @Nullable DefaultInputModule module, @Nullable ExtensionMatcher matcher) { boolean keep = (ClassUtils.isAssignable(extension.getClass(), type) || (org.sonar.api.batch.Sensor.class.equals(type) && ClassUtils.isAssignable(extension.getClass(), Sensor.class))) && (matcher == null || matcher.accept(extension)); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/DeprecatedSensorContext.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/DeprecatedSensorContext.java index 1908cf638b2..cfc2d8cf89e 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/DeprecatedSensorContext.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/DeprecatedSensorContext.java @@ -68,11 +68,7 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen return index.getMeasure(module.key(), metric); } - private String getEffectiveKey(Resource r) { - if (r.getEffectiveKey() != null) { - return r.getEffectiveKey(); - } - + private String getComponentKey(Resource r) { if (ResourceUtils.isProject(r) || /* For technical projects */ResourceUtils.isRootProject(r)) { return r.getKey(); } else { @@ -107,12 +103,12 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen @Override public Resource getResource(Resource resource) { - return index.getResource(getEffectiveKey(resource)); + return index.getResource(getComponentKey(resource)); } @Override public M getMeasures(Resource resource, MeasuresFilter filter) { - return index.getMeasures(getEffectiveKey(resource), filter); + return index.getMeasures(getComponentKey(resource), filter); } @Override @@ -124,7 +120,7 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen @Override public Measure saveMeasure(@Nullable Resource resource, Measure measure) { Resource resourceOrProject = resourceOrProject(resource); - return index.addMeasure(getEffectiveKey(resourceOrProject), measure); + return index.addMeasure(getComponentKey(resourceOrProject), measure); } @Override diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/perspectives/ScannerPerspectives.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/perspectives/ScannerPerspectives.java index f15ba18ea66..ad2b65bf934 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/perspectives/ScannerPerspectives.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/perspectives/ScannerPerspectives.java @@ -22,6 +22,8 @@ package org.sonar.scanner.deprecated.perspectives; import com.google.common.collect.Maps; import java.util.Map; import javax.annotation.CheckForNull; + +import org.sonar.api.batch.fs.InputComponent; import org.sonar.api.batch.fs.InputPath; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.component.Perspective; @@ -29,18 +31,15 @@ import org.sonar.api.component.ResourcePerspectives; import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; import org.sonar.core.component.ComponentKeys; -import org.sonar.scanner.index.DefaultIndex; import org.sonar.scanner.scan.filesystem.InputComponentStore; public class ScannerPerspectives implements ResourcePerspectives { private final Map, PerspectiveBuilder> builders = Maps.newHashMap(); - private final DefaultIndex resourceIndex; private final InputComponentStore componentStore; private final DefaultInputModule module; - public ScannerPerspectives(PerspectiveBuilder[] builders, DefaultInputModule module, DefaultIndex resourceIndex, InputComponentStore componentStore) { - this.resourceIndex = resourceIndex; + public ScannerPerspectives(PerspectiveBuilder[] builders, DefaultInputModule module, InputComponentStore componentStore) { this.componentStore = componentStore; this.module = module; @@ -52,22 +51,15 @@ public class ScannerPerspectives implements ResourcePerspectives { @Override @CheckForNull public

P as(Class

perspectiveClass, Resource resource) { - Resource indexedResource = resource; - if (resource.getEffectiveKey() == null) { - indexedResource = resourceIndex.getResource(getEffectiveKey(resource)); - } - if (indexedResource != null) { + InputComponent component = componentStore.getByKey(getComponentKey(resource)); + if (component != null) { PerspectiveBuilder

builder = builderFor(perspectiveClass); - return builder.loadPerspective(perspectiveClass, componentStore.getByKey(indexedResource.getEffectiveKey())); + return builder.loadPerspective(perspectiveClass, component); } return null; } - private String getEffectiveKey(Resource r) { - if (r.getEffectiveKey() != null) { - return r.getEffectiveKey(); - } - + private String getComponentKey(Resource r) { if (ResourceUtils.isProject(r) || /* For technical projects */ResourceUtils.isRootProject(r)) { return r.getKey(); } else { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/TestPlanBuilder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/TestPlanBuilder.java index 580b0b10944..5f80f14d6b8 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/TestPlanBuilder.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/TestPlanBuilder.java @@ -25,6 +25,7 @@ import javax.annotation.CheckForNull; import org.sonar.api.batch.fs.InputComponent; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile.Type; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.test.MutableTestPlan; import org.sonar.scanner.deprecated.perspectives.PerspectiveBuilder; @@ -40,8 +41,9 @@ public class TestPlanBuilder extends PerspectiveBuilder { @Override public MutableTestPlan loadPerspective(Class perspectiveClass, InputComponent component) { if (component.isFile()) { - InputFile inputFile = (InputFile) component; + DefaultInputFile inputFile = (DefaultInputFile) component; if (inputFile.type() == Type.TEST) { + inputFile.setPublish(true); if (!testPlanByFile.containsKey(inputFile)) { testPlanByFile.put(inputFile, new DefaultTestPlan()); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/index/DefaultIndex.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/index/DefaultIndex.java index 48ba1cbf2ab..32019e1f0bd 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/index/DefaultIndex.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/index/DefaultIndex.java @@ -188,7 +188,6 @@ public class DefaultIndex { throw new IllegalArgumentException("Unknow input path type: " + inputComponent); } - r.setEffectiveKey(inputComponent.key()); return r; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java index e618b1ddb96..e819b27c525 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ModuleIssues.java @@ -95,26 +95,28 @@ public class ModuleIssues { return false; } - private void applyFlows(ScannerReport.Issue.Builder builder, ScannerReport.IssueLocation.Builder locationBuilder, ScannerReport.TextRange.Builder textRangeBuilder, Issue issue) { + private static void applyFlows(ScannerReport.Issue.Builder builder, ScannerReport.IssueLocation.Builder locationBuilder, + ScannerReport.TextRange.Builder textRangeBuilder, Issue issue) { ScannerReport.Flow.Builder flowBuilder = ScannerReport.Flow.newBuilder(); for (Flow flow : issue.flows()) { - if (!flow.locations().isEmpty()) { - flowBuilder.clear(); - for (org.sonar.api.batch.sensor.issue.IssueLocation location : flow.locations()) { - locationBuilder.clear(); - locationBuilder.setComponentRef(((DefaultInputComponent) location.inputComponent()).batchId()); - String message = location.message(); - if (message != null) { - locationBuilder.setMsg(message); - } - TextRange textRange = location.textRange(); - if (textRange != null) { - locationBuilder.setTextRange(toProtobufTextRange(textRangeBuilder, textRange)); - } - flowBuilder.addLocation(locationBuilder.build()); + if (flow.locations().isEmpty()) { + return; + } + flowBuilder.clear(); + for (org.sonar.api.batch.sensor.issue.IssueLocation location : flow.locations()) { + locationBuilder.clear(); + locationBuilder.setComponentRef(((DefaultInputComponent) location.inputComponent()).batchId()); + String message = location.message(); + if (message != null) { + locationBuilder.setMsg(message); + } + TextRange textRange = location.textRange(); + if (textRange != null) { + locationBuilder.setTextRange(toProtobufTextRange(textRangeBuilder, textRange)); } - builder.addFlow(flowBuilder.build()); + flowBuilder.addLocation(locationBuilder.build()); } + builder.addFlow(flowBuilder.build()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractPhaseExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractPhaseExecutor.java index ede6ae406fc..7316507aed4 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractPhaseExecutor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractPhaseExecutor.java @@ -19,6 +19,7 @@ */ package org.sonar.scanner.phases; + import org.sonar.api.batch.SensorContext; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.scanner.events.BatchStepEvent; @@ -72,6 +73,8 @@ public abstract class AbstractPhaseExecutor { initIssueExclusions(); sensorsExecutor.execute(sensorContext); + + afterSensors(); if (module.definition().getParent() == null) { executeOnRoot(); @@ -81,6 +84,9 @@ public abstract class AbstractPhaseExecutor { eventBus.fireEvent(new ProjectAnalysisEvent(module, false)); } + protected void afterSensors() { + } + protected abstract void executeOnRoot(); private void initIssueExclusions() { @@ -107,7 +113,7 @@ public abstract class AbstractPhaseExecutor { private void cleanMemory() { String cleanMemory = "Clean memory"; eventBus.fireEvent(new BatchStepEvent(cleanMemory, true)); - //index.clear(); + // index.clear(); eventBus.fireEvent(new BatchStepEvent(cleanMemory, false)); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/IssuesPhaseExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/IssuesPhaseExecutor.java index c68bf066b49..478b29bc5d6 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/IssuesPhaseExecutor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/IssuesPhaseExecutor.java @@ -31,6 +31,7 @@ import org.sonar.scanner.rule.QProfileVerifier; import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; import org.sonar.scanner.scan.filesystem.FileSystemLogger; import org.sonar.scanner.scan.report.IssuesReports; +import org.sonar.scanner.scm.ScmPublisher; public final class IssuesPhaseExecutor extends AbstractPhaseExecutor { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PublishPhaseExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PublishPhaseExecutor.java index c0d769ac318..045f1135d73 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PublishPhaseExecutor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PublishPhaseExecutor.java @@ -28,20 +28,23 @@ import org.sonar.scanner.report.ReportPublisher; import org.sonar.scanner.rule.QProfileVerifier; import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; import org.sonar.scanner.scan.filesystem.FileSystemLogger; +import org.sonar.scanner.scm.ScmPublisher; public final class PublishPhaseExecutor extends AbstractPhaseExecutor { private final EventBus eventBus; private final ReportPublisher reportPublisher; private final CpdExecutor cpdExecutor; + private final ScmPublisher scm; public PublishPhaseExecutor(InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, SensorContext sensorContext, EventBus eventBus, ReportPublisher reportPublisher, FileSystemLogger fsLogger, DefaultModuleFileSystem fs, - QProfileVerifier profileVerifier, IssueExclusionsLoader issueExclusionsLoader, CpdExecutor cpdExecutor) { + QProfileVerifier profileVerifier, IssueExclusionsLoader issueExclusionsLoader, CpdExecutor cpdExecutor, ScmPublisher scm) { super(initializersExecutor, postJobsExecutor, sensorsExecutor, sensorContext, eventBus, fsLogger, fs, profileVerifier, issueExclusionsLoader); this.eventBus = eventBus; this.reportPublisher = reportPublisher; this.cpdExecutor = cpdExecutor; + this.scm = scm; } @Override @@ -50,6 +53,11 @@ public final class PublishPhaseExecutor extends AbstractPhaseExecutor { publishReportJob(); } + @Override + protected void afterSensors() { + scm.publish(); + } + private void computeDuplications() { String stepName = "Computing duplications"; eventBus.fireEvent(new BatchStepEvent(stepName, true)); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ComponentsPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ComponentsPublisher.java index 1449657f23f..d51d3a4b1a4 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ComponentsPublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ComponentsPublisher.java @@ -19,6 +19,8 @@ */ package org.sonar.scanner.report; +import java.util.Collection; + import javax.annotation.CheckForNull; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; @@ -29,13 +31,18 @@ import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.fs.InputPath; import org.sonar.api.batch.fs.internal.DefaultInputComponent; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.InputComponentTree; import org.sonar.api.batch.fs.internal.InputModuleHierarchy; +import org.sonar.core.util.CloseableIterator; +import org.sonar.core.util.stream.Collectors; import org.sonar.scanner.protocol.output.ScannerReport; +import org.sonar.scanner.protocol.output.ScannerReportReader; import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType; import org.sonar.scanner.protocol.output.ScannerReport.ComponentLink; import org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType; +import org.sonar.scanner.protocol.output.ScannerReport.Issue; import org.sonar.scanner.protocol.output.ScannerReportWriter; /** @@ -45,6 +52,8 @@ public class ComponentsPublisher implements ReportPublisherStep { private InputComponentTree componentTree; private InputModuleHierarchy moduleHierarchy; + private ScannerReportReader reader; + private ScannerReportWriter writer; public ComponentsPublisher(InputModuleHierarchy moduleHierarchy, InputComponentTree inputComponentTree) { this.moduleHierarchy = moduleHierarchy; @@ -53,10 +62,24 @@ public class ComponentsPublisher implements ReportPublisherStep { @Override public void publish(ScannerReportWriter writer) { - recursiveWriteComponent((DefaultInputComponent) moduleHierarchy.root(), writer); + this.reader = new ScannerReportReader(writer.getFileStructure().root()); + this.writer = writer; + recursiveWriteComponent((DefaultInputComponent) moduleHierarchy.root()); } - private void recursiveWriteComponent(DefaultInputComponent component, ScannerReportWriter writer) { + /** + * Writes the tree of components recursively, deep-first. + * @return true if component was written (not skipped) + */ + private boolean recursiveWriteComponent(DefaultInputComponent component) { + Collection children = componentTree.getChildren(component).stream() + .filter(c -> recursiveWriteComponent((DefaultInputComponent) c)) + .collect(Collectors.toList()); + + if (shouldSkipComponent(component, children)) { + return false; + } + ScannerReport.Component.Builder builder = ScannerReport.Component.newBuilder(); // non-null fields @@ -83,7 +106,7 @@ public class ComponentsPublisher implements ReportPublisherStep { } if (component.isFile()) { - InputFile file = (InputFile) component; + DefaultInputFile file = (DefaultInputFile) component; builder.setIsTest(file.type() == InputFile.Type.TEST); builder.setLines(file.lines()); @@ -98,18 +121,31 @@ public class ComponentsPublisher implements ReportPublisherStep { builder.setPath(path); } - for (InputComponent child : componentTree.getChildren(component)) { + for (InputComponent child : children) { builder.addChildRef(((DefaultInputComponent) child).batchId()); } writeLinks(component, builder); writer.writeComponent(builder.build()); + return true; + } - for (InputComponent child : componentTree.getChildren(component)) { - recursiveWriteComponent((DefaultInputComponent) child, writer); + private boolean shouldSkipComponent(DefaultInputComponent component, Collection children) { + if (component instanceof InputDir && children.isEmpty()) { + try (CloseableIterator componentIssuesIt = reader.readComponentIssues(component.batchId())) { + if (!componentIssuesIt.hasNext()) { + // no file to publish on a directory without issues -> skip it + return true; + } + } + } else if (component instanceof DefaultInputFile) { + // skip files not marked for publishing + DefaultInputFile inputFile = (DefaultInputFile) component; + return !inputFile.publish(); } + return false; } - private void writeVersion(DefaultInputModule module, ScannerReport.Component.Builder builder) { + private static void writeVersion(DefaultInputModule module, ScannerReport.Component.Builder builder) { ProjectDefinition def = module.definition(); String version = getVersion(def); if (version != null) { @@ -142,7 +178,7 @@ public class ComponentsPublisher implements ReportPublisherStep { return def.getParent() != null ? getVersion(def.getParent()) : null; } - private void writeLinks(InputComponent c, ScannerReport.Component.Builder builder) { + private static void writeLinks(InputComponent c, ScannerReport.Component.Builder builder) { if (c instanceof InputModule) { DefaultInputModule inputModule = (DefaultInputModule) c; ProjectDefinition def = inputModule.definition(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MeasuresPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MeasuresPublisher.java index 30e649716d3..ed54d5261cb 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MeasuresPublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MeasuresPublisher.java @@ -104,7 +104,7 @@ public class MeasuresPublisher implements ReportPublisherStep { } } - private static void setValueAccordingToType(ScannerReport.Measure.Builder builder, DefaultMeasure measure) { + private static void setValueAccordingToType(ScannerReport.Measure.Builder builder, DefaultMeasure measure) { Serializable value = measure.value(); Metric metric = measure.metric(); if (Boolean.class.equals(metric.valueType())) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RuleFinderCompatibility.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RuleFinderCompatibility.java index 4d16945fc97..ea78959f3c7 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RuleFinderCompatibility.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RuleFinderCompatibility.java @@ -33,8 +33,6 @@ import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; import org.sonar.core.util.stream.Collectors; -import static org.sonar.core.util.stream.Collectors.toList; - public class RuleFinderCompatibility implements RuleFinder { private final Rules rules; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultComponentTree.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultComponentTree.java index bf5218f3714..3329036fdae 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultComponentTree.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultComponentTree.java @@ -27,14 +27,19 @@ import java.util.Map; import java.util.Set; import javax.annotation.CheckForNull; + import org.sonar.api.batch.fs.InputComponent; import org.sonar.api.batch.fs.internal.InputComponentTree; +import com.google.common.base.Preconditions; + public class DefaultComponentTree implements InputComponentTree { private Map parents = new HashMap<>(); private Map> children = new HashMap<>(); public void index(InputComponent component, InputComponent parent) { + Preconditions.checkNotNull(component); + Preconditions.checkNotNull(parent); parents.put(component, parent); Set list = children.get(parent); if (list == null) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultInputModuleHierarchy.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultInputModuleHierarchy.java index f1f35acf1f9..ef036c0bfab 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultInputModuleHierarchy.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultInputModuleHierarchy.java @@ -26,53 +26,31 @@ import java.util.Map; import javax.annotation.CheckForNull; -import org.sonar.api.Startable; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.InputModuleHierarchy; import org.sonar.api.scan.filesystem.PathResolver; -import org.sonar.scanner.scan.filesystem.BatchIdGenerator; +import com.google.common.base.Preconditions; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; -public class DefaultInputModuleHierarchy implements InputModuleHierarchy, Startable { +public class DefaultInputModuleHierarchy implements InputModuleHierarchy { private final PathResolver pathResolver = new PathResolver(); - private final ImmutableProjectReactor projectReactor; - private final DefaultComponentTree componentTree; - private final BatchIdGenerator batchIdGenerator; - private DefaultInputModule root; - private Map parents; - private Multimap children; - - public DefaultInputModuleHierarchy(ImmutableProjectReactor projectReactor, DefaultComponentTree componentTree, BatchIdGenerator batchIdGenerator) { - this.projectReactor = projectReactor; - this.componentTree = componentTree; - this.batchIdGenerator = batchIdGenerator; - } - - @Override - public void start() { - doStart(projectReactor.getRoot()); - } + private final Map parents = new HashMap<>(); + private final Multimap children = HashMultimap.create(); - void doStart(ProjectDefinition rootProjectDefinition) { - parents = new HashMap<>(); - children = HashMultimap.create(); - root = new DefaultInputModule(rootProjectDefinition, batchIdGenerator.get()); - createChildren(root); + public void setRoot(DefaultInputModule root) { + this.root = root; } - private void createChildren(DefaultInputModule parent) { - for (ProjectDefinition def : parent.definition().getSubProjects()) { - DefaultInputModule child = new DefaultInputModule(def, batchIdGenerator.get()); - parents.put(child, parent); - children.put(parent, child); - componentTree.index(child, parent); - createChildren(child); - } + public void index(DefaultInputModule child, DefaultInputModule parent) { + Preconditions.checkNotNull(child); + Preconditions.checkNotNull(parent); + parents.put(child, parent); + children.put(parent, child); } @Override @@ -111,9 +89,4 @@ public class DefaultInputModuleHierarchy implements InputModuleHierarchy, Starta return pathResolver.relativePath(parentBaseDir, moduleBaseDir); } - - @Override - public void stop() { - // nothing to do - } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguageVerifier.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguageVerifier.java deleted file mode 100644 index 55f9f1f6780..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguageVerifier.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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.scan; - -import org.apache.commons.lang.StringUtils; -import org.picocontainer.Startable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.fs.internal.DefaultFileSystem; -import org.sonar.api.config.Settings; -import org.sonar.api.utils.MessageException; -import org.sonar.scanner.repository.language.Language; -import org.sonar.scanner.repository.language.LanguagesRepository; - -/** - * Verifies that the property sonar.language is valid - */ -public class LanguageVerifier implements Startable { - - private static final Logger LOG = LoggerFactory.getLogger(LanguageVerifier.class); - - private final Settings settings; - private final LanguagesRepository languages; - private final DefaultFileSystem fs; - - public LanguageVerifier(Settings settings, LanguagesRepository languages, DefaultFileSystem fs) { - this.settings = settings; - this.languages = languages; - this.fs = fs; - } - - @Override - public void start() { - String languageKey = settings.getString(CoreProperties.PROJECT_LANGUAGE_PROPERTY); - if (StringUtils.isNotBlank(languageKey)) { - LOG.info("Language is forced to {}", languageKey); - Language language = languages.get(languageKey); - if (language == null) { - throw MessageException.of("You must install a plugin that supports the language '" + languageKey + "'"); - } - - // force the registration of the language, even if there are no related source files - fs.addLanguages(languageKey); - } - } - - @Override - public void stop() { - // nothing to do - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java new file mode 100644 index 00000000000..24c1557246a --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java @@ -0,0 +1,61 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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.scan; + +import org.picocontainer.Startable; +import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.batch.fs.internal.DefaultInputModule; +import org.sonar.scanner.scan.filesystem.BatchIdGenerator; + +public class ModuleIndexer implements Startable { + private final ImmutableProjectReactor projectReactor; + private final DefaultComponentTree componentTree; + private final DefaultInputModuleHierarchy moduleHierarchy; + private final BatchIdGenerator batchIdGenerator; + + public ModuleIndexer(ImmutableProjectReactor projectReactor, DefaultComponentTree componentTree, + BatchIdGenerator batchIdGenerator, DefaultInputModuleHierarchy moduleHierarchy) { + this.projectReactor = projectReactor; + this.componentTree = componentTree; + this.moduleHierarchy = moduleHierarchy; + this.batchIdGenerator = batchIdGenerator; + } + + @Override + public void start() { + DefaultInputModule root = new DefaultInputModule(projectReactor.getRoot(), batchIdGenerator.get()); + moduleHierarchy.setRoot(root); + createChildren(root); + } + + private void createChildren(DefaultInputModule parent) { + for (ProjectDefinition def : parent.definition().getSubProjects()) { + DefaultInputModule child = new DefaultInputModule(def, batchIdGenerator.get()); + moduleHierarchy.index(child, parent); + componentTree.index(child, parent); + createChildren(child); + } + } + + @Override + public void stop() { + // nothing to do + } +} 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 35dabd15894..9c087e1b1d7 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 @@ -60,9 +60,9 @@ import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; import org.sonar.scanner.scan.filesystem.ExclusionFilters; import org.sonar.scanner.scan.filesystem.FileIndexer; import org.sonar.scanner.scan.filesystem.FileSystemLogger; -import org.sonar.scanner.scan.filesystem.IndexedFileBuilderProvider; +import org.sonar.scanner.scan.filesystem.InputFileBuilder; +import org.sonar.scanner.scan.filesystem.LanguageDetection; import org.sonar.scanner.scan.filesystem.MetadataGeneratorProvider; -import org.sonar.scanner.scan.filesystem.LanguageDetectionFactory; import org.sonar.scanner.scan.filesystem.ModuleFileSystemInitializer; import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore; import org.sonar.scanner.scan.filesystem.StatusDetectionFactory; @@ -95,10 +95,6 @@ public class ModuleScanContainer extends ComponentContainer { module, ModuleSettings.class); - // hack to initialize settings before ExtensionProviders - ModuleSettings moduleSettings = getComponentByType(ModuleSettings.class); - //module.setSettings(moduleSettings); - if (getComponentByType(AnalysisMode.class).isIssues()) { add(IssuesPhaseExecutor.class, IssuesReports.class); @@ -120,10 +116,9 @@ public class ModuleScanContainer extends ComponentContainer { new MetadataGeneratorProvider(), FileMetadata.class, StatusDetectionFactory.class, - LanguageDetectionFactory.class, + LanguageDetection.class, FileIndexer.class, - new IndexedFileBuilderProvider(), - LanguageVerifier.class, + InputFileBuilder.class, FileSystemLogger.class, DefaultModuleFileSystem.class, ModuleFileSystemInitializer.class, @@ -175,9 +170,6 @@ public class ModuleScanContainer extends ComponentContainer { index.setCurrentProject(getComponentByType(DefaultSensorStorage.class)); getComponentByType(AbstractPhaseExecutor.class).execute(module); - - // Free memory since module settings are no more used - //module.setSettings(null); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java index de4bfe28a36..0144b2e7a4b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java @@ -147,6 +147,7 @@ public class ProjectScanContainer extends ComponentContainer { new AnalysisTempFolderProvider(), // file system + ModuleIndexer.class, InputComponentStore.class, PathResolver.class, DefaultInputModuleHierarchy.class, diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicates.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicates.java index 713ca7a3d89..cf2f12713d5 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicates.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicates.java @@ -19,7 +19,7 @@ */ package org.sonar.scanner.scan.filesystem; -import org.sonar.api.batch.fs.IndexedFile; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.AbstractFilePredicate; /** @@ -40,7 +40,7 @@ class AdditionalFilePredicates { } @Override - public boolean apply(IndexedFile f) { + public boolean apply(InputFile f) { return key.equals(f.key()); } } 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 4b1d99e355c..61ef1d38d27 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 @@ -41,7 +41,6 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.IndexedFile; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile.Type; -import org.sonar.api.batch.fs.internal.DefaultIndexedFile; import org.sonar.api.batch.fs.internal.DefaultInputDir; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; @@ -61,8 +60,7 @@ public class FileIndexer { private final InputFileFilter[] filters; private final boolean isAggregator; private final ExclusionFilters exclusionFilters; - private final IndexedFileBuilder indexedFileBuilder; - private final MetadataGenerator metadataGenerator; + private final InputFileBuilder inputFileBuilder; private final DefaultComponentTree componentTree; private final DefaultInputModule module; private final BatchIdGenerator batchIdGenerator; @@ -71,21 +69,20 @@ public class FileIndexer { private ProgressReport progressReport; public FileIndexer(BatchIdGenerator batchIdGenerator, InputComponentStore componentStore, DefaultInputModule module, ExclusionFilters exclusionFilters, - DefaultComponentTree componentTree, IndexedFileBuilder indexedFileBuilder, MetadataGenerator inputFileBuilder, ProjectDefinition def, InputFileFilter[] filters) { + DefaultComponentTree componentTree, InputFileBuilder inputFileBuilder, ProjectDefinition def, InputFileFilter[] filters) { this.batchIdGenerator = batchIdGenerator; this.componentStore = componentStore; this.module = module; this.componentTree = componentTree; - this.indexedFileBuilder = indexedFileBuilder; - this.metadataGenerator = inputFileBuilder; + this.inputFileBuilder = inputFileBuilder; this.filters = filters; this.exclusionFilters = exclusionFilters; this.isAggregator = !def.getSubProjects().isEmpty(); } public FileIndexer(BatchIdGenerator batchIdGenerator, InputComponentStore componentStore, DefaultInputModule module, ExclusionFilters exclusionFilters, - DefaultComponentTree componentTree, IndexedFileBuilder indexedFileBuilder, MetadataGenerator inputFileBuilder, ProjectDefinition def) { - this(batchIdGenerator, componentStore, module, exclusionFilters, componentTree, indexedFileBuilder, inputFileBuilder, def, new InputFileFilter[0]); + DefaultComponentTree componentTree, InputFileBuilder inputFileBuilder, ProjectDefinition def) { + this(batchIdGenerator, componentStore, module, exclusionFilters, componentTree, inputFileBuilder, def, new InputFileFilter[0]); } void index(DefaultModuleFileSystem fileSystem) { @@ -132,14 +129,13 @@ public class FileIndexer { private void indexFile(DefaultModuleFileSystem fileSystem, Progress progress, Path sourceFile, InputFile.Type type) throws IOException { // get case of real file without resolving link Path realFile = sourceFile.toRealPath(LinkOption.NOFOLLOW_LINKS); - DefaultIndexedFile indexedFile = indexedFileBuilder.create(realFile, type, fileSystem.baseDirPath()); - if (indexedFile != null) { - InputFile inputFile = new DefaultInputFile(indexedFile, f -> metadataGenerator.readMetadata(f, fileSystem.encoding())); - if (exclusionFilters.accept(indexedFile, type) && accept(inputFile)) { + DefaultInputFile inputFile = inputFileBuilder.create(realFile, type, fileSystem.encoding()); + if (inputFile != null) { + if (exclusionFilters.accept(inputFile, type) && accept(inputFile)) { fileSystem.add(inputFile); indexParentDir(fileSystem, inputFile); - progress.markAsIndexed(indexedFile); - LOG.debug("'{}' indexed {} with language '{}'", indexedFile.relativePath(), type == Type.TEST ? "as test " : "", indexedFile.language()); + progress.markAsIndexed(inputFile); + LOG.debug("'{}' indexed {} with language '{}'", inputFile.relativePath(), type == Type.TEST ? "as test " : "", inputFile.language()); } else { progress.increaseExcludedByPatternsCount(); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilderProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilderProvider.java deleted file mode 100644 index e0bbf85464e..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilderProvider.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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.scan.filesystem; - -import org.picocontainer.injectors.ProviderAdapter; -import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.api.config.Settings; -import org.sonar.api.scan.filesystem.PathResolver; - -public class IndexedFileBuilderProvider extends ProviderAdapter { - - public IndexedFileBuilder provide(ProjectDefinition def, PathResolver pathResolver, Settings settings, - LanguageDetectionFactory langDetectionFactory, BatchIdGenerator idGenerator) { - return new IndexedFileBuilder(def.getKey(), pathResolver, settings, langDetectionFactory.create(), idGenerator); - } - -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java similarity index 64% rename from sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilder.java rename to sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java index 1db56df4c15..c3826963bb6 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/IndexedFileBuilder.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java @@ -19,36 +19,40 @@ */ package org.sonar.scanner.scan.filesystem; +import java.nio.charset.Charset; import java.nio.file.Path; import javax.annotation.CheckForNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.CoreProperties; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultIndexedFile; -import org.sonar.api.config.Settings; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.scan.filesystem.PathResolver; -public class IndexedFileBuilder { - private static final Logger LOG = LoggerFactory.getLogger(IndexedFileBuilder.class); +public class InputFileBuilder { + private static final Logger LOG = LoggerFactory.getLogger(InputFileBuilder.class); private final String moduleKey; + private final Path moduleBaseDir; private final PathResolver pathResolver; private final LanguageDetection langDetection; - private final Settings settings; private final BatchIdGenerator idGenerator; + private final MetadataGenerator metadataGenerator; - IndexedFileBuilder(String moduleKey, PathResolver pathResolver, Settings settings, LanguageDetection langDetection, BatchIdGenerator idGenerator) { - this.moduleKey = moduleKey; + public InputFileBuilder(DefaultInputModule module, PathResolver pathResolver, LanguageDetection langDetection, MetadataGenerator metadataGenerator, + BatchIdGenerator idGenerator) { + this.moduleKey = module.key(); + this.moduleBaseDir = module.definition().getBaseDir().toPath(); this.pathResolver = pathResolver; - this.settings = settings; this.langDetection = langDetection; + this.metadataGenerator = metadataGenerator; this.idGenerator = idGenerator; } @CheckForNull - DefaultIndexedFile create(Path file, InputFile.Type type, Path moduleBaseDir) { + DefaultInputFile create(Path file, InputFile.Type type, Charset defaultEncoding) { String relativePath = pathResolver.relativePath(moduleBaseDir, file); if (relativePath == null) { LOG.warn("File '{}' is ignored. It is not located in module basedir '{}'.", file.toAbsolutePath(), moduleBaseDir); @@ -56,12 +60,11 @@ public class IndexedFileBuilder { } DefaultIndexedFile indexedFile = new DefaultIndexedFile(moduleKey, moduleBaseDir, relativePath, type, idGenerator.get()); String language = langDetection.language(indexedFile); - if (language == null && !settings.getBoolean(CoreProperties.IMPORT_UNKNOWN_FILES_KEY)) { - LOG.debug("'{}' language is not supported by any analyzer. Skipping it.", relativePath); + if (language == null && langDetection.forcedLanguage() != null) { + LOG.warn("File '{}' is ignored because it doens't belong to the forced langauge '{}'", file.toAbsolutePath(), langDetection.forcedLanguage()); return null; } - indexedFile.setLanguage(language); - return indexedFile; + return new DefaultInputFile(indexedFile, f -> metadataGenerator.setMetadata(f, defaultEncoding)); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java index b83402a7733..847f3f2f364 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java @@ -30,6 +30,7 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; +import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.fs.internal.DefaultIndexedFile; import org.sonar.api.batch.fs.internal.PathPattern; import org.sonar.api.config.Settings; @@ -40,7 +41,8 @@ import org.sonar.scanner.repository.language.LanguagesRepository; /** * Detect language of a source file based on its suffix and configured patterns. */ -class LanguageDetection { +@ScannerSide +public class LanguageDetection { private static final Logger LOG = LoggerFactory.getLogger(LanguageDetection.class); @@ -51,7 +53,7 @@ class LanguageDetection { private final List languagesToConsider = Lists.newArrayList(); private final String forcedLanguage; - LanguageDetection(Settings settings, LanguagesRepository languages) { + public LanguageDetection(Settings settings, LanguagesRepository languages) { for (Language language : languages.all()) { String[] filePatterns = settings.getStringArray(getFileLangPatternPropKey(language.key())); PathPattern[] pathPatterns = PathPattern.create(filePatterns); @@ -75,14 +77,19 @@ class LanguageDetection { // First try with lang patterns if (forcedLanguage != null) { if (!patternsByLanguage.containsKey(forcedLanguage)) { - throw MessageException.of("No language is installed with key '" + forcedLanguage + "'. Please update property '" + CoreProperties.PROJECT_LANGUAGE_PROPERTY + "'"); + throw MessageException.of("You must install a plugin that supports the language '" + forcedLanguage + "'"); } + LOG.info("Language is forced to {}", forcedLanguage); languagesToConsider.add(forcedLanguage); } else { languagesToConsider.addAll(patternsByLanguage.keySet()); } } + public String forcedLanguage() { + return forcedLanguage; + } + Map patternsByLanguage() { return patternsByLanguage; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactory.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactory.java deleted file mode 100644 index 91e389dbaed..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactory.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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.scan.filesystem; - -import org.sonar.api.batch.ScannerSide; -import org.sonar.api.config.Settings; -import org.sonar.scanner.repository.language.LanguagesRepository; - -@ScannerSide -public class LanguageDetectionFactory { - private final Settings settings; - private final LanguagesRepository languages; - - public LanguageDetectionFactory(Settings settings, LanguagesRepository languages) { - this.settings = settings; - this.languages = languages; - } - - public LanguageDetection create() { - return new LanguageDetection(settings, languages); - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGenerator.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGenerator.java index 5468bd7ae6e..ace65041674 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGenerator.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGenerator.java @@ -31,6 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.FileMetadata; import org.sonar.api.batch.fs.internal.Metadata; @@ -44,8 +45,10 @@ class MetadataGenerator { private final StatusDetection statusDetection; private final FileMetadata fileMetadata; + private final DefaultInputModule inputModule; - MetadataGenerator(StatusDetection statusDetection, FileMetadata fileMetadata) { + MetadataGenerator(DefaultInputModule inputModule, StatusDetection statusDetection, FileMetadata fileMetadata) { + this.inputModule = inputModule; this.statusDetection = statusDetection; this.fileMetadata = fileMetadata; } @@ -76,15 +79,15 @@ class MetadataGenerator { } } - public Metadata readMetadata(final DefaultInputFile inputFile, Charset defaultEncoding) { + public void setMetadata(final DefaultInputFile inputFile, Charset defaultEncoding) { try { Charset charset = detectCharset(inputFile.file(), defaultEncoding); inputFile.setCharset(charset); Metadata metadata = fileMetadata.readMetadata(inputFile.file(), charset); - inputFile.setStatus(statusDetection.status(inputFile.moduleKey(), inputFile.relativePath(), metadata.hash())); + inputFile.setMetadata(metadata); + inputFile.setStatus(statusDetection.status(inputModule.definition().getKeyWithBranch(), inputFile.relativePath(), metadata.hash())); LOG.debug("'{}' generated metadata {} with and charset '{}'", inputFile.relativePath(), inputFile.type() == Type.TEST ? "as test " : "", charset); - return metadata; } catch (Exception e) { throw new IllegalStateException(e); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProvider.java index 13bfd484184..216fe5df2bb 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProvider.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProvider.java @@ -21,11 +21,12 @@ package org.sonar.scanner.scan.filesystem; import org.picocontainer.injectors.ProviderAdapter; import org.sonar.api.batch.ScannerSide; +import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.FileMetadata; @ScannerSide public class MetadataGeneratorProvider extends ProviderAdapter { - public MetadataGenerator provide(StatusDetectionFactory statusDetectionFactory, FileMetadata fileMetadata) { - return new MetadataGenerator(statusDetectionFactory.create(), fileMetadata); + public MetadataGenerator provide(DefaultInputModule inputModule, StatusDetectionFactory statusDetectionFactory, FileMetadata fileMetadata) { + return new MetadataGenerator(inputModule, statusDetectionFactory.create(), fileMetadata); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/SameInputFilePredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/SameInputFilePredicate.java index 5ec413082cd..83faa5e4cc0 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/SameInputFilePredicate.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/SameInputFilePredicate.java @@ -19,16 +19,17 @@ */ package org.sonar.scanner.scan.filesystem; +import java.util.function.Predicate; + import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.fs.internal.InputFilePredicate; import org.sonar.scanner.repository.FileData; import org.sonar.scanner.repository.ProjectRepositories; -public class SameInputFilePredicate implements InputFilePredicate { +public class SameInputFilePredicate implements Predicate { private static final Logger LOG = LoggerFactory.getLogger(SameInputFilePredicate.class); private final ProjectRepositories projectRepositories; private final String moduleKey; @@ -39,7 +40,7 @@ public class SameInputFilePredicate implements InputFilePredicate { } @Override - public boolean apply(InputFile inputFile) { + public boolean test(InputFile inputFile) { FileData fileDataPerPath = projectRepositories.fileData(moduleKey, inputFile.relativePath()); if (fileDataPerPath == null) { // ADDED diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmSensor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java similarity index 64% rename from sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmSensor.java rename to sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java index 3f00b5b5c58..8c8f8ff5e95 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmSensor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java @@ -19,52 +19,54 @@ */ package org.sonar.scanner.scm; +import java.io.File; import java.util.LinkedList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; -import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.InstantiationStrategy; +import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile.Status; import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.sensor.Sensor; -import org.sonar.api.batch.sensor.SensorContext; -import org.sonar.api.batch.sensor.SensorDescriptor; +import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.scanner.protocol.output.ScannerReport; +import org.sonar.scanner.protocol.output.ScannerReportWriter; import org.sonar.scanner.protocol.output.ScannerReport.Changesets.Builder; -import org.sonar.scanner.report.ReportPublisher; import org.sonar.scanner.repository.FileData; import org.sonar.scanner.repository.ProjectRepositories; +import org.sonar.scanner.scan.ImmutableProjectReactor; +import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; +import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore; -public final class ScmSensor implements Sensor { +@InstantiationStrategy(InstantiationStrategy.PER_PROJECT) +@ScannerSide +public final class ScmPublisher { - private static final Logger LOG = Loggers.get(ScmSensor.class); + private static final Logger LOG = Loggers.get(ScmPublisher.class); - private final ProjectDefinition projectDefinition; + private final DefaultInputModule inputModule; private final ScmConfiguration configuration; - private final FileSystem fs; private final ProjectRepositories projectRepositories; - private final ReportPublisher publishReportJob; + private final ModuleInputComponentStore componentStore; - public ScmSensor(ProjectDefinition projectDefinition, ScmConfiguration configuration, - ProjectRepositories projectRepositories, FileSystem fs, ReportPublisher publishReportJob) { - this.projectDefinition = projectDefinition; + private DefaultModuleFileSystem fs; + private ScannerReportWriter writer; + + public ScmPublisher(DefaultInputModule inputModule, ScmConfiguration configuration, ProjectRepositories projectRepositories, + ModuleInputComponentStore componentStore, DefaultModuleFileSystem fs, ImmutableProjectReactor reactor) { + this.inputModule = inputModule; this.configuration = configuration; this.projectRepositories = projectRepositories; + this.componentStore = componentStore; this.fs = fs; - this.publishReportJob = publishReportJob; - } - - @Override - public void describe(SensorDescriptor descriptor) { - descriptor.name("SCM Sensor"); + File reportDir = new File(reactor.getRoot().getWorkDir(), "batch-report"); + writer = new ScannerReportWriter(reportDir); } - @Override - public void execute(SensorContext context) { + public void publish() { if (configuration.isDisabled()) { LOG.info("SCM Publisher is disabled"); return; @@ -74,11 +76,11 @@ public final class ScmSensor implements Sensor { return; } - List filesToBlame = collectFilesToBlame(); + List filesToBlame = collectFilesToBlame(writer); if (!filesToBlame.isEmpty()) { String key = configuration.provider().key(); LOG.info("SCM provider for this project is: " + key); - DefaultBlameOutput output = new DefaultBlameOutput(publishReportJob.getWriter(), filesToBlame); + DefaultBlameOutput output = new DefaultBlameOutput(writer, filesToBlame); try { configuration.provider().blameCommand().blame(new DefaultBlameInput(fs, filesToBlame), output); } catch (Exception e) { @@ -89,32 +91,36 @@ public final class ScmSensor implements Sensor { } } - private List collectFilesToBlame() { + private List collectFilesToBlame(ScannerReportWriter writer) { if (configuration.forceReloadAll()) { LOG.warn("Forced reloading of SCM data for all files."); } List filesToBlame = new LinkedList<>(); - for (InputFile f : fs.inputFiles(fs.predicates().all())) { + for (InputFile f : componentStore.inputFiles()) { + DefaultInputFile inputFile = (DefaultInputFile) f; + if (!inputFile.publish()) { + continue; + } if (configuration.forceReloadAll() || f.status() != Status.SAME) { addIfNotEmpty(filesToBlame, f); } else { // File status is SAME so that mean fileData exists - FileData fileData = projectRepositories.fileData(projectDefinition.getKeyWithBranch(), f.relativePath()); + FileData fileData = projectRepositories.fileData(inputModule.definition().getKeyWithBranch(), f.relativePath()); if (StringUtils.isEmpty(fileData.revision())) { addIfNotEmpty(filesToBlame, f); } else { - askToCopyDataFromPreviousAnalysis((DefaultInputFile) f); + askToCopyDataFromPreviousAnalysis((DefaultInputFile) f, writer); } } } return filesToBlame; } - private void askToCopyDataFromPreviousAnalysis(DefaultInputFile f) { + private void askToCopyDataFromPreviousAnalysis(DefaultInputFile f, ScannerReportWriter writer) { Builder scmBuilder = ScannerReport.Changesets.newBuilder(); scmBuilder.setComponentRef(f.batchId()); scmBuilder.setCopyFromPrevious(true); - publishReportJob.getWriter().writeComponentChangesets(scmBuilder.build()); + writer.writeComponentChangesets(scmBuilder.build()); } private static void addIfNotEmpty(List filesToBlame, InputFile f) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java index 8600ec3fdab..61b5c31ab3c 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorContext.java @@ -25,6 +25,7 @@ import org.sonar.api.batch.AnalysisMode; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputModule; +import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.coverage.NewCoverage; @@ -160,6 +161,7 @@ public class DefaultSensorContext implements SensorContext { @Override public void markForPublishing(InputFile inputFile) { - + DefaultInputFile file = (DefaultInputFile) inputFile; + file.setPublish(true); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java index 051565781cd..3ba1565e874 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java @@ -204,6 +204,9 @@ public class DefaultSensorStorage implements SensorStorage { @Override public void store(Measure newMeasure) { + if (newMeasure.inputComponent() instanceof DefaultInputFile) { + ((DefaultInputFile) newMeasure.inputComponent()).setPublish(true); + } saveMeasure(newMeasure.inputComponent(), (DefaultMeasure) newMeasure); } @@ -344,6 +347,9 @@ public class DefaultSensorStorage implements SensorStorage { @Override public void store(Issue issue) { + if (issue.primaryLocation().inputComponent() instanceof DefaultInputFile) { + ((DefaultInputFile) issue.primaryLocation().inputComponent()).setPublish(true); + } moduleIssues.initAndAddIssue(issue); } @@ -351,6 +357,7 @@ public class DefaultSensorStorage implements SensorStorage { public void store(DefaultHighlighting highlighting) { ScannerReportWriter writer = reportPublisher.getWriter(); DefaultInputFile inputFile = (DefaultInputFile) highlighting.inputFile(); + inputFile.setPublish(true); int componentRef = inputFile.batchId(); if (writer.hasComponentData(FileStructure.Domain.SYNTAX_HIGHLIGHTINGS, componentRef)) { throw new UnsupportedOperationException("Trying to save highlighting twice for the same file is not supported: " + inputFile.absolutePath()); @@ -375,6 +382,7 @@ public class DefaultSensorStorage implements SensorStorage { public void store(DefaultSymbolTable symbolTable) { ScannerReportWriter writer = reportPublisher.getWriter(); DefaultInputFile inputFile = (DefaultInputFile) symbolTable.inputFile(); + inputFile.setPublish(true); int componentRef = inputFile.batchId(); if (writer.hasComponentData(FileStructure.Domain.SYMBOLS, componentRef)) { throw new UnsupportedOperationException("Trying to save symbol table twice for the same file is not supported: " + symbolTable.inputFile().absolutePath()); @@ -405,31 +413,34 @@ public class DefaultSensorStorage implements SensorStorage { @Override public void store(DefaultCoverage defaultCoverage) { - if (coverageExclusions.isExcluded(defaultCoverage.inputFile())) { + DefaultInputFile inputFile = (DefaultInputFile) defaultCoverage.inputFile(); + inputFile.setPublish(true); + if (coverageExclusions.isExcluded(inputFile)) { return; } if (defaultCoverage.linesToCover() > 0) { - saveCoverageMetricInternal(defaultCoverage.inputFile(), LINES_TO_COVER, new DefaultMeasure().forMetric(LINES_TO_COVER).withValue(defaultCoverage.linesToCover())); - saveCoverageMetricInternal(defaultCoverage.inputFile(), UNCOVERED_LINES, + saveCoverageMetricInternal(inputFile, LINES_TO_COVER, new DefaultMeasure().forMetric(LINES_TO_COVER).withValue(defaultCoverage.linesToCover())); + saveCoverageMetricInternal(inputFile, UNCOVERED_LINES, new DefaultMeasure().forMetric(UNCOVERED_LINES).withValue(defaultCoverage.linesToCover() - defaultCoverage.coveredLines())); - saveCoverageMetricInternal(defaultCoverage.inputFile(), COVERAGE_LINE_HITS_DATA, + saveCoverageMetricInternal(inputFile, COVERAGE_LINE_HITS_DATA, new DefaultMeasure().forMetric(COVERAGE_LINE_HITS_DATA).withValue(KeyValueFormat.format(defaultCoverage.hitsByLine()))); } if (defaultCoverage.conditions() > 0) { - saveCoverageMetricInternal(defaultCoverage.inputFile(), CONDITIONS_TO_COVER, + saveCoverageMetricInternal(inputFile, CONDITIONS_TO_COVER, new DefaultMeasure().forMetric(CONDITIONS_TO_COVER).withValue(defaultCoverage.conditions())); - saveCoverageMetricInternal(defaultCoverage.inputFile(), UNCOVERED_CONDITIONS, + saveCoverageMetricInternal(inputFile, UNCOVERED_CONDITIONS, new DefaultMeasure().forMetric(UNCOVERED_CONDITIONS).withValue(defaultCoverage.conditions() - defaultCoverage.coveredConditions())); - saveCoverageMetricInternal(defaultCoverage.inputFile(), COVERED_CONDITIONS_BY_LINE, + saveCoverageMetricInternal(inputFile, COVERED_CONDITIONS_BY_LINE, new DefaultMeasure().forMetric(COVERED_CONDITIONS_BY_LINE).withValue(KeyValueFormat.format(defaultCoverage.coveredConditionsByLine()))); - saveCoverageMetricInternal(defaultCoverage.inputFile(), CONDITIONS_BY_LINE, + saveCoverageMetricInternal(inputFile, CONDITIONS_BY_LINE, new DefaultMeasure().forMetric(CONDITIONS_BY_LINE).withValue(KeyValueFormat.format(defaultCoverage.conditionsByLine()))); } } @Override public void store(DefaultCpdTokens defaultCpdTokens) { - InputFile inputFile = defaultCpdTokens.inputFile(); + DefaultInputFile inputFile = (DefaultInputFile) defaultCpdTokens.inputFile(); + inputFile.setPublish(true); PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language())); List blocks = blockChunker.chunk(inputFile.key(), defaultCpdTokens.getTokenLines()); index.insert(inputFile, blocks); @@ -446,6 +457,7 @@ public class DefaultSensorStorage implements SensorStorage { @Override public void store(AnalysisError analysisError) { + ((DefaultInputFile) analysisError.inputFile()).setPublish(true); // no op } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/source/LinesSensor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/source/LinesSensor.java deleted file mode 100644 index 726eec05aa3..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/source/LinesSensor.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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.source; - -import org.sonar.api.batch.Phase; -import org.sonar.api.batch.fs.FileSystem; -import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.batch.fs.InputFile.Type; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.sensor.Sensor; -import org.sonar.api.batch.sensor.SensorContext; -import org.sonar.api.batch.sensor.SensorDescriptor; -import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; -import org.sonar.api.measures.CoreMetrics; - -@Phase(name = Phase.Name.POST) -public final class LinesSensor implements Sensor { - - @Override - public void describe(SensorDescriptor descriptor) { - descriptor.name("Lines Sensor"); - } - - @Override - public void execute(final SensorContext context) { - FileSystem fs = context.fileSystem(); - for (InputFile f : fs.inputFiles(fs.predicates().hasType(Type.MAIN))) { - ((DefaultMeasure) context.newMeasure() - .on(f) - .forMetric(CoreMetrics.LINES) - .withValue(f.lines())) - .setFromCore() - .save(); - if (f.language() == null) { - // As an approximation for files with no language plugin we consider every non blank line as ncloc - ((DefaultMeasure) context.newMeasure() - .on(f) - .forMetric(CoreMetrics.NCLOC) - .withValue(((DefaultInputFile) f).nonBlankLines())) - .save(); - // No test and no coverage on those files - ((DefaultMeasure) context.newMeasure() - .on(f) - .forMetric(CoreMetrics.LINES_TO_COVER) - .withValue(0)) - .save(); - } - } - } - -} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/deprecated/JavaCpdBlockIndexerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/deprecated/JavaCpdBlockIndexerTest.java index a40589be0f7..13c2409c895 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/deprecated/JavaCpdBlockIndexerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/deprecated/JavaCpdBlockIndexerTest.java @@ -69,7 +69,9 @@ public class JavaCpdBlockIndexerTest { File baseDir = temp.newFolder(); DefaultFileSystem fs = new DefaultFileSystem(baseDir); - file = new TestInputFileBuilder("foo", "src/ManyStatements.java").setLanguage(JAVA).build(); + file = new TestInputFileBuilder("foo", "src/ManyStatements.java") + .setModuleBaseDir(baseDir.toPath()) + .setLanguage(JAVA).build(); fs.add(file); File ioFile = file.file(); FileUtils.copyURLToFile(this.getClass().getResource("ManyStatements.java"), ioFile); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/index/DefaultIndexTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/index/DefaultIndexTest.java index d8cc87b574a..2eadd1f5170 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/index/DefaultIndexTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/index/DefaultIndexTest.java @@ -20,22 +20,28 @@ package org.sonar.scanner.index; import java.io.IOException; -import org.apache.commons.io.FileUtils; +import java.util.Collections; + import org.junit.Before; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.batch.fs.InputComponent; +import org.sonar.api.batch.fs.InputDir; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputDir; +import org.sonar.api.batch.fs.internal.DefaultInputModule; +import org.sonar.api.batch.fs.internal.InputComponentTree; +import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.batch.measure.MetricFinder; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.MeasuresFilters; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.resources.Directory; import org.sonar.api.resources.File; import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; -import org.sonar.scanner.FakeJava; +import org.sonar.scanner.scan.filesystem.InputComponentStore; import org.sonar.scanner.scan.measure.MeasureCache; import org.sonar.scanner.sensor.DefaultSensorStorage; @@ -48,97 +54,83 @@ public class DefaultIndexTest { @org.junit.Rule public TemporaryFolder temp = new TemporaryFolder(); - DefaultIndex index = null; - Rule rule; - RuleFinder ruleFinder; - Project project; - Project moduleA; - Project moduleB; - Project moduleB1; + private DefaultIndex index = null; + private Rule rule; + private RuleFinder ruleFinder; + private Project project; + private Project moduleA; + private Project moduleB; + private Project moduleB1; + private InputComponentStore componentStore; + private InputComponentTree componentTree; private java.io.File baseDir; - // TODO -/* - * @Before public void createIndex() throws IOException { ruleFinder = mock(RuleFinder.class); - - DefaultProjectTree projectTree = mock(DefaultProjectTree.class); - BatchComponentCache resourceCache = new BatchComponentCache(); - index = new DefaultIndex(resourceCache, projectTree, mock(MeasureCache.class), mock(MetricFinder.class)); + componentStore = mock(InputComponentStore.class); + componentTree = mock(InputComponentTree.class); + index = new DefaultIndex(componentStore, componentTree, mock(MeasureCache.class), mock(MetricFinder.class)); baseDir = temp.newFolder(); - project = new Project("project"); - when(projectTree.getProjectDefinition(project)).thenReturn(ProjectDefinition.create().setBaseDir(baseDir)); - moduleA = new Project("moduleA").setParent(project); - when(projectTree.getProjectDefinition(moduleA)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleA"))); - moduleB = new Project("moduleB").setParent(project); - when(projectTree.getProjectDefinition(moduleB)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB"))); - moduleB1 = new Project("moduleB1").setParent(moduleB); - when(projectTree.getProjectDefinition(moduleB1)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB/moduleB1"))); + + ProjectDefinition rootDef = ProjectDefinition.create().setKey("project").setBaseDir(baseDir); + ProjectDefinition moduleADef = ProjectDefinition.create().setKey("moduleA").setBaseDir(new java.io.File(baseDir, "moduleA")); + ProjectDefinition moduleBDef = ProjectDefinition.create().setKey("moduleB").setBaseDir(new java.io.File(baseDir, "moduleB")); + ProjectDefinition moduleB1Def = ProjectDefinition.create().setKey("moduleB1").setBaseDir(new java.io.File(baseDir, "moduleB/moduleB1")); + + rootDef.addSubProject(moduleADef); + rootDef.addSubProject(moduleBDef); + moduleBDef.addSubProject(moduleB1Def); + + project = new Project(rootDef); + moduleA = new Project(moduleADef); + moduleB = new Project(moduleBDef); + moduleB1 = new Project(moduleB1Def); RulesProfile rulesProfile = RulesProfile.create(); rule = Rule.create("repoKey", "ruleKey", "Rule"); rule.setId(1); rulesProfile.activateRule(rule, null); - index.setCurrentProject(project, mock(DefaultSensorStorage.class)); - index.doStart(project); - } - - @Test - public void shouldIndexParentOfDeprecatedFiles() { - File file = File.create("src/org/foo/Bar.java", null, false); - assertThat(index.index(file)).isTrue(); - - Directory reference = Directory.create("src/org/foo"); - assertThat(index.getResource(reference).getName()).isEqualTo("src/org/foo"); - assertThat(index.getChildren(reference)).hasSize(1); - assertThat(index.getParent(reference)).isInstanceOf(Project.class); - } - - @Test - public void shouldIndexTreeOfResources() { - Directory directory = Directory.create("src/org/foo"); - File file = File.create("src/org/foo/Bar.java", FakeJava.INSTANCE, false); - - assertThat(index.index(directory)).isTrue(); - assertThat(index.index(file, directory)).isTrue(); - - File fileRef = File.create("src/org/foo/Bar.java", null, false); - assertThat(index.getResource(fileRef).getKey()).isEqualTo("src/org/foo/Bar.java"); - assertThat(index.getResource(fileRef).getLanguage().getKey()).isEqualTo("java"); - assertThat(index.getChildren(fileRef)).isEmpty(); - assertThat(index.getParent(fileRef)).isInstanceOf(Directory.class); + index.setCurrentProject(mock(DefaultSensorStorage.class)); } @Test - public void shouldNotIndexResourceIfParentNotIndexed() { - Directory directory = Directory.create("src/org/other"); - File file = File.create("src/org/foo/Bar.java", null, false); + public void shouldGetHierarchy() { + InputComponent component = new DefaultInputModule("module1"); + InputFile file1 = new TestInputFileBuilder("module1", "src/org/foo/Bar.java").build(); - assertThat(index.index(file, directory)).isFalse(); + when(componentStore.getByKey("module1")).thenReturn(component); + when(componentStore.getByKey("module1:src/org/foo/Bar.java")).thenReturn(file1); + when(componentTree.getParent(file1)).thenReturn(component); + when(componentTree.getChildren(component)).thenReturn(Collections.singleton(file1)); - File fileRef = File.create("src/org/foo/Bar.java", null, false); - assertThat(index.getChildren(fileRef)).isEmpty(); - assertThat(index.getParent(fileRef)).isNull(); - } - - @Test - public void shouldNotIndexResourceWhenAddingMeasure() { - Resource dir = Directory.create("src/org/foo"); - index.addMeasure(dir, new Measure("ncloc").setValue(50.0)); + assertThat(index.getParent("module1:src/org/foo/Bar.java").getKey()).isEqualTo("module1"); + assertThat(index.getParent("module1")).isNull(); - assertThat(index.getMeasures(dir, MeasuresFilters.metric("ncloc"))).isNull(); + assertThat(index.getChildren("module1")).containsOnly(File.create("src/org/foo/Bar.java")); + assertThat(index.getChildren("module1:src/org/foo/Bar.java")).isEmpty(); } @Test - public void shouldComputePathOfIndexedModules() { - assertThat(index.getResource(project).getPath()).isNull(); - assertThat(index.getResource(moduleA).getPath()).isEqualTo("moduleA"); - assertThat(index.getResource(moduleB).getPath()).isEqualTo("moduleB"); - assertThat(index.getResource(moduleB1).getPath()).isEqualTo("moduleB1"); + public void shouldTransformToResource() { + DefaultInputModule component = new DefaultInputModule(ProjectDefinition.create() + .setKey("module1") + .setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "branch1"), 1); + InputFile file1 = new TestInputFileBuilder("module1", "src/org/foo/Bar.java").build(); + InputDir dir = new DefaultInputDir("module1", "src"); + + assertThat(index.toResource(component)).isInstanceOf(Project.class); + assertThat(index.toResource(component).getKey()).isEqualTo("module1"); + assertThat(index.toResource(component).getEffectiveKey()).isEqualTo("module1:branch1"); + + assertThat(index.toResource(file1)).isInstanceOf(File.class); + assertThat(index.toResource(file1).getKey()).isEqualTo("src/org/foo/Bar.java"); + assertThat(index.toResource(file1).getPath()).isEqualTo("src/org/foo/Bar.java"); + + assertThat(index.toResource(dir)).isInstanceOf(Directory.class); + assertThat(index.toResource(dir).getKey()).isEqualTo("src"); + assertThat(index.toResource(dir).getPath()).isEqualTo("src"); } - */ } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/branch/BranchMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/branch/BranchMediumTest.java index d579e26a77e..5147e929dc2 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/branch/BranchMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/branch/BranchMediumTest.java @@ -36,6 +36,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.scanner.mediumtest.ScannerMediumTester; import org.sonar.scanner.mediumtest.TaskResult; import org.sonar.xoo.XooPlugin; +import org.sonar.xoo.rule.XooRulesDefinition; import static org.assertj.core.api.Assertions.assertThat; @@ -49,6 +50,9 @@ public class BranchMediumTest { public ScannerMediumTester tester = ScannerMediumTester.builder() .registerPlugin("xoo", new XooPlugin()) + .addRules(new XooRulesDefinition()) + // active a rule just to be sure that xoo files are published + .addActiveRule("xoo", "xoo:OneIssuePerFile", null, "One Issue Per File", null, null, null) .addDefaultQProfile("xoo", "Sonar Way") .build(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumTest.java index 16a6428dab2..1cf428dc0ca 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumTest.java @@ -69,7 +69,6 @@ public class GenericCoverageMediumTest { assertThat(result.allMeasures().get(noConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value") .containsOnly( - tuple(CoreMetrics.LINES_KEY, 8, ""), tuple(CoreMetrics.LINES_TO_COVER_KEY, 2, ""), tuple(CoreMetrics.UNCOVERED_LINES_KEY, 1, ""), tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "6=1;7=0")); @@ -81,7 +80,6 @@ public class GenericCoverageMediumTest { assertThat(result.allMeasures().get(withConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value") .containsOnly( - tuple(CoreMetrics.LINES_KEY, 6, ""), tuple(CoreMetrics.LINES_TO_COVER_KEY, 1, ""), tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0, ""), tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "3=1"), @@ -112,7 +110,6 @@ public class GenericCoverageMediumTest { assertThat(result.allMeasures().get(noConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value") .containsOnly( - tuple(CoreMetrics.LINES_KEY, 8, ""), tuple(CoreMetrics.LINES_TO_COVER_KEY, 2, ""), tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0, ""), tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "6=1;7=1")); @@ -124,7 +121,6 @@ public class GenericCoverageMediumTest { assertThat(result.allMeasures().get(withConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value") .containsOnly( - tuple(CoreMetrics.LINES_KEY, 6, ""), tuple(CoreMetrics.LINES_TO_COVER_KEY, 1, ""), tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0, ""), tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "3=2"), diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/cpd/CpdMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/cpd/CpdMediumTest.java index 49c8056ff3e..6326e015bc6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/cpd/CpdMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/cpd/CpdMediumTest.java @@ -42,6 +42,7 @@ import org.sonar.scanner.mediumtest.TaskResult; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.xoo.XooPlugin; import org.sonar.xoo.lang.CpdTokenizerSensor; +import org.sonar.xoo.rule.XooRulesDefinition; import static org.assertj.core.api.Assertions.assertThat; @@ -64,6 +65,9 @@ public class CpdMediumTest { public ScannerMediumTester tester = ScannerMediumTester.builder() .registerPlugin("xoo", new XooPlugin()) .addDefaultQProfile("xoo", "Sonar Way") + .addRules(new XooRulesDefinition()) + // active a rule just to be sure that xoo files are published + .addActiveRule("xoo", "xoo:OneIssuePerFile", null, "One Issue Per File", null, null, null) .build(); private File baseDir; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java index de4ecaac496..db4cb6db8de 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java @@ -30,7 +30,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import org.sonar.api.measures.CoreMetrics; import org.sonar.api.utils.log.LogTester; import org.sonar.api.utils.log.LoggerLevel; import org.sonar.scanner.mediumtest.ScannerMediumTester; @@ -75,63 +74,6 @@ public class MeasuresMediumTest { srcDir.mkdir(); } - @Test - public void computeMeasuresOnTempProject() throws IOException { - File xooFile = new File(srcDir, "sample.xoo"); - File xooMeasureFile = new File(srcDir, "sample.xoo.measures"); - FileUtils.write(xooFile, "Sample xoo\ncontent"); - FileUtils.write(xooMeasureFile, "lines:20"); - - TaskResult result = tester.newTask() - .properties(ImmutableMap.builder() - .put("sonar.task", "scan") - .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) - .put("sonar.projectKey", "com.foo.project") - .put("sonar.projectName", "Foo Project") - .put("sonar.projectVersion", "1.0-SNAPSHOT") - .put("sonar.projectDescription", "Description of Foo Project") - .put("sonar.sources", "src") - .put("sonar.cpd.xoo.skip", "true") - .build()) - .start(); - - Map> allMeasures = result.allMeasures(); - - assertThat(allMeasures.get("com.foo.project")).extracting("metricKey", "stringValue.value").isEmpty(); - - assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value").containsOnly( - tuple(CoreMetrics.LINES_KEY, 2)); - } - - @Test - public void computeLinesOnAllFiles() throws IOException { - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\n\ncontent"); - - File otherFile = new File(srcDir, "sample.other"); - FileUtils.write(otherFile, "Sample other\ncontent\n"); - - TaskResult result = tester.newTask() - .properties(ImmutableMap.builder() - .put("sonar.task", "scan") - .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) - .put("sonar.projectKey", "com.foo.project") - .put("sonar.projectName", "Foo Project") - .put("sonar.projectVersion", "1.0-SNAPSHOT") - .put("sonar.projectDescription", "Description of Foo Project") - .put("sonar.sources", "src") - .put("sonar.import_unknown_files", "true") - .build()) - .start(); - - Map> allMeasures = result.allMeasures(); - - assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value") - .contains(tuple("lines", 3)); - assertThat(allMeasures.get("com.foo.project:src/sample.other")).extracting("metricKey", "intValue.value") - .contains(tuple("lines", 3), tuple("ncloc", 2)); - } - @Test public void applyExclusionsOnCoverageMeasures() throws IOException { File xooFile = new File(srcDir, "sample.xoo"); @@ -155,8 +97,7 @@ public class MeasuresMediumTest { Map> allMeasures = result.allMeasures(); assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value") - .containsOnly(tuple("lines", 3), - tuple("lines_to_cover", 2)); + .containsOnly(tuple("lines_to_cover", 2)); result = tester.newTask() .properties(ImmutableMap.builder() @@ -173,7 +114,7 @@ public class MeasuresMediumTest { allMeasures = result.allMeasures(); assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value") - .containsOnly(tuple("lines", 3)); + .isEmpty(); } @Test @@ -199,8 +140,7 @@ public class MeasuresMediumTest { Map> allMeasures = result.allMeasures(); assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value") - .containsOnly(tuple("lines", 3), - tuple("lines_to_cover", 2)); + .containsOnly(tuple("lines_to_cover", 2)); assertThat(logTester.logs(LoggerLevel.WARN)) .contains("Coverage measure for metric 'lines_to_cover' should not be saved directly by a Sensor. Plugin should be updated to use SensorContext::newCoverage instead."); @@ -257,7 +197,7 @@ public class MeasuresMediumTest { Map> allMeasures = result.allMeasures(); assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value", "stringValue.value") - .containsExactly(tuple("lines", 4, ""), tuple("ncloc_data", 0, "1=1;4=1")); + .containsExactly(tuple("ncloc_data", 0, "1=1;4=1")); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java index f0462e6206b..cd369da5e54 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java @@ -40,6 +40,7 @@ import org.sonar.scanner.repository.FileData; import org.sonar.scanner.protocol.output.ScannerReport.Component; import org.sonar.scanner.protocol.output.ScannerReportReader; import org.sonar.xoo.XooPlugin; +import org.sonar.xoo.rule.XooRulesDefinition; import static org.assertj.core.api.Assertions.assertThat; @@ -64,6 +65,9 @@ public class ScmMediumTest { public ScannerMediumTester tester = ScannerMediumTester.builder() .registerPlugin("xoo", new XooPlugin()) .addDefaultQProfile("xoo", "Sonar Way") + .addRules(new XooRulesDefinition()) + // active a rule just to be sure that xoo files are published + .addActiveRule("xoo", "xoo:OneIssuePerFile", null, "One Issue Per File", null, null, null) .addFileData("com.foo.project", CHANGED_CONTENT_SCM_ON_SERVER_XOO, new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), null)) .addFileData("com.foo.project", SAME_CONTENT_NO_SCM_ON_SERVER_XOO, new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), null)) .addFileData("com.foo.project", SAME_CONTENT_SCM_ON_SERVER_XOO, new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), "1.1")) @@ -82,7 +86,6 @@ public class ScmMediumTest { @Test public void testScmMeasure() throws IOException { - File baseDir = prepareProject(); tester.newTask() @@ -242,6 +245,8 @@ public class ScmMediumTest { assertThat(getChangesets(baseDir, NO_BLAME_SCM_ON_SERVER_XOO)).isNull(); + // 5 .xoo files + 3 .scm files, but only 4 marked for publishing. 1 file is SAME so not included in the total + assertThat(logTester.logs()).containsSubsequence("8 files indexed"); assertThat(logTester.logs()).containsSubsequence("4 files to be analyzed", "3/4 files analyzed"); assertThat(logTester.logs()).containsSubsequence(MISSING_BLAME_INFORMATION_FOR_THE_FOLLOWING_FILES, " * " + noBlameScmOnServer.getPath().replaceAll("\\\\", "/")); } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/profiling/PhasesSumUpTimeProfilerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/profiling/PhasesSumUpTimeProfilerTest.java index 6d7249b1eba..2e69ae0bb7a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/profiling/PhasesSumUpTimeProfilerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/profiling/PhasesSumUpTimeProfilerTest.java @@ -29,14 +29,11 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.CoreProperties; -import org.sonar.api.batch.Decorator; import org.sonar.api.batch.Initializer; import org.sonar.api.batch.PostJob; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.api.batch.events.DecoratorExecutionHandler; -import org.sonar.api.batch.events.DecoratorsPhaseHandler; import org.sonar.api.batch.events.InitializerExecutionHandler; import org.sonar.api.batch.events.InitializersPhaseHandler; import org.sonar.api.batch.events.PostJobExecutionHandler; @@ -238,26 +235,6 @@ public class PhasesSumUpTimeProfilerTest { }; } - private DecoratorExecutionHandler.DecoratorExecutionEvent decoratorEvent(final Decorator decorator, final boolean start) { - return new DecoratorExecutionHandler.DecoratorExecutionEvent() { - - @Override - public boolean isStart() { - return start; - } - - @Override - public boolean isEnd() { - return !start; - } - - @Override - public Decorator getDecorator() { - return decorator; - } - }; - } - private PostJobExecutionHandler.PostJobExecutionEvent postJobEvent(final PostJob postJob, final boolean start) { return new PostJobExecutionHandler.PostJobExecutionEvent() { @@ -338,26 +315,6 @@ public class PhasesSumUpTimeProfilerTest { }; } - private DecoratorsPhaseHandler.DecoratorsPhaseEvent decoratorsEvent(final boolean start) { - return new DecoratorsPhaseHandler.DecoratorsPhaseEvent() { - - @Override - public boolean isStart() { - return start; - } - - @Override - public boolean isEnd() { - return !start; - } - - @Override - public List getDecorators() { - return null; - } - }; - } - private ProjectAnalysisEvent projectEvent(final Project project, final boolean start) { return new ProjectAnalysisHandler.ProjectAnalysisEvent() { @Override diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java index 1fbb2ad50b4..0d2b7b7c7d6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java @@ -38,6 +38,7 @@ import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.utils.DateUtils; import org.sonar.scanner.ProjectAnalysisInfo; import org.sonar.scanner.protocol.output.FileStructure; +import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReport.Component; import org.sonar.scanner.protocol.output.ScannerReport.ComponentLink.ComponentLinkType; import org.sonar.scanner.report.ComponentsPublisher; @@ -65,6 +66,10 @@ public class ComponentsPublisherTest { writer = new ScannerReportWriter(outputDir); } + private void writeIssue(int componentId) { + writer.writeComponentIssues(componentId, Collections.singleton(ScannerReport.Issue.newBuilder().build())); + } + @Test public void add_components_to_report() throws Exception { ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class); @@ -96,10 +101,13 @@ public class ComponentsPublisherTest { DefaultInputFile file = new TestInputFileBuilder("module1", "src/Foo.java", 4).setLines(2).build(); tree.index(file, dir); - DefaultInputFile fileWithoutLang = new TestInputFileBuilder("module1", "src/make", 5).setLines(10).build(); + DefaultInputFile file2 = new TestInputFileBuilder("module1", "src/Foo2.java", 5).setPublish(false).setLines(2).build(); + tree.index(file2, dir); + + DefaultInputFile fileWithoutLang = new TestInputFileBuilder("module1", "src/make", 6).setLines(10).build(); tree.index(fileWithoutLang, dir); - DefaultInputFile testFile = new TestInputFileBuilder("module1", "test/FooTest.java", 6).setType(Type.TEST).setLines(4).build(); + DefaultInputFile testFile = new TestInputFileBuilder("module1", "test/FooTest.java", 7).setType(Type.TEST).setLines(4).build(); tree.index(testFile, dir); ComponentsPublisher publisher = new ComponentsPublisher(moduleHierarchy, tree); @@ -109,11 +117,13 @@ public class ComponentsPublisherTest { assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 2)).isTrue(); assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 3)).isTrue(); assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 4)).isTrue(); - assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 5)).isTrue(); assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 6)).isTrue(); + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 7)).isTrue(); + // not marked for publishing + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 5)).isFalse(); // no such reference - assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 7)).isFalse(); + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 8)).isFalse(); ScannerReportReader reader = new ScannerReportReader(outputDir); Component rootProtobuf = reader.readComponent(1); @@ -128,6 +138,59 @@ public class ComponentsPublisherTest { assertThat(module1Protobuf.getVersion()).isEqualTo("1.0"); } + @Test + public void should_skip_dir_without_published_files() { + ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class); + when(projectAnalysisInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); + + ProjectDefinition rootDef = ProjectDefinition.create() + .setKey("foo") + .setProperty(CoreProperties.PROJECT_VERSION_PROPERTY, "1.0") + .setName("Root project") + .setDescription("Root description"); + DefaultInputModule root = new DefaultInputModule(rootDef, 1); + + moduleHierarchy = mock(InputModuleHierarchy.class); + when(moduleHierarchy.root()).thenReturn(root); + when(moduleHierarchy.children(root)).thenReturn(Collections.emptyList()); + + // dir with files + DefaultInputDir dir = new DefaultInputDir("module1", "src", 2); + tree.index(dir, root); + + // dir without files and issues + DefaultInputDir dir2 = new DefaultInputDir("module1", "src2", 3); + tree.index(dir2, root); + + // dir without files but has issues + DefaultInputDir dir3 = new DefaultInputDir("module1", "src3", 4); + tree.index(dir3, root); + writeIssue(4); + + DefaultInputFile file = new TestInputFileBuilder("module1", "src/Foo.java", 5).setLines(2).build(); + tree.index(file, dir); + + DefaultInputFile file2 = new TestInputFileBuilder("module1", "src2/Foo2.java", 6).setPublish(false).setLines(2).build(); + tree.index(file2, dir2); + + DefaultInputFile file3 = new TestInputFileBuilder("module1", "src2/Foo3.java", 7).setPublish(false).setLines(2).build(); + tree.index(file3, dir3); + + ComponentsPublisher publisher = new ComponentsPublisher(moduleHierarchy, tree); + publisher.publish(writer); + + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isTrue(); + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 2)).isTrue(); + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 5)).isTrue(); + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 4)).isTrue(); + + // file was not marked for publishing and directory doesn't contain issues, so directory won't be included as well + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 3)).isFalse(); + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 6)).isFalse(); + assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 7)).isFalse(); + + } + @Test public void add_components_without_version_and_name() throws IOException { ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java index f6caf2f6bbd..d9a9cec17a7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java @@ -49,9 +49,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class MeasuresPublisherTest { - - private static final String FILE_KEY = "foo:src/Foo.php"; - @Rule public ExpectedException thrown = ExpectedException.none(); @@ -65,12 +62,14 @@ public class MeasuresPublisherTest { private File outputDir; private ScannerReportWriter writer; private DefaultInputFile inputFile; + private DefaultInputModule InputModule; @Before public void prepare() throws IOException { - inputFile = new TestInputFileBuilder("foo", "src/Foo.php").build(); + InputModule = new DefaultInputModule("foo"); + inputFile = new TestInputFileBuilder("foo", "src/Foo.php").setPublish(true).build(); componentCache = new InputComponentStore(); - componentCache.put(new DefaultInputModule("foo")); + componentCache.put(InputModule); componentCache.put(inputFile); measureCache = mock(MeasureCache.class); when(measureCache.byComponentKey(anyString())).thenReturn(Collections.>emptyList()); @@ -86,12 +85,12 @@ public class MeasuresPublisherTest { // String value DefaultMeasure stringMeasure = new DefaultMeasure().forMetric(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION) .withValue("foo bar"); - when(measureCache.byComponentKey(FILE_KEY)).thenReturn(asList(measure, stringMeasure)); + when(measureCache.byComponentKey(inputFile.key())).thenReturn(asList(measure, stringMeasure)); publisher.publish(writer); ScannerReportReader reader = new ScannerReportReader(outputDir); - assertThat(reader.readComponentMeasures(1)).hasSize(0); + assertThat(reader.readComponentMeasures(InputModule.batchId())).hasSize(0); try (CloseableIterator componentMeasures = reader.readComponentMeasures(inputFile.batchId())) { assertThat(componentMeasures).hasSize(2); } @@ -100,7 +99,7 @@ public class MeasuresPublisherTest { @Test public void fail_with_IAE_when_measure_has_no_value() throws Exception { DefaultMeasure measure = new DefaultMeasure().forMetric(CoreMetrics.LINES_TO_COVER); - when(measureCache.byComponentKey(FILE_KEY)).thenReturn(Collections.singletonList(measure)); + when(measureCache.byComponentKey(inputFile.key())).thenReturn(Collections.singletonList(measure)); try { publisher.publish(writer); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java index 6e5ee36b182..d2aa0ec35bf 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java @@ -61,7 +61,7 @@ public class MetadataPublisherTest { @Before public void prepare() { projectDef = ProjectDefinition.create().setKey("foo"); - rootModule = new DefaultInputModule(projectDef, TestInputFileBuilder.batchId++); + rootModule = new DefaultInputModule(projectDef, TestInputFileBuilder.nextBatchId()); projectAnalysisInfo = mock(ProjectAnalysisInfo.class); when(projectAnalysisInfo.analysisDate()).thenReturn(new Date(1234567L)); inputModuleHierarchy = mock(InputModuleHierarchy.class); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java index 8a749037dee..0dde3f3f0f6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java @@ -22,7 +22,6 @@ package org.sonar.scanner.rule; import com.google.common.collect.ImmutableList; import java.util.LinkedList; import java.util.List; -import org.apache.commons.lang.mutable.MutableBoolean; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -36,7 +35,6 @@ import org.sonar.scanner.rule.ModuleQProfiles; import org.sonarqube.ws.QualityProfiles.SearchWsResponse.QualityProfile; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultComponentTreeTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultComponentTreeTest.java new file mode 100644 index 00000000000..b799074d07d --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultComponentTreeTest.java @@ -0,0 +1,59 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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.scan; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.fs.internal.DefaultInputComponent; +import org.sonar.api.batch.fs.internal.DefaultInputModule; + +public class DefaultComponentTreeTest { + private DefaultComponentTree tree; + + @Before + public void setUp() { + tree = new DefaultComponentTree(); + } + + @Test + public void test() { + DefaultInputComponent root = new DefaultInputModule("root"); + DefaultInputComponent mod1 = new DefaultInputModule("mod1"); + DefaultInputComponent mod2 = new DefaultInputModule("mod2"); + DefaultInputComponent mod3 = new DefaultInputModule("mod3"); + DefaultInputComponent mod4 = new DefaultInputModule("mod4"); + + tree.index(mod1, root); + tree.index(mod2, mod1); + tree.index(mod3, root); + tree.index(mod4, root); + + assertThat(tree.getChildren(root)).containsOnly(mod1, mod3, mod4); + assertThat(tree.getChildren(mod4)).isEmpty(); + assertThat(tree.getChildren(mod1)).containsOnly(mod2); + + assertThat(tree.getParent(mod4)).isEqualTo(root); + assertThat(tree.getParent(mod2)).isEqualTo(mod1); + assertThat(tree.getParent(mod1)).isEqualTo(root); + assertThat(tree.getParent(root)).isNull(); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java new file mode 100644 index 00000000000..5037a273932 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java @@ -0,0 +1,61 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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.scan; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.fs.internal.DefaultInputModule; + +public class DefaultInputModuleHierarchyTest { + private DefaultInputModuleHierarchy moduleHierarchy; + + @Before + public void setUp() { + moduleHierarchy = new DefaultInputModuleHierarchy(); + } + + @Test + public void test() { + DefaultInputModule root = new DefaultInputModule("root"); + DefaultInputModule mod1 = new DefaultInputModule("mod1"); + DefaultInputModule mod2 = new DefaultInputModule("mod2"); + DefaultInputModule mod3 = new DefaultInputModule("mod3"); + DefaultInputModule mod4 = new DefaultInputModule("mod4"); + + moduleHierarchy.setRoot(root); + moduleHierarchy.index(mod1, root); + moduleHierarchy.index(mod2, mod1); + moduleHierarchy.index(mod3, root); + moduleHierarchy.index(mod4, root); + + assertThat(moduleHierarchy.children(root)).containsOnly(mod1, mod3, mod4); + assertThat(moduleHierarchy.children(mod4)).isEmpty(); + assertThat(moduleHierarchy.children(mod1)).containsOnly(mod2); + + assertThat(moduleHierarchy.parent(mod4)).isEqualTo(root); + assertThat(moduleHierarchy.parent(mod2)).isEqualTo(mod1); + assertThat(moduleHierarchy.parent(mod1)).isEqualTo(root); + assertThat(moduleHierarchy.parent(root)).isNull(); + + assertThat(moduleHierarchy.root()).isEqualTo(root); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/LanguageVerifierTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/LanguageVerifierTest.java deleted file mode 100644 index e4af7a57587..00000000000 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/LanguageVerifierTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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.scan; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.batch.fs.internal.DefaultFileSystem; -import org.sonar.api.config.Settings; -import org.sonar.api.config.MapSettings; -import org.sonar.api.resources.Languages; -import org.sonar.api.utils.MessageException; -import org.sonar.scanner.FakeJava; -import org.sonar.scanner.repository.language.DefaultLanguagesRepository; -import org.sonar.scanner.repository.language.LanguagesRepository; - -import static org.assertj.core.api.Assertions.assertThat; - -public class LanguageVerifierTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private Settings settings = new MapSettings(); - private LanguagesRepository languages = new DefaultLanguagesRepository(new Languages(FakeJava.INSTANCE)); - private DefaultFileSystem fs; - - @Before - public void prepare() throws Exception { - fs = new DefaultFileSystem(temp.newFolder().toPath()); - } - - @Test - public void language_is_not_set() { - LanguageVerifier verifier = new LanguageVerifier(settings, languages, fs); - verifier.start(); - - // no failure and no language is forced - assertThat(fs.languages()).isEmpty(); - - verifier.stop(); - } - - @Test - public void language_is_empty() { - settings.setProperty("sonar.language", ""); - LanguageVerifier verifier = new LanguageVerifier(settings, languages, fs); - verifier.start(); - - // no failure and no language is forced - assertThat(fs.languages()).isEmpty(); - - verifier.stop(); - } - - @Test - public void language_is_valid() { - settings.setProperty("sonar.language", "java"); - - LanguageVerifier verifier = new LanguageVerifier(settings, languages, fs); - verifier.start(); - - // no failure and language is hardly registered - assertThat(fs.languages()).contains("java"); - - verifier.stop(); - } - - @Test - public void language_is_not_valid() { - thrown.expect(MessageException.class); - thrown.expectMessage("You must install a plugin that supports the language 'php'"); - - settings.setProperty("sonar.language", "php"); - LanguageVerifier verifier = new LanguageVerifier(settings, languages, fs); - verifier.start(); - } -} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java new file mode 100644 index 00000000000..00d7c123bf7 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java @@ -0,0 +1,67 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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.scan; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.batch.fs.InputModule; +import org.sonar.scanner.scan.filesystem.BatchIdGenerator; + +public class ModuleIndexerTest { + private ModuleIndexer indexer; + private DefaultComponentTree tree; + private DefaultInputModuleHierarchy moduleHierarchy; + private ImmutableProjectReactor reactor; + + @Before + public void setUp() { + reactor = mock(ImmutableProjectReactor.class); + tree = new DefaultComponentTree(); + moduleHierarchy = new DefaultInputModuleHierarchy(); + indexer = new ModuleIndexer(reactor, tree, new BatchIdGenerator(), moduleHierarchy); + } + + @Test + public void testIndex() { + ProjectDefinition root = ProjectDefinition.create().setKey("root"); + ProjectDefinition mod1 = ProjectDefinition.create().setKey("mod1"); + ProjectDefinition mod2 = ProjectDefinition.create().setKey("mod2"); + ProjectDefinition mod3 = ProjectDefinition.create().setKey("mod3"); + ProjectDefinition mod4 = ProjectDefinition.create().setKey("mod4"); + + root.addSubProject(mod1); + mod1.addSubProject(mod2); + root.addSubProject(mod3); + root.addSubProject(mod4); + + when(reactor.getRoot()).thenReturn(root); + indexer.start(); + + InputModule rootModule = moduleHierarchy.root(); + assertThat(rootModule).isNotNull(); + assertThat(moduleHierarchy.children(rootModule)).hasSize(3); + assertThat(tree.getChildren(rootModule)).hasSize(3); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java index 38548c7370b..54445c639b3 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java @@ -21,24 +21,22 @@ package org.sonar.scanner.scan.filesystem; import org.junit.Test; import org.sonar.api.batch.fs.FilePredicate; -import org.sonar.api.batch.fs.IndexedFile; -import org.sonar.api.batch.fs.internal.DefaultIndexedFile; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.scanner.scan.filesystem.AdditionalFilePredicates; import static org.assertj.core.api.Assertions.assertThat; -import java.nio.file.Paths; - public class AdditionalFilePredicatesTest { @Test public void key() { FilePredicate predicate = new AdditionalFilePredicates.KeyPredicate("struts:Action.java"); - IndexedFile indexedFile = new DefaultIndexedFile("struts", Paths.get("module"), "Action.java"); - assertThat(predicate.apply(indexedFile)).isTrue(); + InputFile inputFile = new TestInputFileBuilder("struts", "Action.java").build(); + assertThat(predicate.apply(inputFile)).isTrue(); - indexedFile = new DefaultIndexedFile("struts", Paths.get("module"), "Filter.java"); - assertThat(predicate.apply(indexedFile)).isFalse(); + inputFile = new TestInputFileBuilder("struts", "Filter.java").build(); + assertThat(predicate.apply(inputFile)).isFalse(); } } 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 new file mode 100644 index 00000000000..b1c514fd1a2 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java @@ -0,0 +1,70 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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.scan.filesystem; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +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.scan.filesystem.PathResolver; + +public class InputFileBuilderTest { + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private Path baseDir; + private InputFileBuilder builder; + + @Before + public void setUp() throws IOException { + baseDir = temp.newFolder().toPath(); + DefaultInputModule module = new DefaultInputModule(ProjectDefinition.create() + .setKey("module1") + .setBaseDir(baseDir.toFile()), 0); + + PathResolver pathResolver = new PathResolver(); + LanguageDetection langDetection = mock(LanguageDetection.class); + MetadataGenerator metadataGenerator = mock(MetadataGenerator.class); + BatchIdGenerator idGenerator = new BatchIdGenerator(); + builder = new InputFileBuilder(module, pathResolver, langDetection, metadataGenerator, idGenerator); + } + + @Test + public void testBuild() { + Path filePath = baseDir.resolve("src/File1.xoo"); + DefaultInputFile inputFile = builder.create(filePath, Type.MAIN, StandardCharsets.UTF_8); + + assertThat(inputFile.moduleKey()).isEqualTo("module1"); + assertThat(inputFile.absolutePath()).isEqualTo(filePath.toString()); + assertThat(inputFile.key()).isEqualTo("module1:src/File1.xoo"); + assertThat(inputFile.publish()).isFalse(); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactoryTest.java deleted file mode 100644 index 0064dd10ebf..00000000000 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionFactoryTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * 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.scan.filesystem; - -import org.junit.Test; -import org.sonar.api.config.MapSettings; -import org.sonar.api.resources.Languages; -import org.sonar.scanner.FakeJava; -import org.sonar.scanner.repository.language.DefaultLanguagesRepository; -import org.sonar.scanner.repository.language.LanguagesRepository; - -import static org.assertj.core.api.Assertions.assertThat; - -public class LanguageDetectionFactoryTest { - @Test - public void testCreate() throws Exception { - LanguagesRepository languages = new DefaultLanguagesRepository(new Languages(FakeJava.INSTANCE)); - LanguageDetectionFactory factory = new LanguageDetectionFactory(new MapSettings(), languages); - LanguageDetection languageDetection = factory.create(); - assertThat(languageDetection).isNotNull(); - assertThat(languageDetection.patternsByLanguage()).hasSize(1); - assertThat(languageDetection.patternsByLanguage().containsKey("java")).isTrue(); - } -} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java index 874351ee3e0..c9ab6444c42 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java @@ -123,7 +123,7 @@ public class LanguageDetectionTest { @Test public void fail_if_invalid_language() { thrown.expect(MessageException.class); - thrown.expectMessage("No language is installed with key 'unknown'. Please update property 'sonar.language'"); + thrown.expectMessage("You must install a plugin that supports the language 'unknown'"); LanguagesRepository languages = new DefaultLanguagesRepository(new Languages(new MockLanguage("java", "java"), new MockLanguage("php", "php"))); Settings settings = new MapSettings(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProviderTest.java index 73f0dc3c8f7..e752025b0b6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorProviderTest.java @@ -21,6 +21,7 @@ package org.sonar.scanner.scan.filesystem; import org.junit.Test; import org.mockito.Mockito; +import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.FileMetadata; import static org.assertj.core.api.Assertions.assertThat; @@ -32,6 +33,6 @@ public class MetadataGeneratorProviderTest { StatusDetectionFactory statusDetectionFactory = mock(StatusDetectionFactory.class, Mockito.RETURNS_MOCKS); MetadataGeneratorProvider factory = new MetadataGeneratorProvider(); - assertThat(factory.provide(statusDetectionFactory, new FileMetadata())).isNotNull(); + assertThat(factory.provide(new DefaultInputModule("module"), statusDetectionFactory, new FileMetadata())).isNotNull(); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java index 17f7f61a27a..9826ce2c4ab 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java @@ -20,13 +20,11 @@ package org.sonar.scanner.scan.filesystem; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.io.File; -import java.io.FileNotFoundException; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; import org.apache.commons.io.FileUtils; import org.junit.Assert; @@ -37,13 +35,10 @@ import org.junit.rules.TemporaryFolder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; 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.FileMetadata; -import org.sonar.api.batch.fs.internal.Metadata; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; -import org.sonar.api.config.MapSettings; -import org.sonar.api.scan.filesystem.PathResolver; import org.sonar.api.utils.PathUtils; public class MetadataGeneratorTest { @@ -54,106 +49,70 @@ public class MetadataGeneratorTest { private StatusDetection statusDetection; @Mock private DefaultModuleFileSystem fs; - @Mock - private FileMetadata metadata; - private MetadataGenerator builder; + private FileMetadata metadata; + private MetadataGenerator generator; @Before public void setUp() { MockitoAnnotations.initMocks(this); - builder = new MetadataGenerator(statusDetection, metadata); - // TODO + metadata = new FileMetadata(); + generator = new MetadataGenerator(new DefaultInputModule("module"), statusDetection, metadata); + } + + @Test + public void should_detect_charset_from_BOM() { + Path basedir = Paths.get("src/test/resources/org/sonar/scanner/scan/filesystem/"); + + assertThat(createInputFileWithMetadata(generator, basedir, "without_BOM.txt").charset()) + .isEqualTo(StandardCharsets.US_ASCII); + assertThat(createInputFileWithMetadata(generator, basedir, "UTF-8.txt").charset()) + .isEqualTo(StandardCharsets.UTF_8); + assertThat(createInputFileWithMetadata(generator, basedir, "UTF-16BE.txt").charset()) + .isEqualTo(StandardCharsets.UTF_16BE); + assertThat(createInputFileWithMetadata(generator, basedir, "UTF-16LE.txt").charset()) + .isEqualTo(StandardCharsets.UTF_16LE); + assertThat(createInputFileWithMetadata(generator, basedir, "UTF-32BE.txt").charset()) + .isEqualTo(MetadataGenerator.UTF_32BE); + assertThat(createInputFileWithMetadata(generator, basedir, "UTF-32LE.txt").charset()) + .isEqualTo(MetadataGenerator.UTF_32LE); + + try { + createInputFileWithMetadata(generator, basedir, "non_existing"); + Assert.fail(); + } catch (IllegalStateException e) { + assertThat(e.getMessage()).endsWith("Unable to read file " + basedir.resolve("non_existing").toAbsolutePath()); + assertThat(e.getCause()).isInstanceOf(IllegalStateException.class); + } + } + + private DefaultInputFile createInputFileWithMetadata(MetadataGenerator generator, Path baseDir, String relativePath) { + DefaultInputFile inputFile = new TestInputFileBuilder("struts", relativePath) + .setModuleBaseDir(baseDir) + .build(); + generator.setMetadata(inputFile, StandardCharsets.US_ASCII); + return inputFile; + } + + @Test + public void complete_input_file() throws Exception { + // file system + Path baseDir = temp.newFolder().toPath(); + Path srcFile = baseDir.resolve("src/main/java/foo/Bar.java"); + FileUtils.touch(srcFile.toFile()); + FileUtils.write(srcFile.toFile(), "single line"); + + // status + when(statusDetection.status("foo", "src/main/java/foo/Bar.java", "6c1d64c0b3555892fe7273e954f6fb5a")) + .thenReturn(InputFile.Status.ADDED); + + InputFile inputFile = createInputFileWithMetadata(generator, baseDir, "src/main/java/foo/Bar.java"); + + assertThat(inputFile.type()).isEqualTo(InputFile.Type.MAIN); + assertThat(inputFile.file()).isEqualTo(srcFile.toFile()); + assertThat(inputFile.absolutePath()).isEqualTo(PathUtils.sanitize(srcFile.toAbsolutePath().toString())); + assertThat(inputFile.key()).isEqualTo("struts:src/main/java/foo/Bar.java"); + assertThat(inputFile.relativePath()).isEqualTo("src/main/java/foo/Bar.java"); + assertThat(inputFile.lines()).isEqualTo(1); } - /* - * @Test - * public void should_detect_charset_from_BOM() { - * File basedir = new File("src/test/resources/org/sonar/scanner/scan/filesystem/"); - * when(fs.baseDir()).thenReturn(basedir); - * when(fs.encoding()).thenReturn(StandardCharsets.US_ASCII); - * - * assertThat(createAndComplete(builder, new File(basedir, "without_BOM.txt")).charset()) - * .isEqualTo(StandardCharsets.US_ASCII); - * assertThat(createAndComplete(builder, new File(basedir, "UTF-8.txt")).charset()) - * .isEqualTo(StandardCharsets.UTF_8); - * assertThat(createAndComplete(builder, new File(basedir, "UTF-16BE.txt")).charset()) - * .isEqualTo(StandardCharsets.UTF_16BE); - * assertThat(createAndComplete(builder, new File(basedir, "UTF-16LE.txt")).charset()) - * .isEqualTo(StandardCharsets.UTF_16LE); - * assertThat(createAndComplete(builder, new File(basedir, "UTF-32BE.txt")).charset()) - * .isEqualTo(InputFileBuilder.UTF_32BE); - * assertThat(createAndComplete(builder, new File(basedir, "UTF-32LE.txt")).charset()) - * .isEqualTo(InputFileBuilder.UTF_32LE); - * - * try { - * createAndComplete(builder, new File(basedir, "non_existing")); - * Assert.fail(); - * } catch (IllegalStateException e) { - * assertThat(e.getMessage()).isEqualTo("Unable to read file " + new File(basedir, "non_existing").getAbsolutePath()); - * assertThat(e.getCause()).isInstanceOf(FileNotFoundException.class); - * } - * } - * - * private static DefaultInputFile createAndComplete(InputFileBuilder builder, File file) { - * DefaultInputFile inputFile = new TestInputFileBuilder("module", file.toString()) - * .setMetadata() - * .build(); - * return inputFile; - * } - * - * @Test - * public void complete_input_file() throws Exception { - * // file system - * File basedir = temp.newFolder(); - * File srcFile = new File(basedir, "src/main/java/foo/Bar.java"); - * FileUtils.touch(srcFile); - * FileUtils.write(srcFile, "single line"); - * when(fs.baseDir()).thenReturn(basedir); - * when(fs.encoding()).thenReturn(StandardCharsets.UTF_8); - * - * // status - * when(statusDetection.status("foo", "src/main/java/foo/Bar.java", "6c1d64c0b3555892fe7273e954f6fb5a")) - * .thenReturn(InputFile.Status.ADDED); - * - * Metadata metadata = builder.readMetadata(srcFile); - * builder.readMetadata(inputFile); - * - * assertThat(inputFile.type()).isEqualTo(InputFile.Type.MAIN); - * assertThat(inputFile.file()).isEqualTo(srcFile.getAbsoluteFile()); - * assertThat(inputFile.absolutePath()).isEqualTo(PathUtils.sanitize(srcFile.getAbsolutePath())); - * assertThat(inputFile.language()).isEqualTo("java"); - * assertThat(inputFile.key()).isEqualTo("struts:src/main/java/foo/Bar.java"); - * assertThat(inputFile.relativePath()).isEqualTo("src/main/java/foo/Bar.java"); - * assertThat(inputFile.lines()).isEqualTo(1); - * } - * - * @Test - * public void set_metadata() throws Exception { - * DefaultInputFile inputFile = new TestInputFileBuilder("module", "src/main/java/foo/Bar.java").build(); - * when() - * - * Metadata metadata = builder.readMetadata(inputFile); - * - * } - * - * @Test - * public void return_null_if_language_not_detected() throws Exception { - * // file system - * File basedir = temp.newFolder(); - * File srcFile = new File(basedir, "src/main/java/foo/Bar.java"); - * FileUtils.touch(srcFile); - * FileUtils.write(srcFile, "single line"); - * when(fs.baseDir()).thenReturn(basedir); - * when(fs.encoding()).thenReturn(StandardCharsets.UTF_8); - * - * // lang - * when(langDetection.language(any(DefaultIndexedFile.class))).thenReturn(null); - * - * InputFileBuilder builder = new InputFileBuilder(statusDetection, fs, new FileMetadata()); - * DefaultInputFile inputFile = builder.create(srcFile); - * inputFile = builder.completeAndComputeMetadata(inputFile, InputFile.Type.MAIN); - * - * assertThat(inputFile).isNull(); - * } - */ } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/report/JSONReportTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/report/JSONReportTest.java index 2918d4fd5e6..01cce65f395 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/report/JSONReportTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/report/JSONReportTest.java @@ -82,7 +82,7 @@ public class JSONReportTest { SIMPLE_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+02:00")); when(server.getVersion()).thenReturn("3.6"); - DefaultInputDir inputDir = new DefaultInputDir("struts", "src/main/java/org/apache/struts", TestInputFileBuilder.batchId++); + DefaultInputDir inputDir = new DefaultInputDir("struts", "src/main/java/org/apache/struts", TestInputFileBuilder.nextBatchId()); DefaultInputFile inputFile = new TestInputFileBuilder("struts", "src/main/java/org/apache/struts/Action.java").build(); inputFile.setStatus(InputFile.Status.CHANGED); InputComponentStore fileCache = mock(InputComponentStore.class); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java index 4d11247c5d4..400c16eef42 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java @@ -37,8 +37,6 @@ import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable; import org.sonar.api.config.MapSettings; import org.sonar.api.config.Settings; import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.resources.File; -import org.sonar.api.resources.Resource; import org.sonar.api.utils.KeyValueFormat; import org.sonar.core.metric.ScannerMetrics; import org.sonar.scanner.cpd.index.SonarCpdBlockIndex; @@ -105,7 +103,6 @@ public class DefaultSensorStorageTest { InputFile file = new TestInputFileBuilder("foo", "src/Foo.php").build(); ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(DefaultMeasure.class); - Resource sonarFile = File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php"); when(measureCache.put(eq(file.key()), eq(CoreMetrics.NCLOC_KEY), argumentCaptor.capture())).thenReturn(null); underTest.store(new DefaultMeasure() .on(file) diff --git a/sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/output/FileStructure.java b/sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/output/FileStructure.java index 5d408aef691..34fbc34a9b0 100644 --- a/sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/output/FileStructure.java +++ b/sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/output/FileStructure.java @@ -78,4 +78,8 @@ public class FileStructure { public File contextProperties() { return new File(dir, "context-props.pb"); } + + public File root() { + return dir; + } } -- 2.39.5