diff options
21 files changed, 280 insertions, 344 deletions
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/DefaultCpdEngine.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/DefaultCpdEngine.java index 887c886ac1e..925ecb87638 100644 --- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/DefaultCpdEngine.java +++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/DefaultCpdEngine.java @@ -110,22 +110,7 @@ public class DefaultCpdEngine extends CpdEngine { // Create index SonarDuplicationsIndex index = indexFactory.create(project, languageKey); - - TokenizerBridge bridge = null; - if (mapping != null) { - bridge = new TokenizerBridge(mapping.getTokenizer(), fs.encoding().name(), getBlockSize(languageKey)); - } - for (InputFile inputFile : sourceFiles) { - LOG.debug("Populating index from {}", inputFile); - String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key(); - FileBlocks fileBlocks = duplicationCache.byComponent(resourceEffectiveKey); - if (fileBlocks != null) { - index.insert(inputFile, fileBlocks.blocks()); - } else if (bridge != null) { - List<Block> blocks2 = bridge.chunk(resourceEffectiveKey, inputFile.file()); - index.insert(inputFile, blocks2); - } - } + populateIndex(languageKey, sourceFiles, mapping, index); // Detect Predicate<CloneGroup> minimumTokensPredicate = DuplicationPredicates.numberOfUnitsNotLessThan(getMinimumTokens(languageKey)); @@ -157,6 +142,24 @@ public class DefaultCpdEngine extends CpdEngine { } } + private void populateIndex(String languageKey, List<InputFile> sourceFiles, CpdMapping mapping, SonarDuplicationsIndex index) { + TokenizerBridge bridge = null; + if (mapping != null) { + bridge = new TokenizerBridge(mapping.getTokenizer(), fs.encoding().name(), getBlockSize(languageKey)); + } + for (InputFile inputFile : sourceFiles) { + LOG.debug("Populating index from {}", inputFile); + String resourceEffectiveKey = ((DeprecatedDefaultInputFile) inputFile).key(); + FileBlocks fileBlocks = duplicationCache.byComponent(resourceEffectiveKey); + if (fileBlocks != null) { + index.insert(inputFile, fileBlocks.blocks()); + } else if (bridge != null) { + List<Block> blocks2 = bridge.chunk(resourceEffectiveKey, inputFile.file()); + index.insert(inputFile, blocks2); + } + } + } + @VisibleForTesting int getBlockSize(String languageKey) { int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines"); diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/JavaCpdEngine.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/JavaCpdEngine.java index 43585d4db4f..a5770634444 100644 --- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/JavaCpdEngine.java +++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/JavaCpdEngine.java @@ -198,20 +198,8 @@ public class JavaCpdEngine extends CpdEngine { if (duplications == null || Iterables.isEmpty(duplications)) { return; } - // Calculate number of lines and blocks Set<Integer> duplicatedLines = new HashSet<Integer>(); - int duplicatedBlocks = 0; - for (CloneGroup clone : duplications) { - ClonePart origin = clone.getOriginPart(); - for (ClonePart part : clone.getCloneParts()) { - if (part.getResourceId().equals(origin.getResourceId())) { - duplicatedBlocks++; - for (int duplicatedLine = part.getStartLine(); duplicatedLine < part.getStartLine() + part.getLines(); duplicatedLine++) { - duplicatedLines.add(duplicatedLine); - } - } - } - } + int duplicatedBlocks = computeBlockAndLineCount(duplications, duplicatedLines); FileLinesContext linesContext = contextFactory.createFor(inputFile); for (int i = 1; i <= inputFile.lines(); i++) { linesContext.setIntValue(CoreMetrics.DUPLICATION_LINES_DATA_KEY, i, duplicatedLines.contains(i) ? 1 : 0); @@ -246,4 +234,20 @@ public class JavaCpdEngine extends CpdEngine { context.saveDuplications(inputFile, builder.build()); } + private static int computeBlockAndLineCount(Iterable<CloneGroup> duplications, Set<Integer> duplicatedLines) { + int duplicatedBlocks = 0; + for (CloneGroup clone : duplications) { + ClonePart origin = clone.getOriginPart(); + for (ClonePart part : clone.getCloneParts()) { + if (part.getResourceId().equals(origin.getResourceId())) { + duplicatedBlocks++; + for (int duplicatedLine = part.getStartLine(); duplicatedLine < part.getStartLine() + part.getLines(); duplicatedLine++) { + duplicatedLines.add(duplicatedLine); + } + } + } + } + return duplicatedBlocks; + } + } diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/IndexFactory.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/IndexFactory.java index 6d5a7f1201d..9830f4b1dd0 100644 --- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/IndexFactory.java +++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/IndexFactory.java @@ -64,7 +64,7 @@ public class IndexFactory implements BatchComponent { } @VisibleForTesting - boolean verifyCrossProject(Project project, Logger logger) { + boolean verifyCrossProject(@Nullable Project project, Logger logger) { boolean crossProject = false; if (settings.getBoolean(CoreProperties.CPD_CROSS_PROJECT)) { diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooConstants.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooConstants.java deleted file mode 100644 index 62f7d2ba782..00000000000 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooConstants.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.xoo; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public interface XooConstants { - - String PLUGIN_KEY = "xoo"; - String PLUGIN_NAME = "Xoo"; - - String REPOSITORY_KEY = PLUGIN_KEY; - String REPOSITORY_NAME = PLUGIN_NAME; - - String[] FILE_SUFFIXES = {"xoo"}; - - Logger LOG = LoggerFactory.getLogger("xoo"); -} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java index bc796808f19..4ce85626d15 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java @@ -21,6 +21,8 @@ package org.sonar.xoo.lang; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.batch.sensor.Sensor; @@ -30,7 +32,6 @@ import org.sonar.api.batch.sensor.measure.Measure; import org.sonar.api.batch.sensor.measure.MeasureBuilder; import org.sonar.api.measures.CoreMetrics; import org.sonar.xoo.Xoo; -import org.sonar.xoo.XooConstants; import java.io.File; import java.io.IOException; @@ -42,6 +43,8 @@ import java.util.List; */ public class MeasureSensor implements Sensor { + private static final Logger LOG = LoggerFactory.getLogger(MeasureSensor.class); + private static final String MEASURES_EXTENSION = ".measures"; private MetricFinder metricFinder; @@ -54,7 +57,7 @@ public class MeasureSensor implements Sensor { File ioFile = inputFile.file(); File measureFile = new File(ioFile.getParentFile(), ioFile.getName() + MEASURES_EXTENSION); if (measureFile.exists()) { - XooConstants.LOG.debug("Processing " + measureFile.getAbsolutePath()); + LOG.debug("Processing " + measureFile.getAbsolutePath()); try { List<String> lines = FileUtils.readLines(measureFile, context.fileSystem().encoding().name()); int lineNumber = 0; @@ -81,7 +84,7 @@ public class MeasureSensor implements Sensor { } } - private Measure<?> createMeasure(SensorContext context, InputFile xooFile, String metricKey, String value) { + private Measure createMeasure(SensorContext context, InputFile xooFile, String metricKey, String value) { org.sonar.api.batch.measure.Metric<Serializable> metric = metricFinder.findByKey(metricKey); if (metric == null) { throw new IllegalStateException("Unknow metric with key: " + metricKey); diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java index 628ce6ece70..c8232484a51 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java @@ -22,6 +22,8 @@ package org.sonar.xoo.lang; import com.google.common.base.Splitter; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.SensorContext; @@ -30,7 +32,6 @@ import org.sonar.api.batch.sensor.symbol.Symbol; import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; import org.sonar.api.measures.CoreMetrics; import org.sonar.xoo.Xoo; -import org.sonar.xoo.XooConstants; import java.io.File; import java.io.IOException; @@ -42,41 +43,44 @@ import java.util.List; */ public class SymbolReferencesSensor implements Sensor { + private static final Logger LOG = LoggerFactory.getLogger(SymbolReferencesSensor.class); + private static final String SYMBOL_EXTENSION = ".symbol"; private void processFileSymbol(InputFile inputFile, SensorContext context) { File ioFile = inputFile.file(); File symbolFile = new File(ioFile.getParentFile(), ioFile.getName() + SYMBOL_EXTENSION); if (symbolFile.exists()) { - XooConstants.LOG.debug("Processing " + symbolFile.getAbsolutePath()); + LOG.debug("Processing " + symbolFile.getAbsolutePath()); try { List<String> lines = FileUtils.readLines(symbolFile, context.fileSystem().encoding().name()); int lineNumber = 0; SymbolTableBuilder symbolTableBuilder = context.symbolTableBuilder(inputFile); for (String line : lines) { lineNumber++; - if (StringUtils.isBlank(line)) { - continue; - } - if (line.startsWith("#")) { + if (StringUtils.isBlank(line) || line.startsWith("#")) { continue; } - try { - Iterator<String> split = Splitter.on(",").split(line).iterator(); - int startOffset = Integer.parseInt(split.next()); - int endOffset = Integer.parseInt(split.next()); - Symbol s = symbolTableBuilder.newSymbol(startOffset, endOffset); - while (split.hasNext()) { - symbolTableBuilder.newReference(s, Integer.parseInt(split.next())); - } - } catch (Exception e) { - throw new IllegalStateException("Error processing line " + lineNumber + " of file " + symbolFile.getAbsolutePath(), e); - } + processLine(symbolFile, lineNumber, symbolTableBuilder, line); } symbolTableBuilder.done(); } catch (IOException e) { - throw new RuntimeException(e); + throw new IllegalStateException(e); + } + } + } + + private void processLine(File symbolFile, int lineNumber, SymbolTableBuilder symbolTableBuilder, String line) { + try { + Iterator<String> split = Splitter.on(",").split(line).iterator(); + int startOffset = Integer.parseInt(split.next()); + int endOffset = Integer.parseInt(split.next()); + Symbol s = symbolTableBuilder.newSymbol(startOffset, endOffset); + while (split.hasNext()) { + symbolTableBuilder.newReference(s, Integer.parseInt(split.next())); } + } catch (Exception e) { + throw new IllegalStateException("Error processing line " + lineNumber + " of file " + symbolFile.getAbsolutePath(), e); } } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java index ca2f6b5e0ac..c9c9b886406 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java @@ -19,19 +19,19 @@ */ package org.sonar.xoo.lang; -import org.sonar.api.batch.sensor.highlighting.TypeOfText; - import com.google.common.base.Splitter; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorDescriptor; import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder; +import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.measures.CoreMetrics; import org.sonar.xoo.Xoo; -import org.sonar.xoo.XooConstants; import java.io.File; import java.io.IOException; @@ -43,42 +43,45 @@ import java.util.List; */ public class SyntaxHighlightingSensor implements Sensor { + private static final Logger LOG = LoggerFactory.getLogger(SyntaxHighlightingSensor.class); + private static final String HIGHLIGHTING_EXTENSION = ".highlighting"; private void processFileHighlighting(InputFile inputFile, SensorContext context) { File ioFile = inputFile.file(); File highlightingFile = new File(ioFile.getParentFile(), ioFile.getName() + HIGHLIGHTING_EXTENSION); if (highlightingFile.exists()) { - XooConstants.LOG.debug("Processing " + highlightingFile.getAbsolutePath()); + LOG.debug("Processing " + highlightingFile.getAbsolutePath()); try { List<String> lines = FileUtils.readLines(highlightingFile, context.fileSystem().encoding().name()); int lineNumber = 0; HighlightingBuilder highlightingBuilder = context.highlightingBuilder(inputFile); for (String line : lines) { lineNumber++; - if (StringUtils.isBlank(line)) { - continue; - } - if (line.startsWith("#")) { + if (StringUtils.isBlank(line) || line.startsWith("#")) { continue; } - try { - Iterator<String> split = Splitter.on(":").split(line).iterator(); - int startOffset = Integer.parseInt(split.next()); - int endOffset = Integer.parseInt(split.next()); - TypeOfText type = TypeOfText.forCssClass(split.next()); - highlightingBuilder.highlight(startOffset, endOffset, type); - } catch (Exception e) { - throw new IllegalStateException("Error processing line " + lineNumber + " of file " + highlightingFile.getAbsolutePath(), e); - } + processLine(highlightingFile, lineNumber, highlightingBuilder, line); } highlightingBuilder.done(); } catch (IOException e) { - throw new RuntimeException(e); + throw new IllegalStateException(e); } } } + private void processLine(File highlightingFile, int lineNumber, HighlightingBuilder highlightingBuilder, String line) { + try { + Iterator<String> split = Splitter.on(":").split(line).iterator(); + int startOffset = Integer.parseInt(split.next()); + int endOffset = Integer.parseInt(split.next()); + TypeOfText type = TypeOfText.forCssClass(split.next()); + highlightingBuilder.highlight(startOffset, endOffset, type); + } catch (Exception e) { + throw new IllegalStateException("Error processing line " + lineNumber + " of file " + highlightingFile.getAbsolutePath(), e); + } + } + @Override public void describe(SensorDescriptor descriptor) { descriptor diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java index c3e7d2641e6..041bdd94efd 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java @@ -25,7 +25,6 @@ import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorDescriptor; import org.sonar.xoo.Xoo; -import org.sonar.xoo.XooConstants; public class CreateIssueByInternalKeySensor implements Sensor { @@ -36,7 +35,7 @@ public class CreateIssueByInternalKeySensor implements Sensor { descriptor .name("CreateIssueByInternalKeySensor") .workOnLanguages(Xoo.KEY) - .createIssuesForRuleRepositories(XooConstants.REPOSITORY_KEY) + .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY) .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST); } @@ -48,7 +47,7 @@ public class CreateIssueByInternalKeySensor implements Sensor { } private void createIssues(InputFile file, SensorContext context) { - ActiveRule rule = context.activeRules().findByInternalKey(XooConstants.REPOSITORY_KEY, + ActiveRule rule = context.activeRules().findByInternalKey(XooRulesDefinition.XOO_REPOSITORY, context.settings().getString(INTERNAL_KEY_PROPERTY)); if (rule != null) { context.addIssue(context.issueBuilder() diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java index c2478830975..6763d0308c8 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java @@ -26,7 +26,6 @@ import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorDescriptor; import org.sonar.api.rule.RuleKey; import org.sonar.xoo.Xoo; -import org.sonar.xoo.XooConstants; public class OneIssueOnDirPerFileSensor implements Sensor { @@ -37,7 +36,7 @@ public class OneIssueOnDirPerFileSensor implements Sensor { descriptor .name("One Issue On Dir Per File") .workOnLanguages(Xoo.KEY) - .createIssuesForRuleRepositories(XooConstants.REPOSITORY_KEY) + .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY) .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST); } @@ -49,7 +48,7 @@ public class OneIssueOnDirPerFileSensor implements Sensor { } private void createIssues(InputFile file, SensorContext context) { - RuleKey ruleKey = RuleKey.of(XooConstants.REPOSITORY_KEY, RULE_KEY); + RuleKey ruleKey = RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY); InputDir inputDir = context.fileSystem().inputDir(file.file().getParentFile()); if (inputDir != null) { context.addIssue(context.issueBuilder() diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java index bc0697b64b4..e65efa43718 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java @@ -29,7 +29,6 @@ import org.sonar.api.batch.sensor.measure.Measure; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.rule.RuleKey; import org.sonar.xoo.Xoo; -import org.sonar.xoo.XooConstants; public class OneIssuePerLineSensor implements Sensor { @@ -43,7 +42,7 @@ public class OneIssuePerLineSensor implements Sensor { .name("One Issue Per Line") .dependsOn(CoreMetrics.LINES) .workOnLanguages(Xoo.KEY) - .createIssuesForRuleRepositories(XooConstants.REPOSITORY_KEY) + .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY) .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST); } @@ -55,7 +54,7 @@ public class OneIssuePerLineSensor implements Sensor { } private void createIssues(InputFile file, SensorContext context) { - RuleKey ruleKey = RuleKey.of(XooConstants.REPOSITORY_KEY, RULE_KEY); + RuleKey ruleKey = RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY); Measure<Integer> linesMeasure = context.getMeasure(file, CoreMetrics.LINES); if (linesMeasure == null) { LoggerFactory.getLogger(getClass()).warn("Missing measure " + CoreMetrics.LINES_KEY + " on " + file); diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java index c05fe0e0976..0f37cefcb42 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java @@ -42,13 +42,13 @@ public class XooRulesDefinition implements RulesDefinition { .setName("No empty line") .setMarkdownDescription("Generate an issue on *empty* lines of Xoo source files") - // optional tags + // optional tags .setTags("style", "security") - // optional status. Default value is READY. + // optional status. Default value is READY. .setStatus(RuleStatus.BETA) - // default severity when the rule is activated on a Quality profile. Default value is MAJOR. + // default severity when the rule is activated on a Quality profile. Default value is MAJOR. .setSeverity(Severity.MINOR); // debt-related information diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultTokenBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultTokenBuilder.java index b4af6917440..6add5331875 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultTokenBuilder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultTokenBuilder.java @@ -21,8 +21,6 @@ package org.sonar.batch.duplication; import com.google.common.base.Preconditions; import net.sourceforge.pmd.cpd.TokenEntry; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder; @@ -37,8 +35,6 @@ import java.util.List; public class DefaultTokenBuilder implements DuplicationTokenBuilder { - private static final Logger LOG = LoggerFactory.getLogger(DefaultTokenBuilder.class); - private final BlockCache cache; private final InputFile inputFile; private final List<TokenEntry> tokens = new ArrayList<TokenEntry>(); @@ -69,7 +65,7 @@ public class DefaultTokenBuilder implements DuplicationTokenBuilder { tokens.add(TokenEntry.getEOF()); TokenEntry.clearImages(); List<TokensLine> tokensLines = TokenizerBridge.convert(tokens); - ArrayList<Block> blocks = blockChunker.chunk(((DefaultInputFile) inputFile).key(), tokensLines); + List<Block> blocks = blockChunker.chunk(((DefaultInputFile) inputFile).key(), tokensLines); cache.put(((DefaultInputFile) inputFile).key(), new FileBlocks(((DefaultInputFile) inputFile).key(), blocks)); tokens.clear(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroupValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroupValueCoder.java index 5b6ed6d8401..f53dfb4a569 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroupValueCoder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroupValueCoder.java @@ -26,6 +26,7 @@ import org.sonar.api.batch.sensor.duplication.DuplicationGroup; import org.sonar.api.batch.sensor.duplication.DuplicationGroup.Block; import java.util.ArrayList; +import java.util.List; class DuplicationGroupValueCoder implements ValueCoder { @@ -45,7 +46,7 @@ class DuplicationGroupValueCoder implements ValueCoder { public Object get(Value value, Class clazz, CoderContext context) { DuplicationGroup g = new DuplicationGroup((Block) blockCoder.get(value, DuplicationGroup.Block.class, context)); int count = value.getInt(); - ArrayList<DuplicationGroup.Block> blocks = new ArrayList<DuplicationGroup.Block>(count); + List<DuplicationGroup.Block> blocks = new ArrayList<DuplicationGroup.Block>(count); for (int i = 0; i < count; i++) { blocks.add((Block) blockCoder.get(value, DuplicationGroup.Block.class, context)); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java index 1cf87b1d6d3..6a117d7ec6a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java @@ -19,27 +19,16 @@ */ package org.sonar.batch.scan; -import com.google.common.base.Preconditions; +import org.sonar.api.batch.Sensor; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputDir; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputPath; -import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.measure.Metric; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.sensor.SensorContext; -import org.sonar.api.batch.sensor.duplication.DuplicationBuilder; -import org.sonar.api.batch.sensor.duplication.DuplicationGroup; -import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplicationBuilder; -import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder; import org.sonar.api.batch.sensor.issue.Issue; -import org.sonar.api.batch.sensor.issue.IssueBuilder; -import org.sonar.api.batch.sensor.issue.internal.DefaultIssueBuilder; import org.sonar.api.batch.sensor.measure.Measure; -import org.sonar.api.batch.sensor.measure.MeasureBuilder; -import org.sonar.api.batch.sensor.measure.internal.DefaultMeasureBuilder; -import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; import org.sonar.api.component.ResourcePerspectives; import org.sonar.api.config.Settings; import org.sonar.api.issue.Issuable; @@ -55,66 +44,32 @@ import org.sonar.api.resources.Resource; import org.sonar.api.resources.Scopes; import org.sonar.api.rule.RuleKey; import org.sonar.batch.duplication.BlockCache; -import org.sonar.batch.duplication.DefaultTokenBuilder; import org.sonar.batch.duplication.DuplicationCache; -import org.sonar.batch.highlighting.DefaultHighlightingBuilder; import org.sonar.batch.index.ComponentDataCache; -import org.sonar.batch.symbol.DefaultSymbolTableBuilder; -import org.sonar.duplications.internal.pmd.PmdBlockChunker; +import org.sonar.batch.scan2.CommonSensorContext; import java.io.Serializable; -import java.util.List; /** * Implements {@link SensorContext} but forward everything to {@link org.sonar.api.batch.SensorContext} for backward compatibility. + * Will be dropped once old {@link Sensor} API is dropped. * */ -public class SensorContextAdaptor implements SensorContext { +public class SensorContextAdaptor extends CommonSensorContext { private final org.sonar.api.batch.SensorContext sensorContext; private final MetricFinder metricFinder; private final Project project; private final ResourcePerspectives perspectives; - private final Settings settings; - private final FileSystem fs; - private final ActiveRules activeRules; - private final ComponentDataCache componentDataCache; - private final BlockCache blockCache; - private final DuplicationCache duplicationCache; public SensorContextAdaptor(org.sonar.api.batch.SensorContext sensorContext, MetricFinder metricFinder, Project project, ResourcePerspectives perspectives, Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache, BlockCache blockCache, DuplicationCache duplicationCache) { + super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache); this.sensorContext = sensorContext; this.metricFinder = metricFinder; this.project = project; this.perspectives = perspectives; - this.settings = settings; - this.fs = fs; - this.activeRules = activeRules; - this.componentDataCache = componentDataCache; - this.blockCache = blockCache; - this.duplicationCache = duplicationCache; - } - - @Override - public Settings settings() { - return settings; - } - - @Override - public FileSystem fileSystem() { - return fs; - } - - @Override - public ActiveRules activeRules() { - return activeRules; - } - - @Override - public <G extends Serializable> MeasureBuilder<G> measureBuilder() { - return new DefaultMeasureBuilder<G>(); } @Override @@ -143,7 +98,7 @@ public class SensorContextAdaptor implements SensorContext { return getMeasure(file, m); } - private Metric<?> findMetricOrFail(String metricKey) { + private Metric findMetricOrFail(String metricKey) { Metric<?> m = metricFinder.findByKey(metricKey); if (m == null) { throw new IllegalStateException("Unknow metric with key: " + metricKey); @@ -223,11 +178,6 @@ public class SensorContextAdaptor implements SensorContext { } @Override - public IssueBuilder issueBuilder() { - return new DefaultIssueBuilder(); - } - - @Override public boolean addIssue(Issue issue) { Resource r; InputPath inputPath = issue.inputPath(); @@ -259,53 +209,4 @@ public class SensorContextAdaptor implements SensorContext { .build(); } - @Override - public HighlightingBuilder highlightingBuilder(InputFile inputFile) { - return new DefaultHighlightingBuilder(((DefaultInputFile) inputFile).key(), componentDataCache); - } - - @Override - public SymbolTableBuilder symbolTableBuilder(InputFile inputFile) { - return new DefaultSymbolTableBuilder(((DefaultInputFile) inputFile).key(), componentDataCache); - } - - @Override - public DuplicationTokenBuilder duplicationTokenBuilder(InputFile inputFile) { - PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language())); - return new DefaultTokenBuilder(inputFile, blockCache, blockChunker); - } - - @Override - public DuplicationBuilder duplicationBuilder(InputFile inputFile) { - return new DefaultDuplicationBuilder(inputFile); - } - - @Override - public void saveDuplications(InputFile inputFile, List<DuplicationGroup> duplications) { - Preconditions.checkState(duplications.size() > 0, "Empty duplications"); - String effectiveKey = ((DefaultInputFile) inputFile).key(); - for (DuplicationGroup duplicationGroup : duplications) { - Preconditions.checkState(effectiveKey.equals(duplicationGroup.originBlock().resourceKey()), "Invalid duplication group"); - } - duplicationCache.put(effectiveKey, duplications); - } - - private int getBlockSize(String languageKey) { - int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines"); - if (blockSize == 0) { - blockSize = getDefaultBlockSize(languageKey); - } - return blockSize; - } - - private static int getDefaultBlockSize(String languageKey) { - if ("cobol".equals(languageKey)) { - return 30; - } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) { - return 20; - } else { - return 10; - } - } - } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/DeprecatedMetricFinder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/DeprecatedMetricFinder.java index 7242f61c8ad..761d0a74001 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/DeprecatedMetricFinder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/DeprecatedMetricFinder.java @@ -37,13 +37,12 @@ public final class DeprecatedMetricFinder implements MetricFinder { public DeprecatedMetricFinder(GlobalReferentials globalReferentials) { for (org.sonar.batch.protocol.input.Metric metric : globalReferentials.metrics()) { - Metric hibernateMetric = new org.sonar.api.measures.Metric.Builder(metric.key(), metric.key(), ValueType.valueOf(metric.valueType())) + Metric hibernateMetric = new org.sonar.api.measures.Metric.Builder(metric.key(), metric.name(), ValueType.valueOf(metric.valueType())) .create() .setDirection(metric.direction()) .setQualitative(metric.isQualitative()) .setUserManaged(metric.isUserManaged()) .setDescription(metric.description()) - .setName(metric.name()) .setOptimizedBestValue(metric.isOptimizedBestValue()) .setBestValue(metric.bestValue()) .setWorstValue(metric.worstValue()) diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/CommonSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/CommonSensorContext.java new file mode 100644 index 00000000000..6c3ed8949c4 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/CommonSensorContext.java @@ -0,0 +1,150 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.batch.scan2; + +import com.google.common.base.Preconditions; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.rule.ActiveRules; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.duplication.DuplicationBuilder; +import org.sonar.api.batch.sensor.duplication.DuplicationGroup; +import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder; +import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplicationBuilder; +import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder; +import org.sonar.api.batch.sensor.issue.IssueBuilder; +import org.sonar.api.batch.sensor.issue.internal.DefaultIssueBuilder; +import org.sonar.api.batch.sensor.measure.MeasureBuilder; +import org.sonar.api.batch.sensor.measure.internal.DefaultMeasureBuilder; +import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; +import org.sonar.api.config.Settings; +import org.sonar.batch.duplication.BlockCache; +import org.sonar.batch.duplication.DefaultTokenBuilder; +import org.sonar.batch.duplication.DuplicationCache; +import org.sonar.batch.highlighting.DefaultHighlightingBuilder; +import org.sonar.batch.index.ComponentDataCache; +import org.sonar.batch.scan.SensorContextAdaptor; +import org.sonar.batch.symbol.DefaultSymbolTableBuilder; +import org.sonar.duplications.internal.pmd.PmdBlockChunker; + +import java.io.Serializable; +import java.util.List; + +/** + * Common bits between {@link DefaultSensorContext} and {@link SensorContextAdaptor} + * @author julien + * + */ +public abstract class CommonSensorContext implements SensorContext { + + private final Settings settings; + private final FileSystem fs; + private final ActiveRules activeRules; + private final ComponentDataCache componentDataCache; + private final BlockCache blockCache; + private final DuplicationCache duplicationCache; + + protected CommonSensorContext(Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache, + BlockCache blockCache, DuplicationCache duplicationCache) { + this.settings = settings; + this.fs = fs; + this.activeRules = activeRules; + this.componentDataCache = componentDataCache; + this.blockCache = blockCache; + this.duplicationCache = duplicationCache; + } + + @Override + public Settings settings() { + return settings; + } + + @Override + public FileSystem fileSystem() { + return fs; + } + + @Override + public ActiveRules activeRules() { + return activeRules; + } + + @Override + public <G extends Serializable> MeasureBuilder<G> measureBuilder() { + return new DefaultMeasureBuilder<G>(); + } + + @Override + public IssueBuilder issueBuilder() { + return new DefaultIssueBuilder(); + } + + @Override + public HighlightingBuilder highlightingBuilder(InputFile inputFile) { + return new DefaultHighlightingBuilder(((DefaultInputFile) inputFile).key(), componentDataCache); + } + + @Override + public SymbolTableBuilder symbolTableBuilder(InputFile inputFile) { + return new DefaultSymbolTableBuilder(((DefaultInputFile) inputFile).key(), componentDataCache); + } + + @Override + public DuplicationTokenBuilder duplicationTokenBuilder(InputFile inputFile) { + PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language())); + + return new DefaultTokenBuilder(inputFile, blockCache, blockChunker); + } + + @Override + public DuplicationBuilder duplicationBuilder(InputFile inputFile) { + return new DefaultDuplicationBuilder(inputFile); + } + + @Override + public void saveDuplications(InputFile inputFile, List<DuplicationGroup> duplications) { + Preconditions.checkState(!duplications.isEmpty(), "Empty duplications"); + String effectiveKey = ((DefaultInputFile) inputFile).key(); + for (DuplicationGroup duplicationGroup : duplications) { + Preconditions.checkState(effectiveKey.equals(duplicationGroup.originBlock().resourceKey()), "Invalid duplication group"); + } + duplicationCache.put(effectiveKey, duplications); + } + + private int getBlockSize(String languageKey) { + int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines"); + if (blockSize == 0) { + blockSize = getDefaultBlockSize(languageKey); + } + return blockSize; + } + + private static int getDefaultBlockSize(String languageKey) { + if ("cobol".equals(languageKey)) { + return 30; + } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) { + return 20; + } else { + return 10; + } + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java index 74b13c2e43e..6350622c72f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java @@ -19,93 +19,46 @@ */ package org.sonar.batch.scan2; -import com.google.common.base.Preconditions; import com.google.common.base.Strings; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.measure.Metric; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.DefaultActiveRule; -import org.sonar.api.batch.sensor.SensorContext; -import org.sonar.api.batch.sensor.duplication.DuplicationBuilder; -import org.sonar.api.batch.sensor.duplication.DuplicationGroup; -import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplicationBuilder; -import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder; import org.sonar.api.batch.sensor.issue.Issue; -import org.sonar.api.batch.sensor.issue.IssueBuilder; import org.sonar.api.batch.sensor.issue.internal.DefaultIssue; -import org.sonar.api.batch.sensor.issue.internal.DefaultIssueBuilder; import org.sonar.api.batch.sensor.measure.Measure; -import org.sonar.api.batch.sensor.measure.MeasureBuilder; import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; -import org.sonar.api.batch.sensor.measure.internal.DefaultMeasureBuilder; -import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; import org.sonar.api.config.Settings; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.MessageException; import org.sonar.batch.duplication.BlockCache; -import org.sonar.batch.duplication.DefaultTokenBuilder; import org.sonar.batch.duplication.DuplicationCache; -import org.sonar.batch.highlighting.DefaultHighlightingBuilder; import org.sonar.batch.index.ComponentDataCache; import org.sonar.batch.issue.IssueFilters; import org.sonar.batch.scan.SensorContextAdaptor; -import org.sonar.batch.symbol.DefaultSymbolTableBuilder; import org.sonar.core.component.ComponentKeys; -import org.sonar.duplications.internal.pmd.PmdBlockChunker; import java.io.Serializable; -import java.util.List; -public class DefaultSensorContext implements SensorContext { +public class DefaultSensorContext extends CommonSensorContext { private final AnalyzerMeasureCache measureCache; private final AnalyzerIssueCache issueCache; private final ProjectDefinition def; - private final Settings settings; - private final FileSystem fs; private final ActiveRules activeRules; private final IssueFilters issueFilters; - private final ComponentDataCache componentDataCache; - private final BlockCache blockCache; - private final DuplicationCache duplicationCache; public DefaultSensorContext(ProjectDefinition def, AnalyzerMeasureCache measureCache, AnalyzerIssueCache issueCache, Settings settings, FileSystem fs, ActiveRules activeRules, IssueFilters issueFilters, ComponentDataCache componentDataCache, BlockCache blockCache, DuplicationCache duplicationCache) { + super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache); this.def = def; this.measureCache = measureCache; this.issueCache = issueCache; - this.settings = settings; - this.fs = fs; this.activeRules = activeRules; this.issueFilters = issueFilters; - this.componentDataCache = componentDataCache; - this.blockCache = blockCache; - this.duplicationCache = duplicationCache; - } - - @Override - public Settings settings() { - return settings; - } - - @Override - public FileSystem fileSystem() { - return fs; - } - - @Override - public ActiveRules activeRules() { - return activeRules; - } - - @Override - public <G extends Serializable> MeasureBuilder<G> measureBuilder() { - return new DefaultMeasureBuilder<G>(); } @Override @@ -139,11 +92,6 @@ public class DefaultSensorContext implements SensorContext { } @Override - public IssueBuilder issueBuilder() { - return new DefaultIssueBuilder(); - } - - @Override public boolean addIssue(Issue issue) { String resourceKey; if (issue.inputPath() != null) { @@ -181,54 +129,4 @@ public class DefaultSensorContext implements SensorContext { } } - @Override - public HighlightingBuilder highlightingBuilder(InputFile inputFile) { - return new DefaultHighlightingBuilder(((DefaultInputFile) inputFile).key(), componentDataCache); - } - - @Override - public SymbolTableBuilder symbolTableBuilder(InputFile inputFile) { - return new DefaultSymbolTableBuilder(((DefaultInputFile) inputFile).key(), componentDataCache); - } - - @Override - public DuplicationTokenBuilder duplicationTokenBuilder(InputFile inputFile) { - PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language())); - - return new DefaultTokenBuilder(inputFile, blockCache, blockChunker); - } - - @Override - public DuplicationBuilder duplicationBuilder(InputFile inputFile) { - return new DefaultDuplicationBuilder(inputFile); - } - - @Override - public void saveDuplications(InputFile inputFile, List<DuplicationGroup> duplications) { - Preconditions.checkState(duplications.size() > 0, "Empty duplications"); - String effectiveKey = ((DefaultInputFile) inputFile).key(); - for (DuplicationGroup duplicationGroup : duplications) { - Preconditions.checkState(effectiveKey.equals(duplicationGroup.originBlock().resourceKey()), "Invalid duplication group"); - } - duplicationCache.put(effectiveKey, duplications); - } - - private int getBlockSize(String languageKey) { - int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines"); - if (blockSize == 0) { - blockSize = getDefaultBlockSize(languageKey); - } - return blockSize; - } - - private static int getDefaultBlockSize(String languageKey) { - if ("cobol".equals(languageKey)) { - return 30; - } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) { - return 20; - } else { - return 10; - } - } - } diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/PmdBlockChunker.java b/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/PmdBlockChunker.java index b0ae419332a..c2e42cad0a1 100644 --- a/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/PmdBlockChunker.java +++ b/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/PmdBlockChunker.java @@ -51,7 +51,7 @@ public class PmdBlockChunker { /** * @return ArrayList as we need a serializable object */ - public ArrayList<Block> chunk(String resourceId, List<TokensLine> fragments) { + public List<Block> chunk(String resourceId, List<TokensLine> fragments) { List<TokensLine> filtered = Lists.newArrayList(); int i = 0; while (i < fragments.size()) { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/DuplicationGroup.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/DuplicationGroup.java index 28e1e7d2041..710ab81c652 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/DuplicationGroup.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/DuplicationGroup.java @@ -80,6 +80,14 @@ public class DuplicationGroup { } @Override + public int hashCode() { + return new HashCodeBuilder(13, 43) + .append(resourceKey) + .append(startLine) + .append(length).toHashCode(); + } + + @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE). append("resourceKey", resourceKey). diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java index fefbfb1e4c8..10c0c71f5be 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java @@ -31,6 +31,10 @@ import javax.annotation.Nullable; public class DefaultIssueBuilder implements IssueBuilder { + private static final String INPUT_DIR_SHOULD_BE_NON_NULL = "InputDir should be non null"; + private static final String INPUT_FILE_SHOULD_BE_NON_NULL = "InputFile should be non null"; + private static final String ON_FILE_OR_ON_DIR_ALREADY_CALLED = "onFile or onDir already called"; + private static final String ON_PROJECT_ALREADY_CALLED = "onProject already called"; String key; boolean onProject = false; InputPath path; @@ -48,26 +52,26 @@ public class DefaultIssueBuilder implements IssueBuilder { @Override public DefaultIssueBuilder onFile(InputFile file) { - Preconditions.checkState(!this.onProject, "onProject already called"); - Preconditions.checkState(this.path == null, "onFile or onDir already called"); - Preconditions.checkNotNull(file, "InputFile should be non null"); + Preconditions.checkState(!this.onProject, ON_PROJECT_ALREADY_CALLED); + Preconditions.checkState(this.path == null, ON_FILE_OR_ON_DIR_ALREADY_CALLED); + Preconditions.checkNotNull(file, INPUT_FILE_SHOULD_BE_NON_NULL); this.path = file; return this; } @Override public DefaultIssueBuilder onDir(InputDir dir) { - Preconditions.checkState(!this.onProject, "onProject already called"); - Preconditions.checkState(this.path == null, "onFile or onDir already called"); - Preconditions.checkNotNull(dir, "InputDir should be non null"); + Preconditions.checkState(!this.onProject, ON_PROJECT_ALREADY_CALLED); + Preconditions.checkState(this.path == null, ON_FILE_OR_ON_DIR_ALREADY_CALLED); + Preconditions.checkNotNull(dir, INPUT_DIR_SHOULD_BE_NON_NULL); this.path = dir; return this; } @Override public DefaultIssueBuilder onProject() { - Preconditions.checkState(!this.onProject, "onProject already called"); - Preconditions.checkState(this.path == null, "onFile or onDir already called"); + Preconditions.checkState(!this.onProject, ON_PROJECT_ALREADY_CALLED); + Preconditions.checkState(this.path == null, ON_FILE_OR_ON_DIR_ALREADY_CALLED); this.onProject = true; return this; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java index 5e16b420c2e..af8af470cd1 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java @@ -341,6 +341,7 @@ public class Metric<G extends Serializable> implements ServerExtension, BatchExt /** * @return the metric description */ + @CheckForNull public String getDescription() { return description; } @@ -351,7 +352,7 @@ public class Metric<G extends Serializable> implements ServerExtension, BatchExt * @param description the description * @return this */ - public Metric setDescription(String description) { + public Metric setDescription(@Nullable String description) { this.description = description; return this; } |