diff options
author | simonbrandhof <simon.brandhof@gmail.com> | 2011-01-24 19:06:38 +0100 |
---|---|---|
committer | simonbrandhof <simon.brandhof@gmail.com> | 2011-01-24 19:25:01 +0100 |
commit | 878cec92f8e39fd46628a83bba970293129de710 (patch) | |
tree | 8234845025634f6e8d589fc1ef5df79f4bb4fe12 | |
parent | eb9462d6002daf7f01f8fe627b4517c065bdb5af (diff) | |
download | sonarqube-878cec92f8e39fd46628a83bba970293129de710.tar.gz sonarqube-878cec92f8e39fd46628a83bba970293129de710.zip |
SONAR-791 When the source directory is not exactly the java package root, Sonar should stop the analysis
20 files changed, 202 insertions, 124 deletions
diff --git a/plugins/sonar-core-gwt/src/main/java/org/sonar/plugins/core/testdetailsviewer/TestsViewerDefinition.java b/plugins/sonar-core-gwt/src/main/java/org/sonar/plugins/core/testdetailsviewer/TestsViewerDefinition.java index 0cca72a7d7b..98bc53a0437 100644 --- a/plugins/sonar-core-gwt/src/main/java/org/sonar/plugins/core/testdetailsviewer/TestsViewerDefinition.java +++ b/plugins/sonar-core-gwt/src/main/java/org/sonar/plugins/core/testdetailsviewer/TestsViewerDefinition.java @@ -20,13 +20,13 @@ package org.sonar.plugins.core.testdetailsviewer; import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.resources.Resource; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.web.*; import org.sonar.plugins.core.testdetailsviewer.client.TestsViewer; -@ResourceQualifier(Resource.QUALIFIER_UNIT_TEST_CLASS) +@ResourceQualifier(Qualifiers.UNIT_TEST_FILE) @NavigationSection(NavigationSection.RESOURCE_TAB) -@DefaultTab(metrics={CoreMetrics.TESTS_KEY, CoreMetrics.TEST_EXECUTION_TIME_KEY, CoreMetrics.TEST_SUCCESS_DENSITY_KEY, CoreMetrics.TEST_FAILURES_KEY, CoreMetrics.TEST_ERRORS_KEY, CoreMetrics.SKIPPED_TESTS_KEY}) +@DefaultTab(metrics = {CoreMetrics.TESTS_KEY, CoreMetrics.TEST_EXECUTION_TIME_KEY, CoreMetrics.TEST_SUCCESS_DENSITY_KEY, CoreMetrics.TEST_FAILURES_KEY, CoreMetrics.TEST_ERRORS_KEY, CoreMetrics.SKIPPED_TESTS_KEY}) @UserRole(UserRole.CODEVIEWER) public class TestsViewerDefinition extends GwtPage { diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index 8af552c5f52..944fc9a572d 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -207,7 +207,6 @@ public class CorePlugin implements Plugin { extensions.add(JavaColorizerFormat.class); // batch - extensions.add(JavaSourceImporter.class); extensions.add(ProfileSensor.class); extensions.add(ProjectLinksSensor.class); extensions.add(AsynchronousMeasuresSensor.class); diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/batch/ExcludedResourceFilterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/batch/ExcludedResourceFilterTest.java index a6066489274..b65b0500747 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/batch/ExcludedResourceFilterTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/batch/ExcludedResourceFilterTest.java @@ -20,6 +20,7 @@ package org.sonar.plugins.core.batch; import org.junit.Test; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Resource; import static org.hamcrest.core.Is.is; @@ -59,7 +60,7 @@ public class ExcludedResourceFilterTest { ExcludedResourceFilter filter = new ExcludedResourceFilter(new String[]{"**/foo/*.java", "**/bar/*"}); Resource unitTest = mock(Resource.class); - when(unitTest.getQualifier()).thenReturn(Resource.QUALIFIER_UNIT_TEST_CLASS); + when(unitTest.getQualifier()).thenReturn(Qualifiers.UNIT_TEST_FILE); // match exclusion pattern when(unitTest.matchFilePattern("**/bar/*")).thenReturn(true); diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/JavaSourceImporter.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java index 1b8f32a8892..87e7699ba88 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/JavaSourceImporter.java +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java @@ -17,35 +17,28 @@ * License along with Sonar; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 */ -package org.sonar.plugins.core.sensors; +package org.sonar.plugins.squid; -import org.sonar.api.batch.AbstractSourceImporter; -import org.sonar.api.batch.Phase; -import org.sonar.api.batch.ResourceCreationLock; +import org.sonar.api.batch.*; import org.sonar.api.resources.Java; import org.sonar.api.resources.JavaFile; import org.sonar.api.resources.Resource; +import org.sonar.java.api.JavaUtils; import java.io.File; import java.util.List; -@Phase(name = Phase.Name.PRE) +@DependsUpon(classes=SquidSensor.class) +@DependedUpon(JavaUtils.BARRIER_AFTER_SQUID) public class JavaSourceImporter extends AbstractSourceImporter { - private ResourceCreationLock lock; - public JavaSourceImporter(ResourceCreationLock lock) { + public JavaSourceImporter() { super(Java.INSTANCE); - this.lock = lock; } @Override protected Resource createResource(File file, List<File> sourceDirs, boolean unitTest) { - return (file != null && !file.getName().contains("$")) ? JavaFile.fromIOFile(file, sourceDirs, unitTest) : null; - } - - @Override - protected void onFinished() { - lock.lock(); + return file != null ? JavaFile.fromIOFile(file, sourceDirs, unitTest) : null; } @Override diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidPlugin.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidPlugin.java index 16ba011d56d..856c3438fea 100644 --- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidPlugin.java +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidPlugin.java @@ -24,25 +24,25 @@ import org.sonar.api.Plugin; import org.sonar.api.Properties; import org.sonar.api.Property; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -@Properties( { +@Properties({ @Property(key = SquidPluginProperties.SQUID_ANALYSE_ACCESSORS_PROPERTY, - defaultValue = SquidPluginProperties.SQUID_ANALYSE_ACCESSORS_DEFAULT_VALUE - + "", - name = "Separate accessors", - description = "Flag whether Squid should separate accessors (getters/setters) from methods. " + - "In that case, accessors are not counted in metrics such as complexity or API documentation.", - project = true, global = true), + defaultValue = SquidPluginProperties.SQUID_ANALYSE_ACCESSORS_DEFAULT_VALUE + + "", + name = "Separate accessors", + description = "Flag whether Squid should separate accessors (getters/setters) from methods. " + + "In that case, accessors are not counted in metrics such as complexity or API documentation.", + project = true, global = true), @Property(key = SquidPluginProperties.FIELDS_TO_EXCLUDE_FROM_LCOM4_COMPUTATION, - defaultValue = SquidPluginProperties.FIELDS_TO_EXCLUDE_FROM_LCOM4_COMPUTATION_DEFAULT_VALUE, - name = "List of fields to exclude from LCOM4 computation", - description = "Some fields should not be taken into account when computing LCOM4 measure as they " + - "unexpectedly and artificially decrease the LCOM4 measure. " - + "The best example is a logger used by all methods of a class. " + - "All field names to exclude from LCOM4 computation must be separated by a comma.", - project = true, global = true) }) + defaultValue = SquidPluginProperties.FIELDS_TO_EXCLUDE_FROM_LCOM4_COMPUTATION_DEFAULT_VALUE, + name = "List of fields to exclude from LCOM4 computation", + description = "Some fields should not be taken into account when computing LCOM4 measure as they " + + "unexpectedly and artificially decrease the LCOM4 measure. " + + "The best example is a logger used by all methods of a class. " + + "All field names to exclude from LCOM4 computation must be separated by a comma.", + project = true, global = true)}) public class SquidPlugin implements Plugin { public String getKey() { @@ -58,13 +58,7 @@ public class SquidPlugin implements Plugin { } public List getExtensions() { - List list = new ArrayList(); - - list.add(SquidSearchProxy.class); - list.add(SquidSensor.class); - list.add(SquidRuleRepository.class); - - return list; + return Arrays.asList(SquidSearchProxy.class, SquidSensor.class, SquidRuleRepository.class, JavaSourceImporter.class); } @Override diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java index 5abb4f50b67..c1b242e09de 100644 --- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidSensor.java @@ -26,7 +26,9 @@ import org.sonar.api.checks.AnnotationCheckFactory; import org.sonar.api.checks.NoSonarFilter; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.resources.Java; +import org.sonar.api.resources.JavaFile; import org.sonar.api.resources.Project; +import org.sonar.java.api.JavaUtils; import java.io.File; import java.nio.charset.Charset; @@ -34,20 +36,22 @@ import java.util.Collection; import java.util.List; @Phase(name = Phase.Name.PRE) -/* TODO is the flag still used ? */ -@DependedUpon(value = Sensor.FLAG_SQUID_ANALYSIS, classes = NoSonarFilter.class) +@DependsUpon(JavaUtils.BARRIER_BEFORE_SQUID) +@DependedUpon(value = JavaUtils.BARRIER_AFTER_SQUID, classes = NoSonarFilter.class) public class SquidSensor implements Sensor { private SquidSearchProxy proxy; private NoSonarFilter noSonarFilter; private RulesProfile profile; private ProjectClasspath projectClasspath; + private ResourceCreationLock lock; - public SquidSensor(RulesProfile profile, SquidSearchProxy proxy, NoSonarFilter noSonarFilter, ProjectClasspath projectClasspath) { + public SquidSensor(RulesProfile profile, SquidSearchProxy proxy, NoSonarFilter noSonarFilter, ProjectClasspath projectClasspath, ResourceCreationLock lock) { this.proxy = proxy; this.noSonarFilter = noSonarFilter; this.profile = profile; this.projectClasspath = projectClasspath; + this.lock = lock; } public boolean shouldExecuteOnProject(Project project) { @@ -56,6 +60,12 @@ public class SquidSensor implements Sensor { @SuppressWarnings("unchecked") public void analyse(Project project, SensorContext context) { + analyzeMainSources(project, context); + browseTestSources(project, context); + lock.lock(); + } + + private void analyzeMainSources(Project project, SensorContext context) { boolean analyzePropertyAccessors = project.getConfiguration().getBoolean(SquidPluginProperties.SQUID_ANALYSE_ACCESSORS_PROPERTY, SquidPluginProperties.SQUID_ANALYSE_ACCESSORS_DEFAULT_VALUE); String fieldNamesToExcludeFromLcom4Computation = project.getConfiguration().getString( @@ -66,16 +76,26 @@ public class SquidSensor implements Sensor { AnnotationCheckFactory factory = AnnotationCheckFactory.create(profile, SquidConstants.REPOSITORY_KEY, SquidRuleRepository.getCheckClasses()); SquidExecutor squidExecutor = new SquidExecutor(analyzePropertyAccessors, fieldNamesToExcludeFromLcom4Computation, factory, charset); - squidExecutor.scan(getSourceFiles(project), getBytecodeFiles(project)); + squidExecutor.scan(getMainSourceFiles(project), getMainBytecodeFiles(project)); squidExecutor.save(project, context, noSonarFilter); squidExecutor.initSonarProxy(proxy); } - private List<File> getSourceFiles(Project project) { + private void browseTestSources(Project project, SensorContext context) { + for (File testFile : getTestSourceFiles(project)) { + context.index(JavaFile.fromIOFile(testFile, project.getFileSystem().getTestDirs(), true)); + } + } + + private List<File> getTestSourceFiles(Project project) { + return project.getFileSystem().getTestFiles(Java.INSTANCE); + } + + private List<File> getMainSourceFiles(Project project) { return project.getFileSystem().getJavaSourceFiles(); } - private Collection<File> getBytecodeFiles(Project project) { + private Collection<File> getMainBytecodeFiles(Project project) { Collection<File> bytecodeFiles = projectClasspath.getElements(); if ( !hasProjectBytecodeFiles(project)) { File classesDir = project.getFileSystem().getBuildOutputDir(); diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/bridges/Lcom4BlocksBridge.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/bridges/Lcom4BlocksBridge.java index 14a9b1b09b7..8971e618b4e 100644 --- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/bridges/Lcom4BlocksBridge.java +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/bridges/Lcom4BlocksBridge.java @@ -19,9 +19,11 @@ */ package org.sonar.plugins.squid.bridges; +import com.google.common.collect.Lists; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; import org.sonar.api.measures.PersistenceMode; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Resource; import org.sonar.java.bytecode.asm.AsmField; import org.sonar.java.bytecode.asm.AsmMethod; @@ -29,7 +31,10 @@ import org.sonar.java.bytecode.asm.AsmResource; import org.sonar.squid.api.SourceFile; import org.sonar.squid.measures.Metric; -import java.util.*; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Set; public class Lcom4BlocksBridge extends Bridge { @@ -62,7 +67,7 @@ public class Lcom4BlocksBridge extends Bridge { protected String serialize(List<Set<AsmResource>> blocks) { sortBlocks(blocks); - + StringBuilder sb = new StringBuilder(); sb.append('['); @@ -102,7 +107,7 @@ public class Lcom4BlocksBridge extends Bridge { } protected List<AsmResource> sortResourcesInBlock(Set<AsmResource> block) { - List<AsmResource> result = new ArrayList<AsmResource>(); + List<AsmResource> result = Lists.newArrayList(); result.addAll(block); Collections.sort(result, new Comparator<AsmResource>() { @@ -127,10 +132,10 @@ public class Lcom4BlocksBridge extends Bridge { private static String toQualifier(AsmResource asmResource) { if (asmResource instanceof AsmField) { - return Resource.QUALIFIER_FIELD; + return Qualifiers.FIELD; } if (asmResource instanceof AsmMethod) { - return Resource.QUALIFIER_METHOD; + return Qualifiers.METHOD; } throw new IllegalArgumentException("Wrong ASM resource: " + asmResource.getClass()); } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/JavaSourceImporterTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java index 0b47543b33a..c6667a6920e 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/JavaSourceImporterTest.java +++ b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java @@ -17,16 +17,10 @@ * License along with Sonar; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 */ -package org.sonar.plugins.core.sensors; +package org.sonar.plugins.squid; import org.apache.commons.io.FileUtils; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; - import org.junit.Test; -import org.sonar.api.batch.ResourceCreationLock; import org.sonar.api.resources.JavaFile; import org.sonar.api.resources.JavaPackage; import org.sonar.api.resources.Resource; @@ -36,11 +30,14 @@ import java.io.File; import java.io.IOException; import java.util.Arrays; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + public class JavaSourceImporterTest { @Test - public void shouldCreateResource() throws IOException { - JavaSourceImporter importer = new JavaSourceImporter(mock(ResourceCreationLock.class)); + public void shouldDefineMainFile() throws IOException { + JavaSourceImporter importer = new JavaSourceImporter(); Resource clazz = importer.createResource(new File(newDir("source1"), "/MyClass.java"), Arrays.asList(newDir("source1")), false); assertThat(clazz, is(JavaFile.class)); assertThat(clazz.getKey(), is(JavaPackage.DEFAULT_PACKAGE_NAME + ".MyClass")); @@ -48,21 +45,13 @@ public class JavaSourceImporterTest { } @Test - public void shouldCreateTestResource() throws IOException { - JavaSourceImporter importer = new JavaSourceImporter(mock(ResourceCreationLock.class)); + public void shouldDefineTestFile() throws IOException { + JavaSourceImporter importer = new JavaSourceImporter(); Resource resource = importer.createResource(new File(newDir("tests"), "/MyClassTest.java"), Arrays.asList(newDir("tests")), true); assertThat(resource, is(JavaFile.class)); assertThat(ResourceUtils.isUnitTestClass(resource), is(true)); } - @Test - public void doNotSaveInnerClasses() throws IOException { - // example : https://svn.apache.org/repos/asf/geronimo/server/trunk/plugins/corba/geronimo-corba/src/test/java/org/apache/geronimo/corba/compiler/other/Generic$Interface.java - JavaSourceImporter importer = new JavaSourceImporter(mock(ResourceCreationLock.class)); - Resource resource = importer.createResource(new File(newDir("tests"), "/Generic$Interface.java"), Arrays.asList(newDir("tests")), true); - assertThat(resource, nullValue()); - } - private File newDir(String relativePath) throws IOException { File target = new File("target", relativePath); FileUtils.forceMkdir(target); diff --git a/plugins/sonar-surefire-plugin/src/test/java/org/sonar/plugins/surefire/SurefireSensorTest.java b/plugins/sonar-surefire-plugin/src/test/java/org/sonar/plugins/surefire/SurefireSensorTest.java index e21df1d9648..450570ff6bc 100644 --- a/plugins/sonar-surefire-plugin/src/test/java/org/sonar/plugins/surefire/SurefireSensorTest.java +++ b/plugins/sonar-surefire-plugin/src/test/java/org/sonar/plugins/surefire/SurefireSensorTest.java @@ -19,19 +19,6 @@ */ package org.sonar.plugins.surefire; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyDouble; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import org.apache.commons.lang.ObjectUtils; import org.custommonkey.xmlunit.DetailedDiff; import org.custommonkey.xmlunit.Diff; @@ -46,6 +33,7 @@ import org.sonar.api.measures.Metric; import org.sonar.api.resources.Java; import org.sonar.api.resources.JavaFile; import org.sonar.api.resources.Project; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.test.IsMeasure; import org.sonar.api.test.IsResource; import org.sonar.api.test.MavenTestUtils; @@ -55,6 +43,15 @@ import java.io.FileReader; import java.io.StringReader; import java.net.URISyntaxException; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyDouble; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.argThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.*; + public class SurefireSensorTest { @Test @@ -94,7 +91,7 @@ public class SurefireSensorTest { new SurefireSensor().collect(newJarProject(), context, new File(getClass().getResource( "/org/sonar/plugins/surefire/SurefireSensorTest/doNotInsertZeroTestsOnClasses/").toURI())); - verify(context, never()).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, never()).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), (Metric) anyObject(), anyDouble()); } @@ -123,11 +120,11 @@ public class SurefireSensorTest { new SurefireSensor().collect(newJarProject(), context, new File(getClass().getResource( "/org/sonar/plugins/surefire/SurefireSensorTest/many-results/").toURI())); - verify(context, times(6)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(6)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), eq(CoreMetrics.TESTS), anyDouble()); - verify(context, times(36)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(36)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), (Metric) anyObject(), anyDouble()); - verify(context, times(6)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(6)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), argThat(new IsMeasure(CoreMetrics.TEST_DATA))); verify(context) @@ -147,13 +144,13 @@ public class SurefireSensorTest { "/org/sonar/plugins/surefire/SurefireSensorTest/shouldHandleTestSuiteDetails/").toURI())); // 3 classes, 6 measures by class - verify(context, times(3)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(3)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), eq(CoreMetrics.SKIPPED_TESTS), anyDouble()); - verify(context, times(3)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(3)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), eq(CoreMetrics.TESTS), anyDouble()); - verify(context, times(18)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(18)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), (Metric) anyObject(), anyDouble()); - verify(context, times(3)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(3)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), argThat(new IsMeasure(CoreMetrics.TEST_DATA))); verify(context).saveMeasure(eq(new JavaFile("org.sonar.core.ExtensionsFinderTest", true)), eq(CoreMetrics.TESTS), eq(4d)); @@ -191,14 +188,14 @@ public class SurefireSensorTest { "/org/sonar/plugins/surefire/SurefireSensorTest/shouldSaveErrorsAndFailuresInXML/").toURI())); // 1 classes, 6 measures by class - verify(context, times(1)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(1)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), eq(CoreMetrics.SKIPPED_TESTS), anyDouble()); - verify(context, times(1)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(1)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), eq(CoreMetrics.TESTS), anyDouble()); - verify(context, times(6)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(6)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), (Metric) anyObject(), anyDouble()); - verify(context, times(1)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, JavaFile.QUALIFIER_UNIT_TEST_CLASS)), + verify(context, times(1)).saveMeasure(argThat(new IsResource(JavaFile.SCOPE_ENTITY, Qualifiers.UNIT_TEST_FILE)), argThat(new IsMeasure(CoreMetrics.TEST_DATA))); verify(context).saveMeasure(eq(new JavaFile("org.sonar.core.ExtensionsFinderTest", true)), @@ -283,7 +280,7 @@ public class SurefireSensorTest { public boolean matches(Object obj) { try { - if ( !ObjectUtils.equals(CoreMetrics.TEST_DATA, ((Measure) obj).getMetric())) { + if (!ObjectUtils.equals(CoreMetrics.TEST_DATA, ((Measure) obj).getMetric())) { return false; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultResourceCreationLock.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultResourceCreationLock.java index 93b33f6b53a..49e1244c191 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultResourceCreationLock.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultResourceCreationLock.java @@ -19,6 +19,7 @@ */ package org.sonar.batch; +import org.apache.commons.configuration.Configuration; import org.sonar.api.batch.ResourceCreationLock; /** @@ -30,6 +31,14 @@ import org.sonar.api.batch.ResourceCreationLock; public final class DefaultResourceCreationLock implements ResourceCreationLock { private boolean locked = false; + private boolean failWhenLocked=false; + + public DefaultResourceCreationLock() { + } + + public DefaultResourceCreationLock(Configuration configuration) { + this.failWhenLocked = configuration.getBoolean("sonar.hardIndexLock", false); + } public boolean isLocked() { return locked; @@ -46,4 +55,11 @@ public final class DefaultResourceCreationLock implements ResourceCreationLock { locked = false; } + public boolean isFailWhenLocked() { + return failWhenLocked; + } + + public void setFailWhenLocked(boolean b) { + this.failWhenLocked = b; + } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java index b63bef696fd..5660bf44ade 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java @@ -460,9 +460,7 @@ public final class DefaultIndex extends SonarIndex { return bucket; } - if (lock.isLocked() && !ResourceUtils.isLibrary(resource)) { - LOG.warn("Resource will be ignored in next Sonar versions, index is locked: " + resource); - } + checkLock(resource); Resource parent = null; if (!ResourceUtils.isLibrary(resource)) { @@ -487,6 +485,14 @@ public final class DefaultIndex extends SonarIndex { return bucket; } + private void checkLock(Resource resource) { + if (lock.isLocked() && !ResourceUtils.isLibrary(resource)) { + if (lock.isFailWhenLocked()) { + throw new SonarException("Index is locked, resource can not be indexed: " + resource); + } + LOG.warn("Resource will be ignored in next Sonar versions, index is locked: " + resource); + } + } public boolean isExcluded(Resource reference) { Bucket bucket = getBucket(reference, true); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java index 25f6bcb6cc1..e90cd8a9b61 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java @@ -24,9 +24,13 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.sonar.api.batch.ResourceFilter; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasuresFilters; import org.sonar.api.measures.MetricFinder; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.resources.*; +import org.sonar.api.utils.SonarException; import org.sonar.batch.DefaultResourceCreationLock; import org.sonar.batch.ProjectTree; import org.sonar.batch.ResourceFilters; @@ -36,14 +40,20 @@ import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class DefaultIndexTest { private DefaultIndex index = null; + private DefaultResourceCreationLock lock; @Before public void createIndex() { - index = new DefaultIndex(mock(PersistenceManager.class), new DefaultResourceCreationLock(), mock(ProjectTree.class), mock(MetricFinder.class)); + lock = new DefaultResourceCreationLock(); + MetricFinder metricFinder = mock(MetricFinder.class); + when(metricFinder.findByKey("ncloc")).thenReturn(CoreMetrics.NCLOC); + + index = new DefaultIndex(mock(PersistenceManager.class), lock, mock(ProjectTree.class), metricFinder); Project project = new Project("project"); ResourceFilter filter = new ResourceFilter() { @@ -126,10 +136,25 @@ public class DefaultIndexTest { } + /** + * Only a warning is logged when index is locked. + */ @Test - @Ignore("TODO: should it be really possible") - public void shouldIndexDirectChildOfProject() { + public void shouldIndexEvenIfLocked() { + lock.lock(); + + Directory dir = new Directory("org/foo"); + assertThat(index.index(dir), is(true)); + assertThat(index.isIndexed(dir), is(true)); + } + + @Test(expected = SonarException.class) + public void shouldFailIfIndexingAndLocked() { + lock.setFailWhenLocked(true); + lock.lock(); + Directory dir = new Directory("org/foo"); + index.index(dir); } @Test @@ -139,4 +164,13 @@ public class DefaultIndexTest { assertThat(index.isIndexed(file), is(false)); assertThat(index.isExcluded(file), is(true)); } + + @Test + public void shouldIndexResourceWhenAddingMeasure() { + Resource dir = new Directory("org/foo"); + index.addMeasure(dir, new Measure("ncloc").setValue(50.0)); + + assertThat(index.isIndexed(dir), is(true)); + assertThat(index.getMeasures(dir, MeasuresFilters.metric("ncloc")).getIntValue(), is(50)); + } } diff --git a/sonar-java-api/src/main/java/org/sonar/java/api/JavaClass.java b/sonar-java-api/src/main/java/org/sonar/java/api/JavaClass.java index 0e2bc281479..563879e23bb 100644 --- a/sonar-java-api/src/main/java/org/sonar/java/api/JavaClass.java +++ b/sonar-java-api/src/main/java/org/sonar/java/api/JavaClass.java @@ -20,16 +20,15 @@ package org.sonar.java.api; import org.apache.commons.lang.StringUtils; -import org.sonar.api.resources.Java; -import org.sonar.api.resources.Language; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; +import org.sonar.api.resources.*; /** * @since 2.6 */ public final class JavaClass extends Resource { + public static final String SCOPE = Scopes.TYPE; + public static final String QUALIFIER = Qualifiers.CLASS; public static final int UNKNOWN_LINE = -1; private int fromLine = UNKNOWN_LINE; @@ -87,12 +86,12 @@ public final class JavaClass extends Resource { @Override public String getScope() { - return null; + return SCOPE; } @Override public String getQualifier() { - return Qualifiers.CLASS; + return QUALIFIER; } @Override diff --git a/sonar-java-api/src/main/java/org/sonar/java/api/JavaMethod.java b/sonar-java-api/src/main/java/org/sonar/java/api/JavaMethod.java index 6cf02551be6..743b3fa4069 100644 --- a/sonar-java-api/src/main/java/org/sonar/java/api/JavaMethod.java +++ b/sonar-java-api/src/main/java/org/sonar/java/api/JavaMethod.java @@ -20,16 +20,16 @@ package org.sonar.java.api; import org.apache.commons.lang.StringUtils; -import org.sonar.api.resources.Java; -import org.sonar.api.resources.Language; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; +import org.sonar.api.resources.*; /** * @since 2.6 */ public final class JavaMethod extends Resource { + public static final String SCOPE = Scopes.BLOCK_UNIT; + public static final String QUALIFIER = Qualifiers.METHOD; + public static final int UNKNOWN_LINE = -1; private static final String CLASS_SEPARATOR = "#"; @@ -88,12 +88,12 @@ public final class JavaMethod extends Resource { @Override public String getScope() { - return null; + return SCOPE; } @Override public String getQualifier() { - return Qualifiers.METHOD; + return QUALIFIER; } @Override diff --git a/sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java b/sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java index a1925501b5d..dad567cc1e3 100644 --- a/sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java +++ b/sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java @@ -25,6 +25,17 @@ public final class JavaUtils { public static final String PACKAGE_SEPARATOR = "."; + /** + * All sensors executed after this barrier are sure that all Java resources are indexed. + */ + public static final String BARRIER_BEFORE_SQUID = "BEFORE_SQUID"; + + /** + * Sensors executed before this barrier must not rely on index. No Java resources are indexed. + * Value is 'squid' in order to be backward-compatible with Sensor.FLAG_SQUID_ANALYSIS. + */ + public static final String BARRIER_AFTER_SQUID = "squid"; + private JavaUtils() { // only static methods } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/AbstractSourceImporter.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/AbstractSourceImporter.java index b11a96f5655..0c796b83ec0 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/AbstractSourceImporter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/AbstractSourceImporter.java @@ -21,10 +21,7 @@ package org.sonar.api.batch; import org.apache.commons.io.FileUtils; import org.sonar.api.CoreProperties; -import org.sonar.api.resources.Language; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.ProjectFileSystem; -import org.sonar.api.resources.Resource; +import org.sonar.api.resources.*; import org.sonar.api.utils.SonarException; import java.io.File; @@ -34,7 +31,7 @@ import java.util.List; /** * A pre-implementation for a sensor that imports sources - * + * * @since 1.10 */ @Phase(name = Phase.Name.PRE) @@ -103,7 +100,7 @@ public abstract class AbstractSourceImporter implements Sensor { if (resource != null) { resource.setLanguage(language); if (unitTest) { - resource.setQualifier(Resource.QUALIFIER_UNIT_TEST_CLASS); + resource.setQualifier(Qualifiers.UNIT_TEST_FILE); } } return resource; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java index 8811492b955..06ae5ae80fd 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java @@ -124,6 +124,12 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe addViolation(violation, false); } + /** + * Warning: the resource is automatically indexed for backward-compatibility, but it should be explictly + * indexed before. Next versions will deactivate this automatic indexation. + * + * @throws SonarException if the metric is unknown. + */ public abstract Measure addMeasure(Resource resource, Measure measure); public abstract Dependency addDependency(Dependency dependency); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java index 434fe55e23c..2b74a78a500 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java @@ -45,7 +45,11 @@ public final class MeasuresFilters { } public static MeasuresFilter<Measure> metric(final Metric metric) { - return new MetricFilter<Measure>(metric) { + return metric(metric.getKey()); + } + + public static MeasuresFilter<Measure> metric(final String metricKey) { + return new MetricFilter<Measure>(metricKey) { public Measure filter(Collection<Measure> measures) { if (measures == null) { @@ -53,7 +57,7 @@ public final class MeasuresFilters { } for (Measure measure : measures) { if (measure.getClass().equals(Measure.class) && - measure.getMetricKey().equals(metric.getKey()) && + measure.getMetricKey().equals(metricKey) && measure.getCharacteristic()==null) { return measure; } @@ -165,6 +169,10 @@ public final class MeasuresFilters { this.metricKey = metric.getKey(); } + protected MetricFilter(String metricKey) { + this.metricKey = metricKey; + } + public String filterOnMetricKey() { return metricKey; } diff --git a/sonar-server/src/main/java/org/sonar/server/filters/Filter.java b/sonar-server/src/main/java/org/sonar/server/filters/Filter.java index e50703f6353..d2c864ff181 100644 --- a/sonar-server/src/main/java/org/sonar/server/filters/Filter.java +++ b/sonar-server/src/main/java/org/sonar/server/filters/Filter.java @@ -23,6 +23,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Resource; import java.util.List; @@ -375,6 +376,6 @@ public class Filter { public static Filter createForAllQualifiers() { return new Filter().setQualifiers(Resource.QUALIFIER_VIEW, Resource.QUALIFIER_SUBVIEW, Resource.QUALIFIER_PROJECT, Resource.QUALIFIER_MODULE, Resource.QUALIFIER_DIRECTORY, Resource.QUALIFIER_PACKAGE, - Resource.QUALIFIER_FILE, Resource.QUALIFIER_CLASS, Resource.QUALIFIER_UNIT_TEST_CLASS, Resource.QUALIFIER_LIB); + Resource.QUALIFIER_FILE, Resource.QUALIFIER_CLASS, Qualifiers.UNIT_TEST_FILE, Resource.QUALIFIER_LIB); } } diff --git a/tests/integration/tests/build.xml b/tests/integration/tests/build.xml index 75bad16d20f..29f2fcfe14a 100644 --- a/tests/integration/tests/build.xml +++ b/tests/integration/tests/build.xml @@ -179,6 +179,7 @@ <arg value="-Dsonar.jdbc.driver=${sonar.jdbc.driver}"/> <arg value="-Dsonar.jdbc.username=${sonar.jdbc.username}"/> <arg value="-Dsonar.jdbc.password=${sonar.jdbc.password}"/> + <arg value="-Dsonar.hardIndexLock=true"/> </exec> <exec failonerror="@{failonerror}" executable="${maven.home}/bin/mvn" osfamily="unix"> <arg line="org.codehaus.mojo:sonar-maven-plugin:1.0-beta-2:sonar @{args} -B -e"/> @@ -187,6 +188,7 @@ <arg value="-Dsonar.jdbc.driver=${sonar.jdbc.driver}"/> <arg value="-Dsonar.jdbc.username=${sonar.jdbc.username}"/> <arg value="-Dsonar.jdbc.password=${sonar.jdbc.password}"/> + <arg value="-Dsonar.hardIndexLock=true"/> </exec> </sequential> </macrodef> |