diff options
40 files changed, 541 insertions, 571 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java index 62de7d120f8..adde73809f6 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java @@ -29,7 +29,7 @@ import org.sonar.api.batch.fs.InputFile; */ public class SensorStrategy { - private boolean global = false; + private boolean global = true; public boolean isGlobal() { return global; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJob.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJob.java index 659cdbf88e8..facf976fc6f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJob.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJob.java @@ -20,7 +20,7 @@ package org.sonar.api.batch.postjob; import org.sonar.api.ExtensionPoint; -import org.sonar.api.batch.ScannerSide; +import org.sonar.api.scanner.ScannerSide; /** * PostJobs are executed at the very end of scanner analysis. A PostJob can't do any modification @@ -29,6 +29,7 @@ import org.sonar.api.batch.ScannerSide; * asynchronous process to compute data on server side in 5.x series. * * @since 5.2 + * @since 7.6 postjobs are loaded in the project container */ @ScannerSide @ExtensionPoint diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/scm/BlameCommand.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/scm/BlameCommand.java index 5fd89b5bb55..c31fe6c8b34 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/scm/BlameCommand.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/scm/BlameCommand.java @@ -19,18 +19,15 @@ */ package org.sonar.api.batch.scm; -import org.sonar.api.batch.ScannerSide; -import org.sonar.api.batch.InstantiationStrategy; +import java.util.List; +import org.sonar.api.scanner.ScannerSide; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; -import java.util.List; - /** * This class should be implemented by SCM providers. * @since 5.0 */ -@InstantiationStrategy(InstantiationStrategy.PER_BATCH) @ScannerSide public abstract class BlameCommand { 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 c5e84f19f33..420f433557b 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 @@ -87,6 +87,7 @@ public class DefaultInputFileTest { assertThat(inputFile.getModuleRelativePath()).isEqualTo(MODULE_RELATIVE_PATH); assertThat(inputFile.getProjectRelativePath()).isEqualTo(PROJECT_RELATIVE_PATH); + sensorStrategy.setGlobal(false); assertThat(inputFile.relativePath()).isEqualTo(MODULE_RELATIVE_PATH); assertThat(new File(inputFile.relativePath())).isRelative(); sensorStrategy.setGlobal(true); 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/AbstractExtensionDictionnary.java index e8e9d81e3fc..811a6569695 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/AbstractExtensionDictionnary.java @@ -33,36 +33,16 @@ import org.apache.commons.lang.ClassUtils; import org.sonar.api.batch.DependedUpon; import org.sonar.api.batch.DependsUpon; import org.sonar.api.batch.Phase; -import org.sonar.api.batch.postjob.PostJob; -import org.sonar.api.batch.postjob.PostJobContext; -import org.sonar.api.batch.sensor.Sensor; -import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.utils.AnnotationUtils; import org.sonar.api.utils.dag.DirectAcyclicGraph; import org.sonar.core.platform.ComponentContainer; -import org.sonar.scanner.postjob.PostJobOptimizer; -import org.sonar.scanner.postjob.PostJobWrapper; -import org.sonar.scanner.sensor.SensorOptimizer; -import org.sonar.scanner.sensor.SensorWrapper; -/** - * @since 2.6 - */ -public class ScannerExtensionDictionnary { +public abstract class AbstractExtensionDictionnary { private final ComponentContainer componentContainer; - private final SensorContext sensorContext; - private final SensorOptimizer sensorOptimizer; - private final PostJobOptimizer postJobOptimizer; - private final PostJobContext postJobContext; - public ScannerExtensionDictionnary(ComponentContainer componentContainer, SensorContext sensorContext, SensorOptimizer sensorOptimizer, - PostJobOptimizer postJobOptimizer, PostJobContext postJobContext) { + public AbstractExtensionDictionnary(ComponentContainer componentContainer) { this.componentContainer = componentContainer; - this.sensorContext = sensorContext; - this.sensorOptimizer = sensorOptimizer; - this.postJobOptimizer = postJobOptimizer; - this.postJobContext = postJobContext; } public <T> Collection<T> select(Class<T> type, boolean sort, @Nullable ExtensionMatcher matcher) { @@ -73,22 +53,6 @@ public class ScannerExtensionDictionnary { return result; } - public Collection<SensorWrapper> selectSensors(boolean global) { - Collection<Sensor> result = sort(getFilteredExtensions(Sensor.class, null)); - return result.stream() - .map(s -> new SensorWrapper(s, sensorContext, sensorOptimizer)) - .filter(s -> global == s.isGlobal() && s.shouldExecute()) - .collect(Collectors.toList()); - } - - public Collection<PostJobWrapper> selectPostJobs() { - Collection<PostJob> result = sort(getFilteredExtensions(PostJob.class, null)); - return result.stream() - .map(j -> new PostJobWrapper(j, postJobContext, postJobOptimizer)) - .filter(PostJobWrapper::shouldExecute) - .collect(Collectors.toList()); - } - private static Phase.Name evaluatePhase(Object extension) { Phase phaseAnnotation = AnnotationUtils.getAnnotation(extension, Phase.class); if (phaseAnnotation != null) { @@ -97,7 +61,7 @@ public class ScannerExtensionDictionnary { return Phase.Name.DEFAULT; } - private <T> List<T> getFilteredExtensions(Class<T> type, @Nullable ExtensionMatcher matcher) { + protected <T> List<T> getFilteredExtensions(Class<T> type, @Nullable ExtensionMatcher matcher) { List<T> result = new ArrayList<>(); for (Object extension : getExtensions(type)) { @@ -122,7 +86,7 @@ public class ScannerExtensionDictionnary { } } - private <T> Collection<T> sort(Collection<T> extensions) { + protected <T> Collection<T> sort(Collection<T> extensions) { DirectAcyclicGraph dag = new DirectAcyclicGraph(); for (T extension : extensions) { 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 c6b844a78c3..d5487c990ca 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 @@ -31,8 +31,6 @@ import org.sonar.scanner.genericcoverage.GenericTestExecutionSensor; import org.sonar.scanner.issue.tracking.ServerIssueFromWs; import org.sonar.scanner.issue.tracking.TrackedIssue; import org.sonar.scanner.scan.report.JSONReport; -import org.sonar.scanner.scm.ScmConfiguration; -import org.sonar.scanner.scm.ScmPublisher; import org.sonar.scanner.source.ZeroCoverageSensor; public class BatchComponents { @@ -45,10 +43,6 @@ public class BatchComponents { DefaultResourceTypes.get()); components.addAll(CorePropertyDefinitions.all()); if (!analysisMode.isIssues()) { - // SCM - components.add(ScmConfiguration.class); - components.add(ScmPublisher.class); - components.add(ZeroCoverageSensor.class); // Generic coverage diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionnary.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionnary.java new file mode 100644 index 00000000000..3994149dd2f --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionnary.java @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.bootstrap; + +import java.util.Collection; +import java.util.stream.Collectors; +import org.sonar.api.batch.postjob.PostJob; +import org.sonar.api.batch.postjob.PostJobContext; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.scanner.postjob.PostJobOptimizer; +import org.sonar.scanner.postjob.PostJobWrapper; + +public class PostJobExtensionDictionnary extends AbstractExtensionDictionnary { + + private final PostJobContext postJobContext; + private final PostJobOptimizer postJobOptimizer; + + public PostJobExtensionDictionnary(ComponentContainer componentContainer, PostJobOptimizer postJobOptimizer, PostJobContext postJobContext) { + super(componentContainer); + this.postJobOptimizer = postJobOptimizer; + this.postJobContext = postJobContext; + } + + public Collection<PostJobWrapper> selectPostJobs() { + Collection<PostJob> result = sort(getFilteredExtensions(PostJob.class, null)); + return result.stream() + .map(j -> new PostJobWrapper(j, postJobContext, postJobOptimizer)) + .filter(PostJobWrapper::shouldExecute) + .collect(Collectors.toList()); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SensorExtensionDictionnary.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SensorExtensionDictionnary.java new file mode 100644 index 00000000000..34ac2dd1105 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SensorExtensionDictionnary.java @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.bootstrap; + +import java.util.Collection; +import java.util.stream.Collectors; +import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.scanner.sensor.SensorOptimizer; +import org.sonar.scanner.sensor.SensorWrapper; + +public class SensorExtensionDictionnary extends AbstractExtensionDictionnary { + + private final SensorContext sensorContext; + private final SensorOptimizer sensorOptimizer; + + public SensorExtensionDictionnary(ComponentContainer componentContainer, SensorContext sensorContext, SensorOptimizer sensorOptimizer) { + super(componentContainer); + this.sensorContext = sensorContext; + this.sensorOptimizer = sensorOptimizer; + } + + public Collection<SensorWrapper> selectSensors(boolean global) { + Collection<Sensor> result = sort(getFilteredExtensions(Sensor.class, null)); + return result.stream() + .map(s -> new SensorWrapper(s, sensorContext, sensorOptimizer)) + .filter(s -> global == s.isGlobal() && s.shouldExecute()) + .collect(Collectors.toList()); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java index db4f0787172..5f15ca7bd31 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java @@ -82,7 +82,7 @@ public class AnalysisResult implements AnalysisObserver { private void storeFs(ProjectScanContainer container) { InputComponentStore inputFileCache = container.getComponentByType(InputComponentStore.class); - for (InputFile inputPath : inputFileCache.allFiles()) { + for (InputFile inputPath : inputFileCache.inputFiles()) { inputFilesByKeys.put(((DefaultInputFile) inputPath).getProjectRelativePath(), inputPath); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractCoverageExclusions.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractCoverageExclusions.java index 0690f02f539..a47155b9b99 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractCoverageExclusions.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractCoverageExclusions.java @@ -29,7 +29,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.config.Configuration; import org.sonar.api.utils.WildcardPattern; @Immutable @@ -40,10 +39,10 @@ public abstract class AbstractCoverageExclusions { private Collection<WildcardPattern> exclusionPatterns; - public AbstractCoverageExclusions(Configuration config, Function<DefaultInputFile, String> pathExtractor) { + public AbstractCoverageExclusions(Function<String, String[]> configProvider, Function<DefaultInputFile, String> pathExtractor) { this.pathExtractor = pathExtractor; Builder<WildcardPattern> builder = ImmutableList.builder(); - coverageExclusionConfig = config.getStringArray(CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY); + coverageExclusionConfig = configProvider.apply(CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY); for (String pattern : coverageExclusionConfig) { builder.add(WildcardPattern.create(pattern)); } @@ -60,7 +59,7 @@ public abstract class AbstractCoverageExclusions { } } - boolean isExcluded(DefaultInputFile file) { + public boolean isExcluded(DefaultInputFile file) { boolean found = false; Iterator<WildcardPattern> iterator = exclusionPatterns.iterator(); while (!found && iterator.hasNext()) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractModulePhaseExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractModulePhaseExecutor.java deleted file mode 100644 index 0737c2e594f..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/AbstractModulePhaseExecutor.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info 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.phases; - -import java.util.Arrays; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.batch.fs.internal.AbstractProjectOrModule; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.fs.internal.DefaultInputModule; -import org.sonar.api.batch.fs.internal.InputModuleHierarchy; -import org.sonar.api.notifications.AnalysisWarnings; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader; -import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; - -public abstract class AbstractModulePhaseExecutor { - - private static final Logger LOG = Loggers.get(AbstractModulePhaseExecutor.class); - - private final PostJobsExecutor postJobsExecutor; - private final SensorsExecutor sensorsExecutor; - private final DefaultModuleFileSystem fs; - private final IssueExclusionsLoader issueExclusionsLoader; - private final InputModuleHierarchy hierarchy; - private final ModuleCoverageExclusions moduleCoverageExclusions; - private final ProjectCoverageExclusions projectCoverageExclusions; - private final AnalysisWarnings analysisWarnings; - private boolean warnCoverageAlreadyLogged; - - public AbstractModulePhaseExecutor(PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, InputModuleHierarchy hierarchy, DefaultModuleFileSystem fs, - IssueExclusionsLoader issueExclusionsLoader, - ModuleCoverageExclusions moduleCoverageExclusions, ProjectCoverageExclusions projectCoverageExclusions, - AnalysisWarnings analysisWarnings) { - this.postJobsExecutor = postJobsExecutor; - this.sensorsExecutor = sensorsExecutor; - this.fs = fs; - this.issueExclusionsLoader = issueExclusionsLoader; - this.hierarchy = hierarchy; - this.moduleCoverageExclusions = moduleCoverageExclusions; - this.projectCoverageExclusions = projectCoverageExclusions; - this.analysisWarnings = analysisWarnings; - } - - /** - * Executed on each module - */ - public final void execute(DefaultInputModule module) { - // Initialize coverage exclusions - evaluateCoverageExclusions(module); - - sensorsExecutor.execute(); - - afterSensors(); - - if (hierarchy.isRoot(module)) { - executeOnRoot(); - postJobsExecutor.execute(); - } - } - - private void evaluateCoverageExclusions(AbstractProjectOrModule module) { - if (!Arrays.equals(moduleCoverageExclusions.getCoverageExclusionConfig(), projectCoverageExclusions.getCoverageExclusionConfig())) { - moduleCoverageExclusions.log(); - } - for (InputFile inputFile : fs.inputFiles(fs.predicates().all())) { - boolean excludedByProjectConfiguration = projectCoverageExclusions.isExcluded((DefaultInputFile) inputFile); - if (excludedByProjectConfiguration) { - ((DefaultInputFile) inputFile).setExcludedForCoverage(true); - LOG.debug("File {} excluded for coverage", inputFile); - continue; - } - boolean excludedByModuleConfig = moduleCoverageExclusions.isExcluded((DefaultInputFile) inputFile); - if (excludedByModuleConfig) { - ((DefaultInputFile) inputFile).setExcludedForCoverage(true); - if (Arrays.equals(moduleCoverageExclusions.getCoverageExclusionConfig(), projectCoverageExclusions.getCoverageExclusionConfig())) { - warnOnce("File '" + inputFile + "' was excluded from coverage because patterns are still evaluated using module relative paths but this is deprecated. " + - "Please update '" + CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY + "' configuration so that patterns refer to project relative paths"); - } else { - warnOnce("Defining coverage exclusions at module level is deprecated. " + - "Move '" + CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY + "' from module '" + module.getName() + "' " + - "to the root project and update patterns to refer to project relative paths"); - } - LOG.debug("File {} excluded for coverage", inputFile); - } - } - - } - - private void warnOnce(String msg) { - if (!warnCoverageAlreadyLogged) { - LOG.warn(msg); - analysisWarnings.addUnique(msg); - warnCoverageAlreadyLogged = true; - } - } - - protected void afterSensors() { - } - - protected abstract void executeOnRoot(); - -} 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 deleted file mode 100644 index 9c7e956364c..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/IssuesPhaseExecutor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info 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.phases; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.fs.internal.InputModuleHierarchy; -import org.sonar.api.notifications.AnalysisWarnings; -import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader; -import org.sonar.scanner.issue.tracking.IssueTransition; -import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; -import org.sonar.scanner.scan.report.IssuesReports; - -public final class IssuesPhaseExecutor extends AbstractModulePhaseExecutor { - - private static final Logger LOG = LoggerFactory.getLogger(IssuesPhaseExecutor.class); - - private final IssuesReports issuesReport; - private final IssueTransition localIssueTracking; - - public IssuesPhaseExecutor(PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, - IssuesReports jsonReport, DefaultModuleFileSystem fs, - IssueExclusionsLoader issueExclusionsLoader, IssueTransition localIssueTracking, InputModuleHierarchy moduleHierarchy, - ModuleCoverageExclusions moduleCoverageExclusions, ProjectCoverageExclusions projectCoverageExclusions, - AnalysisWarnings analysisWarnings) { - super(postJobsExecutor, sensorsExecutor, moduleHierarchy, fs, issueExclusionsLoader, - moduleCoverageExclusions, projectCoverageExclusions, analysisWarnings); - this.issuesReport = jsonReport; - this.localIssueTracking = localIssueTracking; - } - - @Override - protected void executeOnRoot() { - localIssueTracking.execute(); - issuesReport.execute(); - LOG.info("ANALYSIS SUCCESSFUL"); - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/ModuleCoverageExclusions.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/ModuleCoverageExclusions.java index dd00766cfe7..ae264222e19 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/ModuleCoverageExclusions.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/ModuleCoverageExclusions.java @@ -21,12 +21,17 @@ package org.sonar.scanner.phases; import javax.annotation.concurrent.Immutable; import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.scanner.scan.ModuleConfiguration; +import org.sonar.api.batch.fs.internal.DefaultInputModule; + +import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv; @Immutable public class ModuleCoverageExclusions extends AbstractCoverageExclusions { - public ModuleCoverageExclusions(ModuleConfiguration config) { - super(config, DefaultInputFile::getModuleRelativePath); + public ModuleCoverageExclusions(DefaultInputModule module) { + super(k -> { + String value = module.properties().get(k); + return value != null ? parseAsCsv(k, value) : new String[0]; + }, DefaultInputFile::getModuleRelativePath); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/ProjectCoverageExclusions.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/ProjectCoverageExclusions.java index c3167b2adcd..e6ba6a10753 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/ProjectCoverageExclusions.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/ProjectCoverageExclusions.java @@ -27,7 +27,7 @@ import org.sonar.scanner.scan.ProjectConfiguration; public class ProjectCoverageExclusions extends AbstractCoverageExclusions { public ProjectCoverageExclusions(ProjectConfiguration projectConfig) { - super(projectConfig, DefaultInputFile::getProjectRelativePath); + super(projectConfig::getStringArray, DefaultInputFile::getProjectRelativePath); log(); } } 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 deleted file mode 100644 index 6411b5b2309..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PublishPhaseExecutor.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info 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.phases; - -import org.sonar.api.batch.fs.internal.InputModuleHierarchy; -import org.sonar.api.notifications.AnalysisWarnings; -import org.sonar.scanner.cpd.CpdExecutor; -import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader; -import org.sonar.scanner.report.ReportPublisher; -import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; -import org.sonar.scanner.scm.ScmPublisher; - -public final class PublishPhaseExecutor extends AbstractModulePhaseExecutor { - - private final ReportPublisher reportPublisher; - private final CpdExecutor cpdExecutor; - private final ScmPublisher scm; - - public PublishPhaseExecutor(PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, - ReportPublisher reportPublisher, DefaultModuleFileSystem fs, IssueExclusionsLoader issueExclusionsLoader, - CpdExecutor cpdExecutor, ScmPublisher scm, InputModuleHierarchy hierarchy, - ModuleCoverageExclusions moduleCoverageExclusions, ProjectCoverageExclusions projectCoverageExclusions, - AnalysisWarnings analysisWarnings) { - super(postJobsExecutor, sensorsExecutor, hierarchy, fs, issueExclusionsLoader, moduleCoverageExclusions, - projectCoverageExclusions, analysisWarnings); - this.reportPublisher = reportPublisher; - this.cpdExecutor = cpdExecutor; - this.scm = scm; - } - - @Override - protected void executeOnRoot() { - cpdExecutor.execute(); - reportPublisher.execute(); - } - - @Override - protected void afterSensors() { - scm.publish(); - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java index 94515124d0c..002ebf4207a 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java @@ -23,27 +23,25 @@ import java.util.ArrayList; import java.util.Collection; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.InputModuleHierarchy; import org.sonar.api.batch.fs.internal.SensorStrategy; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.core.util.logs.Profiler; -import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; +import org.sonar.scanner.bootstrap.SensorExtensionDictionnary; import org.sonar.scanner.bootstrap.ScannerPluginRepository; import org.sonar.scanner.sensor.SensorWrapper; -@ScannerSide public class SensorsExecutor { private static final Logger LOG = Loggers.get(SensorsExecutor.class); private static final Profiler profiler = Profiler.create(LOG); - private final ScannerExtensionDictionnary selector; + private final SensorExtensionDictionnary selector; private final SensorStrategy strategy; private final ScannerPluginRepository pluginRepo; private final boolean isRoot; - public SensorsExecutor(ScannerExtensionDictionnary selector, DefaultInputModule module, InputModuleHierarchy hierarchy, + public SensorsExecutor(SensorExtensionDictionnary selector, DefaultInputModule module, InputModuleHierarchy hierarchy, SensorStrategy strategy, ScannerPluginRepository pluginRepo) { this.selector = selector; this.strategy = strategy; @@ -52,17 +50,18 @@ public class SensorsExecutor { } public void execute() { - Collection<SensorWrapper> moduleSensors = selector.selectSensors(false); + Collection<SensorWrapper> moduleSensors = new ArrayList<>(); + withModuleStrategy(() -> moduleSensors.addAll(selector.selectSensors(false))); Collection<SensorWrapper> globalSensors = new ArrayList<>(); if (isRoot) { - withGlobalStrategy(() -> globalSensors.addAll(selector.selectSensors(true))); + globalSensors.addAll(selector.selectSensors(true)); } printSensors(moduleSensors, globalSensors); - execute(moduleSensors); + withModuleStrategy(() -> execute(moduleSensors)); if (isRoot) { - withGlobalStrategy(() -> execute(globalSensors)); + execute(globalSensors); } } @@ -74,9 +73,9 @@ public class SensorsExecutor { LOG.debug("Sensors : {}", sensors); } - private void withGlobalStrategy(Runnable r) { + private void withModuleStrategy(Runnable r) { boolean orig = strategy.isGlobal(); - strategy.setGlobal(true); + strategy.setGlobal(false); r.run(); strategy.setGlobal(orig); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/PostJobWrapper.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/PostJobWrapper.java index 4b8e7b3772f..408ad6385c0 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/PostJobWrapper.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/PostJobWrapper.java @@ -35,6 +35,9 @@ public class PostJobWrapper { this.optimizer = optimizer; this.descriptor = new DefaultPostJobDescriptor(); newPostJob.describe(descriptor); + if (descriptor.name() == null) { + descriptor.name(newPostJob.getClass().getName()); + } this.adaptor = adaptor; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PostJobsExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/PostJobsExecutor.java index 0ceea0050e7..0b5a7608c75 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PostJobsExecutor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/PostJobsExecutor.java @@ -17,23 +17,20 @@ * 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.phases; +package org.sonar.scanner.postjob; import java.util.Collection; import java.util.stream.Collectors; -import org.sonar.api.batch.ScannerSide; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; -import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; -import org.sonar.scanner.postjob.PostJobWrapper; +import org.sonar.scanner.bootstrap.PostJobExtensionDictionnary; -@ScannerSide public class PostJobsExecutor { private static final Logger LOG = Loggers.get(PostJobsExecutor.class); - private final ScannerExtensionDictionnary selector; + private final PostJobExtensionDictionnary selector; - public PostJobsExecutor(ScannerExtensionDictionnary selector) { + public PostJobsExecutor(PostJobExtensionDictionnary selector) { this.selector = selector; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java index 271b84bceee..8a7d8c7f1e0 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java @@ -41,7 +41,7 @@ import org.sonarqube.ws.client.WsResponse; public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoader { private static final Logger LOG = LoggerFactory.getLogger(DefaultProjectRepositoriesLoader.class); private static final String BATCH_PROJECT_URL = "/batch/project.protobuf"; - private ScannerWsClient wsClient; + private final ScannerWsClient wsClient; public DefaultProjectRepositoriesLoader(ScannerWsClient wsClient) { this.wsClient = wsClient; @@ -91,7 +91,7 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad return false; } - private static ProjectRepositories processStream(InputStream is, String projectKey) { + private ProjectRepositories processStream(InputStream is, String projectKey) { try { WsProjectResponse response = WsProjectResponse.parseFrom(is); if (response.getFileDataByModuleAndPathCount() == 0) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/QProfileVerifier.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/QProfileVerifier.java index b7ca1259396..3d86c58e476 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/QProfileVerifier.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/QProfileVerifier.java @@ -51,7 +51,7 @@ public class QProfileVerifier { void execute(Logger logger) { String defaultName = config.get(QualityProfiles.SONAR_PROFILE_PROP).orElse(null); boolean defaultNameUsed = StringUtils.isBlank(defaultName); - for (String lang : store.getLanguages()) { + for (String lang : store.languages()) { QProfile profile = profiles.findByLanguage(lang); if (profile == null) { logger.warn("No Quality profile found for language {}", lang); @@ -62,7 +62,7 @@ public class QProfileVerifier { } } } - if (!defaultNameUsed && !store.getLanguages().isEmpty()) { + if (!defaultNameUsed && !store.languages().isEmpty()) { throw MessageException.of("sonar.profile was set to '" + defaultName + "' but didn't match any profile for any language. Please check your configuration."); } } 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 1530412636a..7ae65e8419c 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 @@ -27,23 +27,14 @@ import org.sonar.core.extension.CoreExtensionsInstaller; import org.sonar.core.platform.ComponentContainer; import org.sonar.scanner.DefaultFileLinesContextFactory; import org.sonar.scanner.bootstrap.ExtensionInstaller; -import org.sonar.scanner.bootstrap.GlobalAnalysisMode; -import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; +import org.sonar.scanner.bootstrap.SensorExtensionDictionnary; import org.sonar.scanner.deprecated.perspectives.ScannerPerspectives; import org.sonar.scanner.issue.ModuleIssueFilters; import org.sonar.scanner.issue.ModuleIssues; -import org.sonar.scanner.phases.AbstractModulePhaseExecutor; -import org.sonar.scanner.phases.IssuesPhaseExecutor; import org.sonar.scanner.phases.ModuleCoverageExclusions; -import org.sonar.scanner.phases.PostJobsExecutor; -import org.sonar.scanner.phases.PublishPhaseExecutor; import org.sonar.scanner.phases.SensorsExecutor; -import org.sonar.scanner.postjob.DefaultPostJobContext; -import org.sonar.scanner.postjob.PostJobOptimizer; -import org.sonar.scanner.rule.QProfileVerifier; import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore; -import org.sonar.scanner.scan.report.IssuesReports; import org.sonar.scanner.sensor.DefaultSensorContext; import org.sonar.scanner.sensor.DefaultSensorStorage; import org.sonar.scanner.sensor.SensorOptimizer; @@ -56,12 +47,10 @@ import static org.sonar.scanner.bootstrap.ExtensionUtils.isInstantiationStrategy public class ModuleScanContainer extends ComponentContainer { private static final Logger LOG = LoggerFactory.getLogger(ModuleScanContainer.class); private final DefaultInputModule module; - private final GlobalAnalysisMode analysisMode; - public ModuleScanContainer(ProjectScanContainer parent, DefaultInputModule module, GlobalAnalysisMode analysisMode) { + public ModuleScanContainer(ProjectScanContainer parent, DefaultInputModule module) { super(parent); this.module = module; - this.analysisMode = analysisMode; } @Override @@ -76,19 +65,8 @@ public class ModuleScanContainer extends ComponentContainer { module.definition(), module, MutableModuleSettings.class, - new ModuleConfigurationProvider()); + new ModuleConfigurationProvider(), - if (analysisMode.isIssues()) { - add( - IssuesPhaseExecutor.class, - IssuesReports.class); - } else { - add( - PublishPhaseExecutor.class); - } - - add( - PostJobsExecutor.class, SensorsExecutor.class, // file system @@ -97,12 +75,10 @@ public class ModuleScanContainer extends ComponentContainer { DefaultModuleFileSystem.class, SensorOptimizer.class, - PostJobOptimizer.class, - DefaultPostJobContext.class, DefaultSensorStorage.class, DefaultSensorContext.class, - ScannerExtensionDictionnary.class, + SensorExtensionDictionnary.class, ModuleIssueFilters.class, ModuleCoverageExclusions.class, @@ -124,7 +100,7 @@ public class ModuleScanContainer extends ComponentContainer { @Override protected void doAfterStart() { - getComponentByType(AbstractModulePhaseExecutor.class).execute(module); + getComponentByType(SensorsExecutor.class).execute(); } } 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 baef9c2cac4..318e6af23d0 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 @@ -43,6 +43,7 @@ import org.sonar.scanner.bootstrap.ExtensionInstaller; import org.sonar.scanner.bootstrap.ExtensionMatcher; import org.sonar.scanner.bootstrap.GlobalAnalysisMode; import org.sonar.scanner.bootstrap.MetricProvider; +import org.sonar.scanner.bootstrap.PostJobExtensionDictionnary; import org.sonar.scanner.cpd.CpdExecutor; import org.sonar.scanner.cpd.CpdSettings; import org.sonar.scanner.cpd.JavaCpdBlockIndexerSensor; @@ -65,6 +66,9 @@ import org.sonar.scanner.issue.tracking.ServerLineHashesLoader; import org.sonar.scanner.mediumtest.AnalysisObservers; import org.sonar.scanner.notifications.DefaultAnalysisWarnings; import org.sonar.scanner.phases.ProjectCoverageExclusions; +import org.sonar.scanner.postjob.DefaultPostJobContext; +import org.sonar.scanner.postjob.PostJobOptimizer; +import org.sonar.scanner.postjob.PostJobsExecutor; import org.sonar.scanner.report.ActiveRulesPublisher; import org.sonar.scanner.report.AnalysisContextReportPublisher; import org.sonar.scanner.report.AnalysisWarningsPublisher; @@ -100,6 +104,7 @@ import org.sonar.scanner.scan.branch.BranchConfigurationProvider; import org.sonar.scanner.scan.branch.BranchType; import org.sonar.scanner.scan.branch.ProjectBranchesProvider; import org.sonar.scanner.scan.branch.ProjectPullRequestsProvider; +import org.sonar.scanner.scan.filesystem.DefaultProjectFileSystem; import org.sonar.scanner.scan.filesystem.FileIndexer; import org.sonar.scanner.scan.filesystem.InputComponentStore; import org.sonar.scanner.scan.filesystem.LanguageDetection; @@ -110,7 +115,10 @@ import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator; import org.sonar.scanner.scan.filesystem.StatusDetection; import org.sonar.scanner.scan.measure.DefaultMetricFinder; import org.sonar.scanner.scan.measure.MeasureCache; +import org.sonar.scanner.scan.report.JSONReport; import org.sonar.scanner.scm.ScmChangedFilesProvider; +import org.sonar.scanner.scm.ScmConfiguration; +import org.sonar.scanner.scm.ScmPublisher; import org.sonar.scanner.storage.Storages; import static org.sonar.api.batch.InstantiationStrategy.PER_BATCH; @@ -183,7 +191,6 @@ public class ProjectScanContainer extends ComponentContainer { ProjectFileIndexer.class, ProjectExclusionFilters.class, - // rules new ActiveRulesProvider(), new QualityProfilesProvider(), @@ -246,6 +253,19 @@ public class ProjectScanContainer extends ComponentContainer { SonarCpdBlockIndex.class, JavaCpdBlockIndexerSensor.class, + // PostJobs + PostJobsExecutor.class, + PostJobOptimizer.class, + DefaultPostJobContext.class, + PostJobExtensionDictionnary.class, + + // SCM + ScmConfiguration.class, + ScmPublisher.class, + + // Filesystem + DefaultProjectFileSystem.class, + AnalysisObservers.class); addIfMissing(DefaultRulesLoader.class, RulesLoader.class); @@ -323,7 +343,21 @@ public class ProjectScanContainer extends ComponentContainer { getComponentByType(QProfileVerifier.class).execute(); LOG.debug("Start recursive analysis of project modules"); - scanRecursively(tree, tree.root(), analysisMode); + scanRecursively(tree, tree.root()); + + getComponentByType(ScmPublisher.class).publish(); + + if (analysisMode.isIssues()) { + getComponentByType(IssueTransition.class).execute(); + getComponentByType(JSONReport.class).execute(); + } else { + getComponentByType(CpdExecutor.class).execute(); + getComponentByType(ReportPublisher.class).execute(); + } + + getComponentByType(PostJobsExecutor.class).execute(); + + LOG.info("ANALYSIS SUCCESSFUL"); if (analysisMode.isMediumTest()) { getComponentByType(AnalysisObservers.class).notifyEndOfScanTask(); @@ -345,16 +379,16 @@ public class ProjectScanContainer extends ComponentContainer { } } - private void scanRecursively(InputModuleHierarchy tree, DefaultInputModule module, GlobalAnalysisMode analysisMode) { + private void scanRecursively(InputModuleHierarchy tree, DefaultInputModule module) { for (DefaultInputModule child : tree.children(module)) { - scanRecursively(tree, child, analysisMode); + scanRecursively(tree, child); } - scan(module, analysisMode); + scan(module); } @VisibleForTesting - void scan(DefaultInputModule module, GlobalAnalysisMode analysisMode) { - new ModuleScanContainer(this, module, analysisMode).execute(); + void scan(DefaultInputModule module) { + new ModuleScanContainer(this, module).execute(); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultProjectFileSystem.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultProjectFileSystem.java new file mode 100644 index 00000000000..5c4292205ab --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultProjectFileSystem.java @@ -0,0 +1,51 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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 com.google.common.annotations.VisibleForTesting; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.fs.internal.DefaultInputProject; +import org.sonar.scanner.analysis.DefaultAnalysisMode; + +public class DefaultProjectFileSystem extends DefaultFileSystem { + + public DefaultProjectFileSystem(InputComponentStore inputComponentStore, DefaultInputProject project, DefaultAnalysisMode mode, + StatusDetection statusDetection) { + super(project.getBaseDir(), inputComponentStore); + setFields(project, mode, statusDetection); + } + + @VisibleForTesting + public DefaultProjectFileSystem(DefaultInputProject project, DefaultAnalysisMode mode, StatusDetection statusDetection) { + super(project.getBaseDir()); + setFields(project, mode, statusDetection); + } + + private void setFields(DefaultInputProject project, DefaultAnalysisMode mode, StatusDetection statusDetection) { + setWorkDir(project.getWorkDir()); + setEncoding(project.getEncoding()); + + // filter the files sensors have access to + if (!mode.scanAllFiles()) { + setDefaultPredicate(p -> new SameInputFilePredicate(p, statusDetection, project.definition().getKeyWithBranch())); + } + } + +} 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 86c11738f1b..801a68e4070 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 @@ -22,7 +22,9 @@ package org.sonar.scanner.scan.filesystem; import java.io.IOException; import java.nio.file.LinkOption; import java.nio.file.Path; +import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; +import org.sonar.api.CoreProperties; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile.Type; import org.sonar.api.batch.fs.InputFileFilter; @@ -36,6 +38,8 @@ import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader; +import org.sonar.scanner.phases.ModuleCoverageExclusions; +import org.sonar.scanner.phases.ProjectCoverageExclusions; import org.sonar.scanner.scan.ScanProperties; import org.sonar.scanner.util.ProgressReport; @@ -49,6 +53,7 @@ public class FileIndexer { private final ScanProperties properties; private final InputFileFilter[] filters; private final ProjectExclusionFilters projectExclusionFilters; + private final ProjectCoverageExclusions projectCoverageExclusions; private final IssueExclusionsLoader issueExclusionsLoader; private final MetadataGenerator metadataGenerator; private final DefaultInputProject project; @@ -58,15 +63,16 @@ public class FileIndexer { private final LanguageDetection langDetection; private boolean warnExclusionsAlreadyLogged; + private boolean warnCoverageExclusionsAlreadyLogged; - public FileIndexer(DefaultInputProject project, ScannerComponentIdGenerator scannerComponentIdGenerator, InputComponentStore componentStore, ProjectExclusionFilters projectExclusionFilters, - IssueExclusionsLoader issueExclusionsLoader, - MetadataGenerator metadataGenerator, SensorStrategy sensorStrategy, - LanguageDetection languageDetection, AnalysisWarnings analysisWarnings, ScanProperties properties, + public FileIndexer(DefaultInputProject project, ScannerComponentIdGenerator scannerComponentIdGenerator, InputComponentStore componentStore, + ProjectExclusionFilters projectExclusionFilters, ProjectCoverageExclusions projectCoverageExclusions, IssueExclusionsLoader issueExclusionsLoader, + MetadataGenerator metadataGenerator, SensorStrategy sensorStrategy, LanguageDetection languageDetection, AnalysisWarnings analysisWarnings, ScanProperties properties, InputFileFilter[] filters) { this.project = project; this.scannerComponentIdGenerator = scannerComponentIdGenerator; this.componentStore = componentStore; + this.projectCoverageExclusions = projectCoverageExclusions; this.issueExclusionsLoader = issueExclusionsLoader; this.metadataGenerator = metadataGenerator; this.sensorStrategy = sensorStrategy; @@ -77,15 +83,18 @@ public class FileIndexer { this.projectExclusionFilters = projectExclusionFilters; } - public FileIndexer(DefaultInputProject project, ScannerComponentIdGenerator scannerComponentIdGenerator, InputComponentStore componentStore, ProjectExclusionFilters projectExclusionFilters, - IssueExclusionsLoader issueExclusionsLoader, + public FileIndexer(DefaultInputProject project, ScannerComponentIdGenerator scannerComponentIdGenerator, InputComponentStore componentStore, + ProjectExclusionFilters projectExclusionFilters, ProjectCoverageExclusions projectCoverageExclusions, IssueExclusionsLoader issueExclusionsLoader, MetadataGenerator metadataGenerator, SensorStrategy sensorStrategy, LanguageDetection languageDetection, AnalysisWarnings analysisWarnings, ScanProperties properties) { - this(project, scannerComponentIdGenerator, componentStore, projectExclusionFilters, issueExclusionsLoader, metadataGenerator, sensorStrategy, languageDetection, analysisWarnings, + this(project, scannerComponentIdGenerator, componentStore, projectExclusionFilters, projectCoverageExclusions, issueExclusionsLoader, metadataGenerator, sensorStrategy, + languageDetection, + analysisWarnings, properties, new InputFileFilter[0]); } - public void indexFile(DefaultInputModule module, AbstractExclusionFilters moduleExclusionFilters, Path sourceFile, InputFile.Type type, ProgressReport progressReport, - AtomicInteger excludedByPatternsCount) + public void indexFile(DefaultInputModule module, ModuleExclusionFilters moduleExclusionFilters, ModuleCoverageExclusions moduleCoverageExclusions, Path sourceFile, + InputFile.Type type, ProgressReport progressReport, + AtomicInteger excludedByPatternsCount) throws IOException { // get case of real file without resolving link Path realAbsoluteFile = sourceFile.toRealPath(LinkOption.NOFOLLOW_LINKS).toAbsolutePath().normalize(); @@ -101,10 +110,10 @@ public class FileIndexer { } if (!moduleExclusionFilters.accept(realAbsoluteFile, moduleRelativePath, type)) { if (projectExclusionFilters.equals(moduleExclusionFilters)) { - warnOnce("File '" + projectRelativePath + "' was excluded because patterns are still evaluated using module relative paths but this is deprecated. " + + warnOnceDeprecatedExclusion("File '" + projectRelativePath + "' was excluded because patterns are still evaluated using module relative paths but this is deprecated. " + "Please update file inclusion/exclusion configuration so that patterns refer to project relative paths."); } else { - warnOnce("Defining inclusion/exclusions at module level is deprecated. " + + warnOnceDeprecatedExclusion("Defining inclusion/exclusions at module level is deprecated. " + "Move file inclusion/exclusion configuration from module '" + module.getName() + "' " + "to the root project and update patterns to refer to project relative paths."); } @@ -127,23 +136,48 @@ public class FileIndexer { if (!accept(inputFile)) { return; } - if (componentStore.getFile(inputFile.getProjectRelativePath()) != null) { - throw MessageException.of("File " + inputFile + " can't be indexed twice. Please check that inclusion/exclusion patterns produce " - + "disjoint sets for main and test files"); - } + checkIfAlreadyIndexed(inputFile); componentStore.put(module.key(), inputFile); if (issueExclusionsLoader.shouldExecute()) { issueExclusionsLoader.addMulticriteriaPatterns(inputFile.getProjectRelativePath(), inputFile.key()); } LOG.debug("'{}' indexed {}with language '{}'", projectRelativePath, type == Type.TEST ? "as test " : "", inputFile.language()); + evaluateCoverageExclusions(module, moduleCoverageExclusions, inputFile); if (properties.preloadFileMetadata()) { inputFile.checkMetadata(); } - int count = componentStore.allFiles().size(); + int count = componentStore.inputFiles().size(); progressReport.message(count + " " + pluralizeFiles(count) + " indexed... (last one was " + inputFile.getProjectRelativePath() + ")"); } - private void warnOnce(String msg) { + private void checkIfAlreadyIndexed(DefaultInputFile inputFile) { + if (componentStore.inputFile(inputFile.getProjectRelativePath()) != null) { + throw MessageException.of("File " + inputFile + " can't be indexed twice. Please check that inclusion/exclusion patterns produce " + + "disjoint sets for main and test files"); + } + } + + private void evaluateCoverageExclusions(DefaultInputModule module, ModuleCoverageExclusions moduleCoverageExclusions, DefaultInputFile inputFile) { + boolean excludedByProjectConfiguration = projectCoverageExclusions.isExcluded(inputFile); + if (excludedByProjectConfiguration) { + inputFile.setExcludedForCoverage(true); + LOG.debug("File {} excluded for coverage", inputFile); + } else if (moduleCoverageExclusions.isExcluded(inputFile)) { + inputFile.setExcludedForCoverage(true); + if (Arrays.equals(moduleCoverageExclusions.getCoverageExclusionConfig(), projectCoverageExclusions.getCoverageExclusionConfig())) { + warnOnceDeprecatedCoverageExclusion( + "File '" + inputFile + "' was excluded from coverage because patterns are still evaluated using module relative paths but this is deprecated. " + + "Please update '" + CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY + "' configuration so that patterns refer to project relative paths"); + } else { + warnOnceDeprecatedCoverageExclusion("Defining coverage exclusions at module level is deprecated. " + + "Move '" + CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY + "' from module '" + module.getName() + "' " + + "to the root project and update patterns to refer to project relative paths"); + } + LOG.debug("File {} excluded for coverage", inputFile); + } + } + + private void warnOnceDeprecatedExclusion(String msg) { if (!warnExclusionsAlreadyLogged) { LOG.warn(msg); analysisWarnings.addUnique(msg); @@ -151,6 +185,14 @@ public class FileIndexer { } } + private void warnOnceDeprecatedCoverageExclusion(String msg) { + if (!warnCoverageExclusionsAlreadyLogged) { + LOG.warn(msg); + analysisWarnings.addUnique(msg); + warnCoverageExclusionsAlreadyLogged = true; + } + } + private boolean accept(InputFile indexedFile) { // InputFileFilter extensions. Might trigger generation of metadata for (InputFileFilter filter : filters) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputComponentStore.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputComponentStore.java index 6cc08a44ad4..4a92f584a30 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputComponentStore.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputComponentStore.java @@ -34,6 +34,7 @@ import java.util.stream.Stream; import javax.annotation.CheckForNull; import org.sonar.api.batch.fs.InputComponent; import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.FileExtensionPredicate; @@ -43,7 +44,7 @@ import org.sonar.scanner.scan.branch.BranchConfiguration; * Store of all files and dirs. Inclusion and * exclusion patterns are already applied. */ -public class InputComponentStore { +public class InputComponentStore extends DefaultFileSystem.Cache { private final SortedSet<String> globalLanguagesCache = new TreeSet<>(); private final Map<String, SortedSet<String>> languagesCache = new HashMap<>(); @@ -65,7 +66,7 @@ public class InputComponentStore { } private Stream<DefaultInputFile> allFilesToPublishStream() { - return inputFileByModuleCache.values().stream() + return globalInputFileCache.values().stream() .map(f -> (DefaultInputFile) f) .filter(DefaultInputFile::isPublished); } @@ -80,7 +81,8 @@ public class InputComponentStore { ::iterator; } - public Collection<InputFile> allFiles() { + @Override + public Collection<InputFile> inputFiles() { return globalInputFileCache.values(); } @@ -116,8 +118,9 @@ public class InputComponentStore { return inputFileByModuleCache.get(moduleKey, relativePath); } + @Override @CheckForNull - public InputFile getFile(String relativePath) { + public InputFile inputFile(String relativePath) { return globalInputFileCache.get(relativePath); } @@ -126,6 +129,17 @@ public class InputComponentStore { return inputModuleCache.get(moduleKeyWithBranch); } + @CheckForNull + public DefaultInputModule findModule(DefaultInputFile file) { + return inputFileByModuleCache + .cellSet() + .stream() + .filter(c -> c.getValue().equals(file)) + .findFirst() + .map(c -> (DefaultInputModule) inputComponents.get(c.getRowKey())) + .orElse(null); + } + public void put(DefaultInputModule inputModule) { String key = inputModule.key(); String keyWithBranch = inputModule.getKeyWithBranch(); @@ -136,23 +150,32 @@ public class InputComponentStore { inputModuleCache.put(keyWithBranch, inputModule); } + @Override public Iterable<InputFile> getFilesByName(String filename) { return filesByNameCache.get(filename); } + @Override public Iterable<InputFile> getFilesByExtension(String extension) { return filesByExtensionCache.get(extension); } - public SortedSet<String> getLanguages() { + @Override + public SortedSet<String> languages() { return globalLanguagesCache; } - public SortedSet<String> getLanguages(String moduleKey) { + public SortedSet<String> languages(String moduleKey) { return languagesCache.getOrDefault(moduleKey, Collections.emptySortedSet()); } public Collection<DefaultInputModule> allModules() { return inputModuleCache.values(); } + + @Override + protected void doAdd(InputFile inputFile) { + throw new UnsupportedOperationException(); + } + } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java index 6bb17759043..c9d1d3c115e 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java @@ -42,7 +42,7 @@ public class ModuleInputComponentStore extends DefaultFileSystem.Cache { @Override public Iterable<InputFile> inputFiles() { if (strategy.isGlobal()) { - return inputComponentStore.allFiles(); + return inputComponentStore.inputFiles(); } else { return inputComponentStore.filesByModule(moduleKey); } @@ -51,7 +51,7 @@ public class ModuleInputComponentStore extends DefaultFileSystem.Cache { @Override public InputFile inputFile(String relativePath) { if (strategy.isGlobal()) { - return inputComponentStore.getFile(relativePath); + return inputComponentStore.inputFile(relativePath); } else { return inputComponentStore.getFile(moduleKey, relativePath); } @@ -60,9 +60,9 @@ public class ModuleInputComponentStore extends DefaultFileSystem.Cache { @Override public SortedSet<String> languages() { if (strategy.isGlobal()) { - return inputComponentStore.getLanguages(); + return inputComponentStore.languages(); } else { - return inputComponentStore.getLanguages(moduleKey); + return inputComponentStore.languages(moduleKey); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java index 4d51181e2c8..bae2a44d47c 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java @@ -28,6 +28,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -37,6 +38,8 @@ import org.sonar.api.batch.fs.InputFile.Type; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.DefaultInputProject; import org.sonar.api.batch.fs.internal.InputModuleHierarchy; +import org.sonar.scanner.phases.ModuleCoverageExclusions; +import org.sonar.scanner.phases.ProjectCoverageExclusions; import org.sonar.scanner.util.ProgressReport; /** @@ -49,16 +52,18 @@ public class ProjectFileIndexer { private final DefaultInputProject project; private final InputComponentStore componentStore; private final InputModuleHierarchy inputModuleHierarchy; + private final ProjectCoverageExclusions projectCoverageExclusions; private final FileIndexer fileIndexer; private ProgressReport progressReport; public ProjectFileIndexer(DefaultInputProject project, InputComponentStore componentStore, AbstractExclusionFilters exclusionFilters, - InputModuleHierarchy inputModuleHierarchy, + InputModuleHierarchy inputModuleHierarchy, ProjectCoverageExclusions projectCoverageExclusions, FileIndexer fileIndexer) { this.project = project; this.componentStore = componentStore; this.inputModuleHierarchy = inputModuleHierarchy; + this.projectCoverageExclusions = projectCoverageExclusions; this.fileIndexer = fileIndexer; this.projectExclusionFilters = exclusionFilters; } @@ -71,7 +76,7 @@ public class ProjectFileIndexer { indexModulesRecursively(inputModuleHierarchy.root(), excludedByPatternsCount); - int totalIndexed = componentStore.allFiles().size(); + int totalIndexed = componentStore.inputFiles().size(); progressReport.stop(totalIndexed + " " + pluralizeFiles(totalIndexed) + " indexed"); if (projectExclusionFilters.hasPattern()) { @@ -81,27 +86,32 @@ public class ProjectFileIndexer { } private void indexModulesRecursively(DefaultInputModule module, AtomicInteger excludedByPatternsCount) { - inputModuleHierarchy.children(module).forEach(m -> indexModulesRecursively(m, excludedByPatternsCount)); + inputModuleHierarchy.children(module).stream().sorted(Comparator.comparing(DefaultInputModule::key)).forEach(m -> indexModulesRecursively(m, excludedByPatternsCount)); index(module, excludedByPatternsCount); } private void index(DefaultInputModule module, AtomicInteger excludedByPatternsCount) { + if (componentStore.allModules().size() > 1) { + LOG.info("Indexing files from module {}", module.getName()); + } ModuleExclusionFilters moduleExclusionFilters = new ModuleExclusionFilters(module); - indexFiles(module, moduleExclusionFilters, module.getSourceDirsOrFiles(), Type.MAIN, excludedByPatternsCount); - indexFiles(module, moduleExclusionFilters, module.getTestDirsOrFiles(), Type.TEST, excludedByPatternsCount); + ModuleCoverageExclusions moduleCoverageExclusions = new ModuleCoverageExclusions(module); + indexFiles(module, moduleExclusionFilters, moduleCoverageExclusions, module.getSourceDirsOrFiles(), Type.MAIN, excludedByPatternsCount); + indexFiles(module, moduleExclusionFilters, moduleCoverageExclusions, module.getTestDirsOrFiles(), Type.TEST, excludedByPatternsCount); } private static String pluralizeFiles(int count) { return count == 1 ? "file" : "files"; } - private void indexFiles(DefaultInputModule module, AbstractExclusionFilters moduleExclusionFilters, List<Path> sources, Type type, AtomicInteger excludedByPatternsCount) { + private void indexFiles(DefaultInputModule module, ModuleExclusionFilters moduleExclusionFilters, ModuleCoverageExclusions moduleCoverageExclusions, List<Path> sources, + Type type, AtomicInteger excludedByPatternsCount) { try { for (Path dirOrFile : sources) { if (dirOrFile.toFile().isDirectory()) { - indexDirectory(module, moduleExclusionFilters, dirOrFile, type, excludedByPatternsCount); + indexDirectory(module, moduleExclusionFilters, moduleCoverageExclusions, dirOrFile, type, excludedByPatternsCount); } else { - fileIndexer.indexFile(module, moduleExclusionFilters, dirOrFile, type, progressReport, excludedByPatternsCount); + fileIndexer.indexFile(module, moduleExclusionFilters, moduleCoverageExclusions, dirOrFile, type, progressReport, excludedByPatternsCount); } } } catch (IOException e) { @@ -109,21 +119,25 @@ public class ProjectFileIndexer { } } - private void indexDirectory(DefaultInputModule module, AbstractExclusionFilters moduleExclusionFilters, Path dirToIndex, Type type, AtomicInteger excludedByPatternsCount) + private void indexDirectory(DefaultInputModule module, ModuleExclusionFilters moduleExclusionFilters, ModuleCoverageExclusions moduleCoverageExclusions, Path dirToIndex, + Type type, AtomicInteger excludedByPatternsCount) throws IOException { Files.walkFileTree(dirToIndex.normalize(), Collections.singleton(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, - new IndexFileVisitor(module, moduleExclusionFilters, type, excludedByPatternsCount)); + new IndexFileVisitor(module, moduleExclusionFilters, moduleCoverageExclusions, type, excludedByPatternsCount)); } private class IndexFileVisitor implements FileVisitor<Path> { private final DefaultInputModule module; - private final AbstractExclusionFilters moduleExclusionFilters; + private final ModuleExclusionFilters moduleExclusionFilters; + private final ModuleCoverageExclusions moduleCoverageExclusions; private final Type type; private final AtomicInteger excludedByPatternsCount; - IndexFileVisitor(DefaultInputModule module, AbstractExclusionFilters moduleExclusionFilters, Type type, AtomicInteger excludedByPatternsCount) { + IndexFileVisitor(DefaultInputModule module, ModuleExclusionFilters moduleExclusionFilters, ModuleCoverageExclusions moduleCoverageExclusions, Type type, + AtomicInteger excludedByPatternsCount) { this.module = module; this.moduleExclusionFilters = moduleExclusionFilters; + this.moduleCoverageExclusions = moduleCoverageExclusions; this.type = type; this.excludedByPatternsCount = excludedByPatternsCount; } @@ -144,7 +158,7 @@ public class ProjectFileIndexer { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (!Files.isHidden(file)) { - fileIndexer.indexFile(module, moduleExclusionFilters, file, type, progressReport, excludedByPatternsCount); + fileIndexer.indexFile(module, moduleExclusionFilters, moduleCoverageExclusions, file, type, progressReport, excludedByPatternsCount); } return FileVisitResult.CONTINUE; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/IssuesReports.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/IssuesReports.java deleted file mode 100644 index b321aabd5b3..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/IssuesReports.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info 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.report; - -import org.sonar.api.batch.ScannerSide; - -@ScannerSide -public class IssuesReports { - - private final Reporter[] reporters; - - public IssuesReports(Reporter... reporters) { - this.reporters = reporters; - } - - public void execute() { - for (Reporter reporter : reporters) { - reporter.execute(); - } - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/JSONReport.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/JSONReport.java index d965bb3e908..50f53f047bf 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/JSONReport.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/JSONReport.java @@ -45,6 +45,7 @@ import org.sonar.api.batch.rule.Rules; import org.sonar.api.config.Configuration; import org.sonar.api.platform.Server; import org.sonar.api.rule.RuleKey; +import org.sonar.api.scanner.ScannerSide; import org.sonar.api.utils.text.JsonWriter; import org.sonar.core.component.ComponentKeys; import org.sonar.scanner.issue.IssueCache; @@ -57,7 +58,8 @@ import org.sonar.scanner.scan.filesystem.InputComponentStore; name = "Report Results Export File", type = PropertyType.STRING, global = false, project = false)}) -public class JSONReport implements Reporter { +@ScannerSide +public class JSONReport { static final String SONAR_REPORT_EXPORT_PATH = "sonar.report.export.path"; private static final Logger LOG = LoggerFactory.getLogger(JSONReport.class); @@ -80,7 +82,6 @@ public class JSONReport implements Reporter { this.componentStore = componentStore; } - @Override public void execute() { settings.get(SONAR_REPORT_EXPORT_PATH).ifPresent(this::exportResults); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/Reporter.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/Reporter.java deleted file mode 100644 index 63babb6dcca..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/report/Reporter.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info 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.report; - -import org.sonar.api.batch.ScannerSide; - -@ScannerSide -@FunctionalInterface -public interface Reporter { - - void execute(); - -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java index dcdb8909a21..05737631ae2 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java @@ -30,8 +30,6 @@ import org.sonar.api.Properties; import org.sonar.api.Property; import org.sonar.api.PropertyType; import org.sonar.api.batch.AnalysisMode; -import org.sonar.api.batch.InstantiationStrategy; -import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.fs.internal.InputModuleHierarchy; import org.sonar.api.batch.scm.ScmProvider; import org.sonar.api.config.Configuration; @@ -55,8 +53,6 @@ import static org.sonar.api.CoreProperties.SCM_PROVIDER_KEY; global = false, type = PropertyType.BOOLEAN) }) -@InstantiationStrategy(InstantiationStrategy.PER_BATCH) -@ScannerSide public class ScmConfiguration implements Startable { private static final Logger LOG = Loggers.get(ScmConfiguration.class); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java index 424f3ee1459..4abb86427d5 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java @@ -23,11 +23,9 @@ import java.util.LinkedList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; -import org.sonar.api.batch.InstantiationStrategy; -import org.sonar.api.batch.ScannerSide; +import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile.Status; -import org.sonar.api.batch.fs.internal.AbstractProjectOrModule; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.scm.ScmProvider; import org.sonar.api.utils.log.Logger; @@ -39,26 +37,21 @@ import org.sonar.scanner.report.ReportPublisher; import org.sonar.scanner.repository.FileData; import org.sonar.scanner.repository.ProjectRepositories; import org.sonar.scanner.scan.branch.BranchConfiguration; -import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; -import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore; +import org.sonar.scanner.scan.filesystem.InputComponentStore; -@InstantiationStrategy(InstantiationStrategy.PER_PROJECT) -@ScannerSide public final class ScmPublisher { private static final Logger LOG = Loggers.get(ScmPublisher.class); - private final AbstractProjectOrModule inputModule; private final ScmConfiguration configuration; private final ProjectRepositories projectRepositories; - private final ModuleInputComponentStore componentStore; - private final DefaultModuleFileSystem fs; + private final InputComponentStore componentStore; + private final FileSystem fs; private final ScannerReportWriter writer; private final BranchConfiguration branchConfiguration; - public ScmPublisher(AbstractProjectOrModule inputModule, ScmConfiguration configuration, ProjectRepositories projectRepositories, - ModuleInputComponentStore componentStore, DefaultModuleFileSystem fs, ReportPublisher reportPublisher, BranchConfiguration branchConfiguration) { - this.inputModule = inputModule; + public ScmPublisher(ScmConfiguration configuration, ProjectRepositories projectRepositories, + InputComponentStore componentStore, FileSystem fs, ReportPublisher reportPublisher, BranchConfiguration branchConfiguration) { this.configuration = configuration; this.projectRepositories = projectRepositories; this.componentStore = componentStore; @@ -99,16 +92,12 @@ public final class ScmPublisher { LOG.warn("Forced reloading of SCM data for all files."); } List<InputFile> filesToBlame = new LinkedList<>(); - for (InputFile f : componentStore.inputFiles()) { - DefaultInputFile inputFile = (DefaultInputFile) f; - if (!inputFile.isPublished()) { - continue; - } + for (DefaultInputFile f : componentStore.allFilesToPublish()) { if (configuration.forceReloadAll() || f.status() != Status.SAME) { addIfNotEmpty(filesToBlame, f); } else if (!branchConfiguration.isShortOrPullRequest()) { // File status is SAME so that mean fileData exists - FileData fileData = projectRepositories.fileData(inputModule.definition().getKeyWithBranch(), inputFile); + FileData fileData = projectRepositories.fileData(componentStore.findModule(f).getKeyWithBranch(), f); if (StringUtils.isEmpty(fileData.revision())) { addIfNotEmpty(filesToBlame, f); } else { diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionnaryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionnaryTest.java new file mode 100644 index 00000000000..a3b55c69e13 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionnaryTest.java @@ -0,0 +1,110 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.bootstrap; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.Phase; +import org.sonar.api.batch.postjob.PostJob; +import org.sonar.api.batch.postjob.PostJobContext; +import org.sonar.api.batch.postjob.PostJobDescriptor; +import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor; +import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.SensorDescriptor; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.scanner.postjob.PostJobOptimizer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class PostJobExtensionDictionnaryTest { + private PostJobOptimizer postJobOptimizer = mock(PostJobOptimizer.class); + + @Before + public void setUp() { + when(postJobOptimizer.shouldExecute(any(DefaultPostJobDescriptor.class))).thenReturn(true); + } + + private PostJobExtensionDictionnary newSelector(Object... extensions) { + ComponentContainer iocContainer = new ComponentContainer(); + for (Object extension : extensions) { + iocContainer.addSingleton(extension); + } + return new PostJobExtensionDictionnary(iocContainer, postJobOptimizer, mock(PostJobContext.class)); + } + + @Test + public void dependsUponPhaseForPostJob() { + PrePostJob pre = new PrePostJob(); + NormalPostJob normal = new NormalPostJob(); + + PostJobExtensionDictionnary selector = newSelector(normal, pre); + assertThat(selector.selectPostJobs()).extracting("wrappedPostJob").containsExactly(pre, normal); + } + + interface Marker { + + } + + @Phase(name = Phase.Name.POST) + class PostSensor implements Sensor { + + @Override + public void describe(SensorDescriptor descriptor) { + } + + @Override + public void execute(SensorContext context) { + } + + } + + class PostSensorSubclass extends PostSensor { + + } + + class NormalPostJob implements PostJob { + + @Override + public void describe(PostJobDescriptor descriptor) { + } + + @Override + public void execute(PostJobContext context) { + } + + } + + @Phase(name = Phase.Name.PRE) + class PrePostJob implements PostJob { + + @Override + public void describe(PostJobDescriptor descriptor) { + } + + @Override + public void execute(PostJobContext context) { + } + + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnaryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SensorExtensionDictionnaryTest.java index 7ddf235b0cd..b922b3a99ad 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnaryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SensorExtensionDictionnaryTest.java @@ -30,16 +30,11 @@ import org.sonar.api.batch.DependedUpon; import org.sonar.api.batch.DependsUpon; import org.sonar.api.batch.Phase; import org.sonar.api.batch.ScannerSide; -import org.sonar.api.batch.postjob.PostJob; -import org.sonar.api.batch.postjob.PostJobContext; -import org.sonar.api.batch.postjob.PostJobDescriptor; -import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor; 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.internal.DefaultSensorDescriptor; import org.sonar.core.platform.ComponentContainer; -import org.sonar.scanner.postjob.PostJobOptimizer; import org.sonar.scanner.sensor.DefaultSensorContext; import org.sonar.scanner.sensor.SensorOptimizer; import org.sonar.scanner.sensor.SensorWrapper; @@ -50,22 +45,20 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class ScannerExtensionDictionnaryTest { +public class SensorExtensionDictionnaryTest { private SensorOptimizer sensorOptimizer = mock(SensorOptimizer.class); - private PostJobOptimizer postJobOptimizer = mock(PostJobOptimizer.class); @Before public void setUp() { when(sensorOptimizer.shouldExecute(any(DefaultSensorDescriptor.class))).thenReturn(true); - when(postJobOptimizer.shouldExecute(any(DefaultPostJobDescriptor.class))).thenReturn(true); } - private ScannerExtensionDictionnary newSelector(Object... extensions) { + private SensorExtensionDictionnary newSelector(Object... extensions) { ComponentContainer iocContainer = new ComponentContainer(); for (Object extension : extensions) { iocContainer.addSingleton(extension); } - return new ScannerExtensionDictionnary(iocContainer, mock(DefaultSensorContext.class), sensorOptimizer, postJobOptimizer, mock(PostJobContext.class)); + return new SensorExtensionDictionnary(iocContainer, mock(DefaultSensorContext.class), sensorOptimizer); } @Test @@ -73,7 +66,7 @@ public class ScannerExtensionDictionnaryTest { final Sensor sensor1 = new FakeSensor(); final Sensor sensor2 = new FakeSensor(); - ScannerExtensionDictionnary selector = newSelector(sensor1, sensor2); + SensorExtensionDictionnary selector = newSelector(sensor1, sensor2); Collection<Sensor> sensors = selector.select(Sensor.class, true, extension -> extension.equals(sensor1)); assertThat(sensors).contains(sensor1); assertEquals(1, sensors.size()); @@ -85,7 +78,7 @@ public class ScannerExtensionDictionnaryTest { Sensor sensor2 = new FakeSensor(); FieldDecorated.Decorator decorator = mock(FieldDecorated.Decorator.class); - ScannerExtensionDictionnary selector = newSelector(sensor1, sensor2, decorator); + SensorExtensionDictionnary selector = newSelector(sensor1, sensor2, decorator); Collection<Sensor> sensors = selector.select(Sensor.class, false, null); assertThat(sensors).containsOnly(sensor1, sensor2); @@ -106,8 +99,7 @@ public class ScannerExtensionDictionnaryTest { ComponentContainer child = parent.createChild(); child.addSingleton(c); - ScannerExtensionDictionnary dictionnary = new ScannerExtensionDictionnary(child, mock(DefaultSensorContext.class), - mock(SensorOptimizer.class), mock(PostJobOptimizer.class), mock(PostJobContext.class)); + SensorExtensionDictionnary dictionnary = new SensorExtensionDictionnary(child, mock(DefaultSensorContext.class), mock(SensorOptimizer.class)); assertThat(dictionnary.select(Sensor.class, true, null)).containsOnly(a, b, c); } @@ -117,7 +109,7 @@ public class ScannerExtensionDictionnaryTest { Object b = new MethodDependentOf(a); Object c = new MethodDependentOf(b); - ScannerExtensionDictionnary selector = newSelector(b, c, a); + SensorExtensionDictionnary selector = newSelector(b, c, a); List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(3); @@ -131,7 +123,7 @@ public class ScannerExtensionDictionnaryTest { Object a = new GeneratesSomething("foo"); Object b = new MethodDependentOf("foo"); - ScannerExtensionDictionnary selector = newSelector(a, b); + SensorExtensionDictionnary selector = newSelector(a, b); List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); assertThat(extensions.size()).isEqualTo(2); @@ -152,7 +144,7 @@ public class ScannerExtensionDictionnaryTest { Object a = new GeneratesSomething("foo"); Object b = new MethodDependentOf(Arrays.asList("foo")); - ScannerExtensionDictionnary selector = newSelector(a, b); + SensorExtensionDictionnary selector = newSelector(a, b); List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); @@ -173,7 +165,7 @@ public class ScannerExtensionDictionnaryTest { Object a = new GeneratesSomething("foo"); Object b = new MethodDependentOf(new String[] {"foo"}); - ScannerExtensionDictionnary selector = newSelector(a, b); + SensorExtensionDictionnary selector = newSelector(a, b); List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); @@ -194,7 +186,7 @@ public class ScannerExtensionDictionnaryTest { Object a = new ClassDependedUpon(); Object b = new ClassDependsUpon(); - ScannerExtensionDictionnary selector = newSelector(a, b); + SensorExtensionDictionnary selector = newSelector(a, b); List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); @@ -217,7 +209,7 @@ public class ScannerExtensionDictionnaryTest { Object b = new InterfaceDependsUpon() { }; - ScannerExtensionDictionnary selector = newSelector(a, b); + SensorExtensionDictionnary selector = newSelector(a, b); List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); @@ -238,7 +230,7 @@ public class ScannerExtensionDictionnaryTest { Object a = new SubClass("foo"); Object b = new MethodDependentOf("foo"); - ScannerExtensionDictionnary selector = newSelector(b, a); + SensorExtensionDictionnary selector = newSelector(b, a); List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); @@ -256,7 +248,7 @@ public class ScannerExtensionDictionnaryTest { @Test(expected = IllegalStateException.class) public void annotatedMethodsCanNotBePrivate() { - ScannerExtensionDictionnary selector = newSelector(); + SensorExtensionDictionnary selector = newSelector(); Object wrong = new Object() { @DependsUpon private Object foo() { @@ -272,26 +264,17 @@ public class ScannerExtensionDictionnaryTest { NormalSensor normal = new NormalSensor(); PostSensor post = new PostSensor(); - ScannerExtensionDictionnary selector = newSelector(normal, post, pre); + SensorExtensionDictionnary selector = newSelector(normal, post, pre); assertThat(selector.selectSensors(false)).extracting("wrappedSensor").containsExactly(pre, normal, post); } @Test - public void dependsUponPhaseForPostJob() { - PrePostJob pre = new PrePostJob(); - NormalPostJob normal = new NormalPostJob(); - - ScannerExtensionDictionnary selector = newSelector(normal, pre); - assertThat(selector.selectPostJobs()).extracting("wrappedPostJob").containsExactly(pre, normal); - } - - @Test public void dependsUponInheritedPhase() { PreSensorSubclass pre = new PreSensorSubclass(); NormalSensor normal = new NormalSensor(); PostSensorSubclass post = new PostSensorSubclass(); - ScannerExtensionDictionnary selector = newSelector(normal, post, pre); + SensorExtensionDictionnary selector = newSelector(normal, post, pre); List extensions = Lists.newArrayList(selector.select(Sensor.class, true, null)); assertThat(extensions).containsExactly(pre, normal, post); @@ -301,7 +284,7 @@ public class ScannerExtensionDictionnaryTest { public void selectSensors() { FakeSensor nonGlobalSensor = new FakeSensor(); FakeGlobalSensor globalSensor = new FakeGlobalSensor(); - ScannerExtensionDictionnary selector = newSelector(nonGlobalSensor, globalSensor); + SensorExtensionDictionnary selector = newSelector(nonGlobalSensor, globalSensor); // verify non-global sensor Collection<SensorWrapper> extensions = selector.selectSensors(false); @@ -319,11 +302,13 @@ public class ScannerExtensionDictionnaryTest { class FakeSensor implements Sensor { - @Override public void describe(SensorDescriptor descriptor) { + @Override + public void describe(SensorDescriptor descriptor) { } - @Override public void execute(SensorContext context) { + @Override + public void execute(SensorContext context) { } } @@ -341,7 +326,8 @@ public class ScannerExtensionDictionnaryTest { } - @ScannerSide class MethodDependentOf implements Marker { + @ScannerSide + class MethodDependentOf implements Marker { private Object dep; MethodDependentOf(Object o) { @@ -355,22 +341,27 @@ public class ScannerExtensionDictionnaryTest { } @ScannerSide - @DependsUpon("flag") class ClassDependsUpon implements Marker { + @DependsUpon("flag") + class ClassDependsUpon implements Marker { } @ScannerSide - @DependedUpon("flag") class ClassDependedUpon implements Marker { + @DependedUpon("flag") + class ClassDependedUpon implements Marker { } @ScannerSide - @DependsUpon("flag") interface InterfaceDependsUpon extends Marker { + @DependsUpon("flag") + interface InterfaceDependsUpon extends Marker { } @ScannerSide - @DependedUpon("flag") interface InterfaceDependedUpon extends Marker { + @DependedUpon("flag") + interface InterfaceDependedUpon extends Marker { } - @ScannerSide class GeneratesSomething implements Marker { + @ScannerSide + class GeneratesSomething implements Marker { private Object gen; GeneratesSomething(Object o) { @@ -401,7 +392,8 @@ public class ScannerExtensionDictionnaryTest { } - @Phase(name = Phase.Name.PRE) class PreSensor implements Sensor { + @Phase(name = Phase.Name.PRE) + class PreSensor implements Sensor { @Override public void describe(SensorDescriptor descriptor) { @@ -417,7 +409,8 @@ public class ScannerExtensionDictionnaryTest { } - @Phase(name = Phase.Name.POST) class PostSensor implements Sensor { + @Phase(name = Phase.Name.POST) + class PostSensor implements Sensor { @Override public void describe(SensorDescriptor descriptor) { @@ -433,27 +426,4 @@ public class ScannerExtensionDictionnaryTest { } - class NormalPostJob implements PostJob { - - @Override - public void describe(PostJobDescriptor descriptor) { - } - - @Override - public void execute(PostJobContext context) { - } - - } - - @Phase(name = Phase.Name.PRE) class PrePostJob implements PostJob { - - @Override - public void describe(PostJobDescriptor descriptor) { - } - - @Override - public void execute(PostJobContext context) { - } - - } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java index bcc778dc724..6c2f47ff34c 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java @@ -574,7 +574,7 @@ public class FileSystemMediumTest { assertThat(fileB).isNull(); assertThat(logTester.logs(LoggerLevel.WARN)) - .contains("File 'moduleB/src/sample.xoo' was excluded because patterns are still evaluated using module relative paths but this is deprecated. " + + .contains("File 'moduleA/src/sample.xoo' was excluded because patterns are still evaluated using module relative paths but this is deprecated. " + "Please update file inclusion/exclusion configuration so that patterns refer to project relative paths."); } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleCoverageExclusionsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleCoverageExclusionsTest.java index 6d95e2ff828..6be5efa45a9 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleCoverageExclusionsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleCoverageExclusionsTest.java @@ -20,11 +20,15 @@ package org.sonar.scanner.phases; import java.io.File; +import java.util.Arrays; +import java.util.stream.Collectors; 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.internal.DefaultInputFile; +import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.scanner.scan.ModuleConfiguration; @@ -63,9 +67,12 @@ public class ModuleCoverageExclusionsTest { assertThat(coverageExclusions.isExcluded(file)).isFalse(); } - private ModuleConfiguration mockConfig(String... values) { + private DefaultInputModule mockConfig(String... values) { ModuleConfiguration config = mock(ModuleConfiguration.class); when(config.getStringArray("sonar.coverage.exclusions")).thenReturn(values); - return config; + return new DefaultInputModule(ProjectDefinition.create() + .setBaseDir(baseDir) + .setWorkDir(baseDir) + .setProperty("sonar.coverage.exclusions", Arrays.asList(values).stream().collect(Collectors.joining(",")))); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/PostJobsExecutorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/PostJobsExecutorTest.java index f4a8ed15f92..92e7bc2a8ce 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/PostJobsExecutorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/PostJobsExecutorTest.java @@ -22,8 +22,9 @@ package org.sonar.scanner.phases; import java.util.Arrays; import org.junit.Before; import org.junit.Test; -import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; +import org.sonar.scanner.bootstrap.PostJobExtensionDictionnary; import org.sonar.scanner.postjob.PostJobWrapper; +import org.sonar.scanner.postjob.PostJobsExecutor; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -33,7 +34,7 @@ import static org.mockito.Mockito.when; public class PostJobsExecutorTest { private PostJobsExecutor executor; - private ScannerExtensionDictionnary selector = mock(ScannerExtensionDictionnary.class); + private PostJobExtensionDictionnary selector = mock(PostJobExtensionDictionnary.class); private PostJobWrapper job1 = mock(PostJobWrapper.class); private PostJobWrapper job2 = mock(PostJobWrapper.class); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/SensorsExecutorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/SensorsExecutorTest.java index ca97a46a6fc..de31e20e3c3 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/SensorsExecutorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/SensorsExecutorTest.java @@ -31,7 +31,7 @@ import org.sonar.api.batch.fs.internal.InputModuleHierarchy; import org.sonar.api.batch.fs.internal.SensorStrategy; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.batch.sensor.Sensor; -import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; +import org.sonar.scanner.bootstrap.SensorExtensionDictionnary; import org.sonar.scanner.bootstrap.ScannerPluginRepository; import org.sonar.scanner.sensor.SensorWrapper; @@ -64,7 +64,7 @@ public class SensorsExecutorTest { when(globalSensor.shouldExecute()).thenReturn(true); when(globalSensor.wrappedSensor()).thenReturn(mock(Sensor.class)); - ScannerExtensionDictionnary selector = mock(ScannerExtensionDictionnary.class); + SensorExtensionDictionnary selector = mock(SensorExtensionDictionnary.class); when(selector.selectSensors(false)).thenReturn(Collections.singleton(perModuleSensor)); when(selector.selectSensors(true)).thenReturn(Collections.singleton(globalSensor)); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java index ee736b0578f..98785e06e62 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java @@ -84,8 +84,8 @@ public class InputComponentStoreTest { assertThat(store.filesByModule(rootModuleKey)).hasSize(1); assertThat(store.filesByModule(subModuleKey)).hasSize(1); - assertThat(store.allFiles()).hasSize(2); - for (InputPath inputPath : store.allFiles()) { + assertThat(store.inputFiles()).hasSize(2); + for (InputPath inputPath : store.inputFiles()) { assertThat(inputPath.relativePath()).startsWith("src/main/java/"); } @@ -118,9 +118,9 @@ public class InputComponentStoreTest { String mod2Key = "mod2"; tester.addFile(mod2Key, "src/main/groovy/Foo.groovy", "groovy"); - assertThat(tester.getLanguages(mod1Key)).containsExactly("java"); - assertThat(tester.getLanguages(mod2Key)).containsExactly("groovy"); - assertThat(tester.getLanguages()).containsExactlyInAnyOrder("java", "groovy"); + assertThat(tester.languages(mod1Key)).containsExactly("java"); + assertThat(tester.languages(mod2Key)).containsExactly("groovy"); + assertThat(tester.languages()).containsExactlyInAnyOrder("java", "groovy"); } @Test @@ -135,6 +135,6 @@ public class InputComponentStoreTest { assertThat(tester.filesByModule(mod1Key)).containsExactly(mod1File); assertThat(tester.filesByModule(mod2Key)).containsExactly(mod2File); - assertThat(tester.allFiles()).containsExactlyInAnyOrder(mod1File, mod2File); + assertThat(tester.inputFiles()).containsExactlyInAnyOrder(mod1File, mod2File); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java index cb1b4793940..29064edd51b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java @@ -127,6 +127,8 @@ public class ModuleInputComponentStoreTest { when(module.key()).thenReturn("foo"); ModuleInputComponentStore store = new ModuleInputComponentStore(module, inputComponentStore, strategy); + strategy.setGlobal(false); + store.inputFiles(); verify(inputComponentStore).filesByModule("foo"); @@ -135,7 +137,7 @@ public class ModuleInputComponentStoreTest { verify(inputComponentStore).getFile(any(String.class), eq(relativePath)); store.languages(); - verify(inputComponentStore).getLanguages(any(String.class)); + verify(inputComponentStore).languages(any(String.class)); } @Test @@ -147,13 +149,13 @@ public class ModuleInputComponentStoreTest { strategy.setGlobal(true); store.inputFiles(); - verify(inputComponentStore).allFiles(); + verify(inputComponentStore).inputFiles(); String relativePath = "somepath"; store.inputFile(relativePath); - verify(inputComponentStore).getFile(relativePath); + verify(inputComponentStore).inputFile(relativePath); store.languages(); - verify(inputComponentStore).getLanguages(); + verify(inputComponentStore).languages(); } } |