From 9cf13638be2e9d4a257183378a948554644079d5 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Mon, 14 Mar 2016 17:57:48 +0100 Subject: SONAR-7389 Add new Sensor API to provide duplication tokens --- .../org/sonar/api/batch/sensor/SensorContext.java | 16 ++-- .../sonar/api/batch/sensor/SensorDescriptor.java | 5 -- .../sonar/api/batch/sensor/cpd/NewCpdTokens.java | 49 +++++++++++ .../sensor/cpd/internal/DefaultCpdTokens.java | 96 ++++++++++++++++++++++ .../batch/sensor/cpd/internal/package-info.java | 21 +++++ .../sonar/api/batch/sensor/cpd/package-info.java | 21 +++++ .../sensor/internal/DefaultSensorDescriptor.java | 11 --- .../batch/sensor/internal/SensorContextTester.java | 20 +++-- .../api/batch/sensor/internal/SensorStorage.java | 6 ++ .../internal/DefaultSensorDescriptorTest.java | 9 -- .../sensor/internal/SensorContextTesterTest.java | 7 -- 11 files changed, 216 insertions(+), 45 deletions(-) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/NewCpdTokens.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/package-info.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/package-info.java (limited to 'sonar-plugin-api') diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java index 228dab0a51c..3d49859470e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java @@ -21,11 +21,11 @@ package org.sonar.api.batch.sensor; import com.google.common.annotations.Beta; import java.io.Serializable; -import org.sonar.api.batch.AnalysisMode; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.sensor.coverage.NewCoverage; +import org.sonar.api.batch.sensor.cpd.NewCpdTokens; import org.sonar.api.batch.sensor.highlighting.NewHighlighting; import org.sonar.api.batch.sensor.internal.SensorContextTester; import org.sonar.api.batch.sensor.issue.Issue; @@ -57,11 +57,6 @@ public interface SensorContext { */ ActiveRules activeRules(); - /** - * Get analysis mode. - */ - AnalysisMode analysisMode(); - /** * @since 5.5 */ @@ -100,4 +95,13 @@ public interface SensorContext { */ NewCoverage newCoverage(); + // ------------ CPD ------------ + + /** + * Builder to define CPD tokens in a file. + * Don't forget to call {@link NewCpdTokens#save()}. + * @since 5.5 + */ + NewCpdTokens newCpdTokens(); + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorDescriptor.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorDescriptor.java index b1eb1294661..9000a81432b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorDescriptor.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorDescriptor.java @@ -81,9 +81,4 @@ public interface SensorDescriptor { */ SensorDescriptor requireProperties(String... propertyKeys); - /** - * Should this sensor be disabled in issues mode. Default is to run all sensors in issues mode. - */ - SensorDescriptor disabledInIssues(); - } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/NewCpdTokens.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/NewCpdTokens.java new file mode 100644 index 00000000000..e2a48d1a724 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/NewCpdTokens.java @@ -0,0 +1,49 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.cpd; + +import com.google.common.annotations.Beta; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.TextRange; + +/** + * This builder is used to define tokens used by CPD algorithm on files. + * @since 5.5 + */ +@Beta +public interface NewCpdTokens { + + /** + * The tokenized file. + */ + NewCpdTokens onFile(InputFile inputFile); + + /** + * Call this method to register a token in a range. Tokens should be registered in order. + * @param range Token position. Use {@link InputFile#newRange(int, int, int, int)} to get a valid range. + * @param image Text content of the token. Can be replaced by a constant placeholder for some tokens (like litterals). + */ + NewCpdTokens addToken(TextRange range, String image); + + /** + * Call this method only once when your are done with defining tokens of the file. + */ + void save(); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java new file mode 100644 index 00000000000..47a62b82399 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java @@ -0,0 +1,96 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.batch.sensor.cpd.internal; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.TextRange; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.cpd.NewCpdTokens; +import org.sonar.api.batch.sensor.internal.DefaultStorable; +import org.sonar.api.batch.sensor.internal.SensorStorage; +import org.sonar.duplications.internal.pmd.TokensLine; + +public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens { + + private final ImmutableList.Builder result = ImmutableList.builder(); + private DefaultInputFile inputFile; + private int startLine = Integer.MIN_VALUE; + private int startIndex = 0; + private int currentIndex = 0; + private StringBuilder sb = new StringBuilder(); + private TextRange lastRange; + + public DefaultCpdTokens(SensorStorage storage) { + super(storage); + } + + @Override + public DefaultCpdTokens onFile(InputFile inputFile) { + Preconditions.checkNotNull(inputFile, "file can't be null"); + this.inputFile = (DefaultInputFile) inputFile; + return this; + } + + public InputFile inputFile() { + return inputFile; + } + + @Override + public NewCpdTokens addToken(TextRange range, String image) { + Preconditions.checkNotNull(range, "Range should not be null"); + Preconditions.checkState(inputFile != null, "Call onFile() first"); + Preconditions.checkState(lastRange == null || lastRange.end().compareTo(range.start()) >= 0, + "Tokens of file %s should be provided in order. \nPrevious token: %s\nLast token: %s", inputFile, lastRange, range); + + String value = image; + + int line = range.start().line(); + if (line != startLine) { + addNewTokensLine(result, startIndex, currentIndex, startLine, sb); + startIndex = currentIndex + 1; + startLine = line; + } + currentIndex++; + sb.append(value); + + return this; + } + + public List getTokenLines() { + return result.build(); + } + + private static void addNewTokensLine(ImmutableList.Builder result, int startUnit, int endUnit, int startLine, StringBuilder sb) { + if (sb.length() != 0) { + result.add(new TokensLine(startUnit, endUnit, startLine, sb.toString())); + sb.setLength(0); + } + } + + @Override + protected void doSave() { + Preconditions.checkState(inputFile != null, "Call onFile() first"); + addNewTokensLine(result, startIndex, currentIndex, startLine, sb); + storage.store(this); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/package-info.java new file mode 100644 index 00000000000..0e670a393ce --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.api.batch.sensor.cpd.internal; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/package-info.java new file mode 100644 index 00000000000..5e53aa27647 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/package-info.java @@ -0,0 +1,21 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.api.batch.sensor.cpd; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptor.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptor.java index ddf836c0f33..985ca6832c6 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptor.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptor.java @@ -32,7 +32,6 @@ public class DefaultSensorDescriptor implements SensorDescriptor { private InputFile.Type type = null; private String[] ruleRepositories = new String[0]; private String[] properties = new String[0]; - private boolean disabledInIssues = false; public String name() { return name; @@ -55,10 +54,6 @@ public class DefaultSensorDescriptor implements SensorDescriptor { return Arrays.asList(properties); } - public boolean isDisabledInIssues() { - return disabledInIssues; - } - @Override public DefaultSensorDescriptor name(String name) { this.name = name; @@ -104,10 +99,4 @@ public class DefaultSensorDescriptor implements SensorDescriptor { return this; } - @Override - public DefaultSensorDescriptor disabledInIssues() { - this.disabledInIssues = true; - return this; - } - } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java index d5bb9d21ea1..46301c089ec 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java @@ -44,6 +44,8 @@ import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.coverage.CoverageType; import org.sonar.api.batch.sensor.coverage.NewCoverage; import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; +import org.sonar.api.batch.sensor.cpd.NewCpdTokens; +import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens; import org.sonar.api.batch.sensor.highlighting.NewHighlighting; import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting; @@ -71,7 +73,6 @@ public class SensorContextTester implements SensorContext { private Settings settings; private DefaultFileSystem fs; private ActiveRules activeRules; - private MockAnalysisMode analysisMode; private InMemorySensorStorage sensorStorage; private InputModule module; @@ -79,7 +80,6 @@ public class SensorContextTester implements SensorContext { this.settings = new Settings(); this.fs = new DefaultFileSystem(moduleBaseDir); this.activeRules = new ActiveRulesBuilder().build(); - this.analysisMode = new MockAnalysisMode(); this.sensorStorage = new InMemorySensorStorage(); this.module = new DefaultInputModule("projectKey"); } @@ -115,11 +115,6 @@ public class SensorContextTester implements SensorContext { this.activeRules = activeRules; } - @Override - public MockAnalysisMode analysisMode() { - return analysisMode; - } - @Override public InputModule module() { return module; @@ -197,6 +192,11 @@ public class SensorContextTester implements SensorContext { return new DefaultCoverage(sensorStorage); } + @Override + public NewCpdTokens newCpdTokens() { + return new DefaultCpdTokens(sensorStorage); + } + public List highlightingTypeAt(String componentKey, int line, int lineOffset) { DefaultHighlighting syntaxHighlightingData = sensorStorage.highlightingByComponent.get(componentKey); if (syntaxHighlightingData == null) { @@ -247,6 +247,7 @@ public class SensorContextTester implements SensorContext { private Collection allIssues = new ArrayList<>(); private Map highlightingByComponent = new HashMap<>(); + private Map cpdTokensByComponent = new HashMap<>(); private Map> coverageByComponent = new HashMap<>(); @Override @@ -273,6 +274,11 @@ public class SensorContextTester implements SensorContext { coverageByComponent.get(key).put(defaultCoverage.type(), defaultCoverage); } + @Override + public void store(DefaultCpdTokens defaultCpdTokens) { + cpdTokensByComponent.put(defaultCpdTokens.inputFile().key(), defaultCpdTokens); + } + } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java index 2e1bd88c825..031ee725728 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java @@ -21,6 +21,7 @@ package org.sonar.api.batch.sensor.internal; import org.sonar.api.batch.BatchSide; import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; +import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens; import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting; import org.sonar.api.batch.sensor.issue.Issue; import org.sonar.api.batch.sensor.measure.Measure; @@ -43,4 +44,9 @@ public interface SensorStorage { */ void store(DefaultCoverage defaultCoverage); + /** + * @since 5.5 + */ + void store(DefaultCpdTokens defaultCpdTokens); + } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptorTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptorTest.java index 05481b0aae5..7ade972164b 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptorTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptorTest.java @@ -43,13 +43,4 @@ public class DefaultSensorDescriptorTest { assertThat(descriptor.ruleRepositories()).containsOnly("squid-java"); } - @Test - public void disabledAnalysisModes() { - DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor(); - descriptor - .disabledInIssues(); - - assertThat(descriptor.isDisabledInIssues()).isTrue(); - } - } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java index c8a70a0630b..4e70a3e293b 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java @@ -81,13 +81,6 @@ public class SensorContextTesterTest { assertThat(tester.fileSystem().baseDir()).isNotEqualTo(baseDir); } - @Test - public void testAnalysisMode() { - assertThat(tester.analysisMode().isPreview()).isFalse(); - tester.analysisMode().setPreview(true); - assertThat(tester.analysisMode().isPreview()).isTrue(); - } - @Test public void testIssues() { assertThat(tester.allIssues()).isEmpty(); -- cgit v1.2.3