diff options
author | simonbrandhof <simon.brandhof@gmail.com> | 2011-01-25 19:10:20 +0100 |
---|---|---|
committer | simonbrandhof <simon.brandhof@gmail.com> | 2011-01-25 19:26:43 +0100 |
commit | e7de7db7a3a3de0bf7961f0b5210156182622f10 (patch) | |
tree | a638d3b82ebf27f68184c527df61fff9923502ab | |
parent | f3b88bb8e5a57a215e59dcc5c38f550433c9a1eb (diff) | |
download | sonarqube-e7de7db7a3a3de0bf7961f0b5210156182622f10.tar.gz sonarqube-e7de7db7a3a3de0bf7961f0b5210156182622f10.zip |
Improve backward-compatibility when adding data to a non-indexed resource
17 files changed, 240 insertions, 216 deletions
diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java index 87e7699ba88..0e7a1c1e3f4 100644 --- a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java +++ b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/JavaSourceImporter.java @@ -19,30 +19,73 @@ */ package org.sonar.plugins.squid; +import org.apache.commons.io.FileUtils; +import org.sonar.api.CoreProperties; 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.api.resources.*; +import org.sonar.api.utils.SonarException; import org.sonar.java.api.JavaUtils; -import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; import java.util.List; -@DependsUpon(classes=SquidSensor.class) +@Phase(name = Phase.Name.PRE) +@DependsUpon(classes = SquidSensor.class) @DependedUpon(JavaUtils.BARRIER_AFTER_SQUID) -public class JavaSourceImporter extends AbstractSourceImporter { +public final class JavaSourceImporter implements Sensor { - public JavaSourceImporter() { - super(Java.INSTANCE); + /** + * {@inheritDoc} + */ + public boolean shouldExecuteOnProject(Project project) { + return isEnabled(project) && Java.KEY.equals(project.getLanguageKey()); } - @Override - protected Resource createResource(File file, List<File> sourceDirs, boolean unitTest) { - return file != null ? JavaFile.fromIOFile(file, sourceDirs, unitTest) : null; + /** + * {@inheritDoc} + */ + public void analyse(Project project, SensorContext context) { + analyse(project.getFileSystem(), context); + } + + void analyse(ProjectFileSystem fileSystem, SensorContext context) { + parseDirs(context, fileSystem.mainFiles(Java.INSTANCE), false, fileSystem.getSourceCharset()); + parseDirs(context, fileSystem.testFiles(Java.INSTANCE), true, fileSystem.getSourceCharset()); + } + + void parseDirs(SensorContext context, List<InputFile> inputFiles, boolean unitTest, Charset sourcesEncoding) { + for (InputFile inputFile : inputFiles) { + JavaFile javaFile = JavaFile.fromRelativePath(inputFile.getRelativePath(), unitTest); + importSource(context, javaFile, inputFile, sourcesEncoding); + } + } + + void importSource(SensorContext context, JavaFile javaFile, InputFile inputFile, Charset sourcesEncoding) { + try { + //if (!context.isIndexed(javaFile, true)) { + // See http://jira.codehaus.org/browse/SONAR-791 + // Squid is the reference plugin to index files. If a file is not indexed, + // throw new SonarException("Invalid file: " + javaFile + ". Please check that Java source directories match root directories" + + // " as defined by packages."); + //} + String source = FileUtils.readFileToString(inputFile.getFile(), sourcesEncoding.name()); + context.saveSource(javaFile, source); + + } catch (IOException e) { + throw new SonarException("Unable to read and import the source file : '" + inputFile.getFile().getAbsolutePath() + "' with the charset : '" + + sourcesEncoding.name() + "'.", e); + } + } + + boolean isEnabled(Project project) { + return project.getConfiguration().getBoolean(CoreProperties.CORE_IMPORT_SOURCES_PROPERTY, + CoreProperties.CORE_IMPORT_SOURCES_DEFAULT_VALUE); } @Override public String toString() { return getClass().getSimpleName(); } + } 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 c1b242e09de..c79a60d2559 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 @@ -25,6 +25,7 @@ import org.sonar.api.batch.*; import org.sonar.api.checks.AnnotationCheckFactory; import org.sonar.api.checks.NoSonarFilter; import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.resources.InputFile; import org.sonar.api.resources.Java; import org.sonar.api.resources.JavaFile; import org.sonar.api.resources.Project; @@ -82,22 +83,18 @@ public class SquidSensor implements Sensor { } private void browseTestSources(Project project, SensorContext context) { - for (File testFile : getTestSourceFiles(project)) { - context.index(JavaFile.fromIOFile(testFile, project.getFileSystem().getTestDirs(), true)); + for (InputFile testFile : project.getFileSystem().testFiles(Java.INSTANCE)) { + context.index(JavaFile.fromRelativePath(testFile.getRelativePath(), 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> getMainBytecodeFiles(Project project) { Collection<File> bytecodeFiles = projectClasspath.getElements(); - if ( !hasProjectBytecodeFiles(project)) { + if (!hasProjectBytecodeFiles(project)) { File classesDir = project.getFileSystem().getBuildOutputDir(); if (classesDir != null && classesDir.exists()) { bytecodeFiles.remove(classesDir); @@ -107,11 +104,11 @@ public class SquidSensor implements Sensor { } private boolean hasProjectBytecodeFiles(Project project) { - if ( !project.getConfiguration() + if (!project.getConfiguration() .getBoolean(CoreProperties.DESIGN_SKIP_DESIGN_PROPERTY, CoreProperties.DESIGN_SKIP_DESIGN_DEFAULT_VALUE)) { File classesDir = project.getFileSystem().getBuildOutputDir(); if (classesDir != null && classesDir.exists()) { - return !FileUtils.listFiles(classesDir, new String[] { "class" }, true).isEmpty(); + return !FileUtils.listFiles(classesDir, new String[]{"class"}, true).isEmpty(); } } return false; diff --git a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java index c6667a6920e..f90274d9964 100644 --- a/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java +++ b/plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/JavaSourceImporterTest.java @@ -19,42 +19,53 @@ */ package org.sonar.plugins.squid; -import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.resources.InputFile; import org.sonar.api.resources.JavaFile; -import org.sonar.api.resources.JavaPackage; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.ResourceUtils; +import org.sonar.api.utils.SonarException; import java.io.File; import java.io.IOException; -import java.util.Arrays; +import java.nio.charset.Charset; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.*; public class JavaSourceImporterTest { - @Test - 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")); - assertThat(clazz.getName(), is("MyClass")); + private JavaSourceImporter importer; + private SensorContext context; + private InputFile inputFile; + + @Before + public void init() { + File fileToImport = new File("test-resources/rules/UndocumentedApi.java"); + inputFile = mock(InputFile.class); + when(inputFile.getRelativePath()).thenReturn("UndocumentedApi.java"); + when(inputFile.getFile()).thenReturn(fileToImport); + when(inputFile.getFileBaseDir()).thenReturn(fileToImport.getParentFile()); + importer = new JavaSourceImporter(); + context = mock(SensorContext.class); } @Test - 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)); + public void shouldSetSource() throws IOException { + JavaFile javaFile = JavaFile.fromRelativePath("UndocumentedApi.java", true); + when(context.isIndexed(javaFile, true)).thenReturn(true); + importer.importSource(context, javaFile, inputFile, Charset.defaultCharset()); + + verify(context).saveSource(eq(javaFile), anyString()); } - private File newDir(String relativePath) throws IOException { - File target = new File("target", relativePath); - FileUtils.forceMkdir(target); - return target; + @Test(expected = SonarException.class) + @Ignore("see SONAR-791") + public void shouldFailWhenSquidDidNotIndexFile() throws IOException { + JavaFile javaFile = new JavaFile("Bar"); + when(context.isIndexed(javaFile, true)).thenReturn(false); + importer.importSource(context, javaFile, inputFile, Charset.defaultCharset()); } }
\ No newline at end of file diff --git a/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/javaFile.java b/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/javaFile.java deleted file mode 100644 index 5ea06251f14..00000000000 --- a/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/javaFile.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Javadoc for this Car class - * @author freddy - * - */ -public class Car { - - private int n; //C++ inline comment - private String s; - - public AClass(int n, String s) { - this.n = n; - this.s = s; - } - - /* - *C style comment - * - */ - public int getN() { - /* - * Another C style comment - */ - return n; - } - - public String getS() { - return s; - } - -}
\ No newline at end of file diff --git a/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/plsqlFile.pak b/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/plsqlFile.pak deleted file mode 100644 index f0e5a8535a5..00000000000 --- a/plugins/sonar-squid-java-plugin/test-resources/basic_handlers/plsqlFile.pak +++ /dev/null @@ -1,83 +0,0 @@ - -CREATE OR REPLACE PACKAGE SONAR002 AS - --- ---------------------------------------------------------------------------- --- package version -FUNCTION VERSION RETURN VARCHAR2; - PRAGMA RESTRICT_REFERENCES (VERSION, WNDS, WNPS, RNPS); - - -TYPE T_trans IS TABLE OF VARCHAR2(250) INDEX BY BINARY_INTEGER; -A_trans T_trans; -w_origine VARCHAR2(160); -w_sqlerrm VARCHAR2(255); - -header_c_langue VARCHAR2(2); - -TYPE T_TAG IS RECORD ( NOM_TAG VARCHAR2(50) - ,VALEUR VARCHAR2(32000)); - -TYPE TT_TAGS IS TABLE OF T_TAG INDEX BY BINARY_INTEGER; - -tb_TAGS TT_TAGS; - - -TYPE ControleData IS RECORD - ( pourcent NUMBER, - bande VARCHAR2(40), - nb_ligne NUMBER, - typ_avis VARCHAR2(25), - nb_brique NUMBER, - no_op operation.no_op%TYPE, - no_op_pere operation.no_op%TYPE, - no_op_doss operation.no_op%TYPE, - c_typ_contrat operation.c_typ_contrat%TYPE, - ref_op operation.ref_op%TYPE, - c_op_param type_oper_param.c_op_param%TYPE, - c_serv operation.c_serv%TYPE, - c_dev operation.c_dev%TYPE, - d_op operation.d_op%TYPE, - c_op_param_role VARCHAR2(4), - c_phase VARCHAR2(4), - c_phase_real VARCHAR2(4), - id_avis NUMBER, - c_form VARCHAR2(10), - c_teneur_envoi VARCHAR2(10), - Spool VARCHAR2(320), - spool_tmp VARCHAR2(320), - old_elt VARCHAR2(10), - new_elt VARCHAR2(10), - old_ligne NUMBER, - new_ligne NUMBER, - old_ordre NUMBER, - new_tag VARCHAR2(3), - old_tag VARCHAR2(3), - new_ordre NUMBER, - mode_fusion VARCHAR2(1), - TRACE VARCHAR2(80), - taux_cent_mille NUMBER, - caractere_taux VARCHAR2(1), - chemin_avis VARCHAR2(20), - nbr_dec_doss NUMBER, - c_dev_doss VARCHAR2(3), - mt_cpta_bloc_2 NUMBER, - regr_aff_dest VARCHAR2(1), - no_seq NUMBER(8), - no_seq_pere NUMBER(8), - id_envoi NUMBER(8), - id_envoi_pere NUMBER(8), - id_message NUMBER(8), - generation VARCHAR2(1), - c_uti VARCHAR2(6), - c_uti_cre VARCHAR2(6), - no_swift VARCHAR2(1), - c_trait_202 VARCHAR2(5), - envoi_pere_202 VARCHAR2(5), - f_envoi_ga_java VARCHAR2(1), - avec_templ_perso VARCHAR2(1), - f_comm_prises VARCHAR2(1), - liab_reduc_with_pmt VARCHAR2(1)); -Controle ControleData; - -END SONAR002; - diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java index a924fba8ac1..4a4acf8bf32 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java @@ -60,8 +60,8 @@ public class DefaultSensorContext implements SensorContext { return index.isExcluded(reference); } - public boolean isIndexed(Resource reference) { - return index.isIndexed(reference); + public boolean isIndexed(Resource reference, boolean acceptExcluded) { + return index.isIndexed(reference, acceptExcluded); } public Resource getParent(Resource reference) { @@ -155,8 +155,8 @@ public class DefaultSensorContext implements SensorContext { return index.getOutgoingEdges(resourceOrProject(from)); } - public boolean saveSource(Resource reference, String source) throws DuplicatedSourceException { - return index.setSource(reference, source); + public void saveSource(Resource reference, String source) throws DuplicatedSourceException { + index.setSource(reference, source); } public void saveLink(ProjectLink link) { 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 5660bf44ade..01ba7d6b384 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 @@ -157,7 +157,7 @@ public final class DefaultIndex extends SonarIndex { * the measure is updated if it's already registered. */ public Measure addMeasure(Resource resource, Measure measure) { - Bucket bucket = doIndex(resource); + Bucket bucket = checkIndexed(resource); if (bucket != null && !bucket.isExcluded()) { Metric metric = metricFinder.findByKey(measure.getMetricKey()); if (metric == null) { @@ -170,7 +170,6 @@ public final class DefaultIndex extends SonarIndex { if (measure.getPersistenceMode().useDatabase()) { persistence.saveMeasure(resource, measure); } - // TODO keep database measures in cache but remove data } return measure; @@ -295,13 +294,12 @@ public final class DefaultIndex extends SonarIndex { } public void addViolation(Violation violation, boolean force) { - Bucket bucket; Resource resource = violation.getResource(); if (resource == null) { violation.setResource(currentProject); } - bucket = doIndex(violation.getResource()); - if (!bucket.isExcluded()) { + Bucket bucket = checkIndexed(resource); + if (bucket != null && !bucket.isExcluded()) { boolean isIgnored = !force && violationFilters != null && violationFilters.isIgnored(violation); if (!isIgnored) { ActiveRule activeRule = profile.getActiveRule(violation.getRule()); @@ -366,13 +364,11 @@ public final class DefaultIndex extends SonarIndex { return null; } - public boolean setSource(Resource reference, String source) { - boolean result = false; - if (isIndexed(reference)) { + public void setSource(Resource reference, String source) { + Bucket bucket = checkIndexed(reference); + if (bucket != null && !bucket.isExcluded()) { persistence.setSource(reference, source); - result = true; } - return result; } @@ -387,7 +383,7 @@ public final class DefaultIndex extends SonarIndex { public <R extends Resource> R getResource(R reference) { Bucket bucket = buckets.get(reference); if (bucket != null) { - return (R)bucket.getResource(); + return (R) bucket.getResource(); } return null; } @@ -443,8 +439,7 @@ public final class DefaultIndex extends SonarIndex { private Bucket doIndex(Resource resource) { if (resource.getParent() != null) { - // SONAR-2127 backward-compatibility - create automatically parent of files - doIndex(resource.getParent(), currentProject); + doIndex(resource.getParent()); } return doIndex(resource, resource.getParent()); } @@ -469,7 +464,7 @@ public final class DefaultIndex extends SonarIndex { } Bucket parentBucket = getBucket(parent, true); - if (parentBucket==null && parent!=null) { + if (parentBucket == null && parent != null) { LOG.warn("Resource ignored, parent is not indexed: " + resource); return null; } @@ -480,7 +475,7 @@ public final class DefaultIndex extends SonarIndex { boolean excluded = checkExclusion(resource, parentBucket); if (!excluded) { - persistence.saveResource(currentProject, resource, (parentBucket!=null ? parentBucket.getResource() : null)); + persistence.saveResource(currentProject, resource, (parentBucket != null ? parentBucket.getResource() : null)); } return bucket; } @@ -494,13 +489,30 @@ public final class DefaultIndex extends SonarIndex { } } + private Bucket checkIndexed(Resource reference) { + Bucket bucket = getBucket(reference, true); + if (bucket == null) { + if (lock.isLocked()) { + if (lock.isFailWhenLocked()) { + throw new ResourceNotIndexedException(reference); + } + LOG.warn("Resource will be ignored in next Sonar versions, index is locked: " + reference); + } else { + // other languages than Java - keep backward compatibility + bucket = doIndex(reference); + } + } + return bucket; + } + + public boolean isExcluded(Resource reference) { Bucket bucket = getBucket(reference, true); return bucket != null && bucket.isExcluded(); } - public boolean isIndexed(Resource reference) { - return getBucket(reference, false) != null; + public boolean isIndexed(Resource reference, boolean acceptExcluded) { + return getBucket(reference, acceptExcluded) != null; } private Bucket getBucket(Resource resource, boolean acceptExcluded) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceNotIndexedException.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceNotIndexedException.java new file mode 100644 index 00000000000..203f4043ff6 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceNotIndexedException.java @@ -0,0 +1,33 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.batch.index; + +import org.sonar.api.resources.Resource; +import org.sonar.api.utils.SonarException; + +/** + * @since 2.6 + */ +public class ResourceNotIndexedException extends SonarException { + + public ResourceNotIndexedException(final Resource reference) { + super(reference.toString()); + } +} 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 e90cd8a9b61..ef88932c7e1 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 @@ -85,7 +85,7 @@ public class DefaultIndexTest { Directory reference = new Directory("org/foo"); assertThat(index.getResource(reference).getName(), is("org/foo")); - assertThat(index.isIndexed(reference), is(true)); + assertThat(index.isIndexed(reference, true), is(true)); assertThat(index.isExcluded(reference), is(false)); assertThat(index.getChildren(reference).size(), is(1)); assertThat(index.getParent(reference), is(Project.class)); @@ -103,7 +103,7 @@ public class DefaultIndexTest { File fileRef = new File("org/foo/Bar.java"); assertThat(index.getResource(fileRef).getKey(), is("org/foo/Bar.java")); assertThat(index.getResource(fileRef).getLanguage(), is((Language) Java.INSTANCE)); - assertThat(index.isIndexed(fileRef), is(true)); + assertThat(index.isIndexed(fileRef, true), is(true)); assertThat(index.isExcluded(fileRef), is(false)); assertThat(index.getChildren(fileRef).size(), is(0)); assertThat(index.getParent(fileRef), is(Directory.class)); @@ -116,7 +116,7 @@ public class DefaultIndexTest { Library reference = new Library("junit", "4.8"); assertThat(index.getResource(reference).getQualifier(), is(Qualifiers.LIBRARY)); - assertThat(index.isIndexed(reference), is(true)); + assertThat(index.isIndexed(reference, true), is(true)); assertThat(index.isExcluded(reference), is(false)); } @@ -128,8 +128,8 @@ public class DefaultIndexTest { assertThat(index.index(file, directory), is(false)); File fileRef = new File("org/foo/Bar.java"); - assertThat(index.isIndexed(directory), is(false)); - assertThat(index.isIndexed(fileRef), is(false)); + assertThat(index.isIndexed(directory, true), is(false)); + assertThat(index.isIndexed(fileRef, true), is(false)); assertThat(index.isExcluded(fileRef), is(false)); assertThat(index.getChildren(fileRef).size(), is(0)); assertThat(index.getParent(fileRef), nullValue()); @@ -145,7 +145,7 @@ public class DefaultIndexTest { Directory dir = new Directory("org/foo"); assertThat(index.index(dir), is(true)); - assertThat(index.isIndexed(dir), is(true)); + assertThat(index.isIndexed(dir, true), is(true)); } @Test(expected = SonarException.class) @@ -161,7 +161,8 @@ public class DefaultIndexTest { public void shouldBeExcluded() { File file = new File("org/foo/ExcludedBar.java"); assertThat(index.index(file), is(false)); - assertThat(index.isIndexed(file), is(false)); + assertThat(index.isIndexed(file, true), is(true)); + assertThat(index.isIndexed(file, false), is(false)); assertThat(index.isExcluded(file), is(true)); } @@ -170,7 +171,7 @@ public class DefaultIndexTest { Resource dir = new Directory("org/foo"); index.addMeasure(dir, new Measure("ncloc").setValue(50.0)); - assertThat(index.isIndexed(dir), is(true)); + assertThat(index.isIndexed(dir, true), 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/JavaUtils.java b/sonar-java-api/src/main/java/org/sonar/java/api/JavaUtils.java index dad567cc1e3..9fa234f5626 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 @@ -24,6 +24,7 @@ import org.apache.commons.lang.StringUtils; public final class JavaUtils { public static final String PACKAGE_SEPARATOR = "."; + public static final String DEFAULT_PACKAGE = "[default]"; /** * All sensors executed after this barrier are sure that all Java resources are indexed. diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java index 07b58dc1a13..8ac007a1e6a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java @@ -58,15 +58,16 @@ public interface SensorContext { boolean index(Resource resource, Resource parentReference); /** - * Returns true if the referenced resource is excluded. An excluded resource is not indexed. + * Returns true if the referenced resource is indexed and excluded. * @since 2.6 */ boolean isExcluded(Resource reference); /** + * Returns true if the referenced resource is indexed. * @since 2.6 */ - boolean isIndexed(Resource reference); + boolean isIndexed(Resource reference, boolean acceptExcluded); /** * Search for an indexed resource. @@ -88,7 +89,6 @@ public interface SensorContext { Collection<Resource> getChildren(Resource reference); - // ----------- MEASURES ON PROJECT -------------- /** @@ -188,14 +188,13 @@ public interface SensorContext { /** * Save the source code of a file. The file must be have been indexed before. - * Note: the source stream is not closed. * * @return false if the resource is excluded or not indexed * @throws org.sonar.api.resources.DuplicatedSourceException * if the source has already been set on this resource * @since 1.10. Returns a boolean since 2.6. */ - boolean saveSource(Resource reference, String source) throws DuplicatedSourceException; + void saveSource(Resource reference, String source) throws DuplicatedSourceException; // ----------- LINKS -------------- 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 06ae5ae80fd..cf441562c1b 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 @@ -39,6 +39,7 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe /** * Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed. + * If the method resource.getParent() does not return null, then this parent will be indexed too. * * @return false if the resource is excluded * @since 2.6 @@ -65,7 +66,7 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe /** * @since 2.6 */ - public abstract boolean isIndexed(Resource reference); + public abstract boolean isIndexed(Resource reference, boolean acceptExcluded); /** * Search for an indexed resource. @@ -95,7 +96,7 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe * @throws org.sonar.api.resources.DuplicatedSourceException * if the source has already been set on this resource */ - public abstract boolean setSource(Resource reference, String source) throws DuplicatedSourceException; + public abstract void setSource(Resource reference, String source) throws DuplicatedSourceException; public abstract Project getProject(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java index 4b7837779e3..85a47eb8945 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java @@ -353,11 +353,11 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { return getFiles(getTestDirs(), false /* FIXME should be true? */, langs); } - private class DefaultInputFile implements InputFile { + private static final class DefaultInputFile implements InputFile { private File basedir; private File file; - public DefaultInputFile(File basedir, File file) { + DefaultInputFile(File basedir, File file) { this.basedir = basedir; this.file = file; } @@ -369,6 +369,10 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { public File getFile() { return file; } + + public String getRelativePath() { + return DefaultProjectFileSystem.getRelativePath(file, basedir); + } } /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java index 24b7d32b6b8..40872867c7e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/File.java @@ -38,7 +38,7 @@ public class File extends Resource<Directory> { private String filename; private Language language; private Directory parent; - private String qualifier = Resource.QUALIFIER_FILE; + private String qualifier = Qualifiers.FILE; /** * File in project. Key is the path relative to project source directories. It is not the absolute path and it does not include the path @@ -187,8 +187,8 @@ public class File extends Resource<Directory> { /** * @return SCOPE_ENTITY */ - public String getScope() { - return Resource.SCOPE_ENTITY; + public final String getScope() { + return SCOPE; } /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java index 6e87e3445ad..4c926f897e1 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/InputFile.java @@ -30,4 +30,14 @@ public interface InputFile { File getFile(); + /** + * Path relative to basedir. Directory separator is slash '/', whatever the platform. + * + * Example on windows: if basedir is c:\project\src\ and file is c:\project\src\org\foo\Bar.java, then relative path + * is org/foo/Bar.java + * + * Example on unix: if basedir is /project/src and file is /project/src/org/foo/Bar.java, then relative path + * is org/foo/Bar.java as well. + */ + String getRelativePath(); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java index ef940898ced..009a04e670a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaFile.java @@ -37,7 +37,7 @@ public class JavaFile extends Resource<JavaPackage> { private String longName; private String packageKey; private boolean unitTest; - private JavaPackage parent = null; + private JavaPackage parent; /** * Creates a JavaFile that is not a class of test based on package and file names @@ -52,7 +52,7 @@ public class JavaFile extends Resource<JavaPackage> { * @param unitTest whether it is a unit test file or a source file */ public JavaFile(String packageKey, String className, boolean unitTest) { - if (className==null) { + if (className == null) { throw new IllegalArgumentException("Java filename can not be null"); } if (className.indexOf('$') >= 0) { @@ -86,10 +86,10 @@ public class JavaFile extends Resource<JavaPackage> { * @param unitTest whether it is a unit test file or a source file */ public JavaFile(String key, boolean unitTest) { - if (key==null) { + if (key == null) { throw new IllegalArgumentException("Java filename can not be null"); } - if (key != null && key.indexOf('$') >= 0) { + if (key.indexOf('$') >= 0) { throw new IllegalArgumentException("Java inner classes are not supported : " + key); } String realKey = StringUtils.trim(key); @@ -117,6 +117,7 @@ public class JavaFile extends Resource<JavaPackage> { parent = new JavaPackage(packageKey); } return parent; + } /** @@ -151,14 +152,14 @@ public class JavaFile extends Resource<JavaPackage> { * @return SCOPE_ENTITY */ public String getScope() { - return Resource.SCOPE_ENTITY; + return Scopes.FILE; } /** * @return QUALIFIER_UNIT_TEST_CLASS or QUALIFIER_CLASS depending whether it is a unit test class */ public String getQualifier() { - return unitTest ? Qualifiers.UNIT_TEST_FILE : Resource.QUALIFIER_CLASS; + return unitTest ? Qualifiers.UNIT_TEST_FILE : Qualifiers.CLASS; } /** @@ -179,23 +180,14 @@ public class JavaFile extends Resource<JavaPackage> { if (!fileKey.endsWith(".java")) { fileKey += ".java"; } - if (StringUtils.substringAfterLast(antPattern, "/").indexOf(".")<0) { + if (StringUtils.substringAfterLast(antPattern, "/").indexOf(".") < 0) { antPattern += ".*"; } WildcardPattern matcher = WildcardPattern.create(antPattern, "."); return matcher.match(fileKey); } - /** - * Creates a JavaFile from a file in the source directories - * - * @return the JavaFile created if exists, null otherwise - */ - public static JavaFile fromIOFile(File file, List<File> sourceDirs, boolean unitTest) { - if (file == null || !StringUtils.endsWithIgnoreCase(file.getName(), ".java")) { - return null; - } - String relativePath = DefaultProjectFileSystem.getRelativePath(file, sourceDirs); + public static JavaFile fromRelativePath(String relativePath, boolean unitTest) { if (relativePath != null) { String pacname = null; String classname = relativePath; @@ -212,6 +204,19 @@ public class JavaFile extends Resource<JavaPackage> { } /** + * Creates a JavaFile from a file in the source directories + * + * @return the JavaFile created if exists, null otherwise + */ + public static JavaFile fromIOFile(File file, List<File> sourceDirs, boolean unitTest) { + if (file == null || !StringUtils.endsWithIgnoreCase(file.getName(), ".java")) { + return null; + } + String relativePath = DefaultProjectFileSystem.getRelativePath(file, sourceDirs); + return fromRelativePath(relativePath, unitTest); + } + + /** * Shortcut to fromIOFile with an abolute path */ public static JavaFile fromAbsolutePath(String path, List<File> sourceDirs, boolean unitTest) { @@ -230,4 +235,25 @@ public class JavaFile extends Resource<JavaPackage> { .append("unitTest", unitTest) .toString(); } + +// @Override +// public boolean equals(Object o) { +// if (this == o) return true; +// if (o == null || getClass() != o.getClass()) return false; +// if (!super.equals(o)) return false; +// +// JavaFile javaFile = (JavaFile) o; +// if (unitTest != javaFile.unitTest) return false; +// if (!getKey().equals(javaFile.getKey())) return false; +// +// return true; +// } +// +// @Override +// public int hashCode() { +// int result = super.hashCode(); +// result = 31 * result + getKey().hashCode(); +// result = 31 * result + (unitTest ? 1 : 0); +// return result; +// } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java index d61088c1b45..0ec5528ca9f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/JavaPackage.java @@ -80,7 +80,7 @@ public class JavaPackage extends Resource { * @return QUALIFIER_PACKAGE */ public String getQualifier() { - return Resource.QUALIFIER_PACKAGE; + return Qualifiers.PACKAGE; } /** |