diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2016-07-08 15:59:54 +0200 |
---|---|---|
committer | Duarte Meneses <duarte.meneses@sonarsource.com> | 2016-07-11 10:53:30 +0200 |
commit | ae5a68d2050ec017ca30b9e770e3ce0a5beae806 (patch) | |
tree | 4dc2feb31a5fd10cb00d17f4eafd432534178abe /sonar-plugin-api/src | |
parent | be5552b150a28447800c588202a0cf78694bf3e3 (diff) | |
download | sonarqube-ae5a68d2050ec017ca30b9e770e3ce0a5beae806.tar.gz sonarqube-ae5a68d2050ec017ca30b9e770e3ce0a5beae806.zip |
SONAR-7876 Add an API for Sensors to report files that can't be analyzed
Diffstat (limited to 'sonar-plugin-api/src')
11 files changed, 365 insertions, 1 deletions
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 22319fb4613..c2852681f60 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 @@ -26,6 +26,7 @@ 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.error.NewAnalysisError; import org.sonar.api.batch.sensor.highlighting.NewHighlighting; import org.sonar.api.batch.sensor.internal.SensorContextTester; import org.sonar.api.batch.sensor.issue.Issue; @@ -127,4 +128,10 @@ public interface SensorContext { */ NewCpdTokens newCpdTokens(); + /** + * Builder to declare errors that happened while processing a source file. + * Don't forget to call {@link NewAnalisisError#save()}. + * @since 6.0 + */ + NewAnalysisError newAnalysisError(); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/AnalysisError.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/AnalysisError.java new file mode 100644 index 00000000000..4bacf8cf29d --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/AnalysisError.java @@ -0,0 +1,50 @@ +/* + * 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.error; + +import javax.annotation.CheckForNull; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.TextPointer; +import org.sonar.api.batch.sensor.Sensor; + +/** + * Represents an analysis error, such as a parsing error, reported by a {@link Sensor}. + * + * @since 6.0 + */ +public interface AnalysisError { + /** + * The file that was being processed when the error occurred. + */ + InputFile inputFile(); + + /** + * A description of the error. + */ + @CheckForNull + String message(); + + /** + * Location of the error. + */ + @CheckForNull + TextPointer location(); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/NewAnalysisError.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/NewAnalysisError.java new file mode 100644 index 00000000000..b6a7419ffde --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/NewAnalysisError.java @@ -0,0 +1,53 @@ +/* + * 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.error; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.TextPointer; +import org.sonar.api.batch.sensor.Sensor; + +/** + * Represents an analysis error, such as a parsing error, that occurs during the execution of a {@link Sensor}. + * Multiple analysis errors might be reported for the same file and issues may be created for a file which also has analysis errors reported. + * The handling of such situations is unspecified and might vary depending on the implementation. + * + * @since 6.0 + */ +public interface NewAnalysisError { + /** + * The file that was being processed when the error occurred. This field must be set before saving the error. + */ + NewAnalysisError onFile(InputFile inputFile); + + /** + * Message about the error. This field is optional. + */ + NewAnalysisError message(String message); + + /** + * Location of this error. This field is optional. + */ + NewAnalysisError at(TextPointer location); + + /** + * Save this error information. + */ + void save(); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisError.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisError.java new file mode 100644 index 00000000000..04a6548714a --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisError.java @@ -0,0 +1,86 @@ +/* + * 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.error.internal; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.TextPointer; +import org.sonar.api.batch.sensor.error.AnalysisError; +import org.sonar.api.batch.sensor.error.NewAnalysisError; +import org.sonar.api.batch.sensor.internal.DefaultStorable; +import org.sonar.api.batch.sensor.internal.SensorStorage; + +import com.google.common.base.Preconditions; + +public class DefaultAnalysisError extends DefaultStorable implements NewAnalysisError, AnalysisError { + private InputFile inputFile; + private String message; + private TextPointer location; + + public DefaultAnalysisError() { + super(null); + } + + public DefaultAnalysisError(SensorStorage storage) { + super(storage); + } + + @Override + public InputFile inputFile() { + return inputFile; + } + + @Override + public String message() { + return message; + } + + @Override + public TextPointer location() { + return location; + } + + @Override + public NewAnalysisError onFile(InputFile inputFile) { + Preconditions.checkArgument(inputFile != null, "Cannot use a inputFile that is null"); + Preconditions.checkState(this.inputFile == null, "onFile() already called"); + this.inputFile = inputFile; + return this; + } + + @Override + public NewAnalysisError message(String message) { + this.message = message; + return this; + } + + @Override + public NewAnalysisError at(TextPointer location) { + Preconditions.checkState(this.location == null, "at() already called"); + this.location = location; + return this; + } + + @Override + protected void doSave() { + Preconditions.checkNotNull(this.inputFile, "inputFile is mandatory on AnalysisError"); + storage.store(this); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/internal/package-info.java new file mode 100644 index 00000000000..fbd5d4aabf1 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/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.error.internal; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/package-info.java new file mode 100644 index 00000000000..b253a6bf1af --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/error/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.error; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java index 53a1364604b..5a79149cbc3 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java @@ -28,6 +28,7 @@ import java.util.Map; import org.sonar.api.batch.sensor.coverage.CoverageType; import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens; +import org.sonar.api.batch.sensor.error.AnalysisError; 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; @@ -39,6 +40,7 @@ class InMemorySensorStorage implements SensorStorage { Table<String, String, Measure> measuresByComponentAndMetric = HashBasedTable.create(); Collection<Issue> allIssues = new ArrayList<>(); + Collection<AnalysisError> allAnalysisErrors = new ArrayList<>(); Map<String, DefaultHighlighting> highlightingByComponent = new HashMap<>(); Map<String, DefaultCpdTokens> cpdTokensByComponent = new HashMap<>(); @@ -101,4 +103,9 @@ class InMemorySensorStorage implements SensorStorage { symbolsPerComponent.put(fileKey, symbolTable); } + @Override + public void store(AnalysisError analysisError) { + allAnalysisErrors.add(analysisError); + } + } 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 53a66952c17..1b274aaecf8 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 @@ -47,6 +47,9 @@ 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.error.AnalysisError; +import org.sonar.api.batch.sensor.error.NewAnalysisError; +import org.sonar.api.batch.sensor.error.internal.DefaultAnalysisError; 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; @@ -192,6 +195,10 @@ public class SensorContextTester implements SensorContext { public Collection<Issue> allIssues() { return sensorStorage.allIssues; } + + public Collection<AnalysisError> allAnalysisErrors() { + return sensorStorage.allAnalysisErrors; + } @CheckForNull public Integer lineHits(String fileKey, CoverageType type, int line) { @@ -245,6 +252,11 @@ public class SensorContextTester implements SensorContext { public NewSymbolTable newSymbolTable() { return new DefaultSymbolTable(sensorStorage); } + + @Override + public NewAnalysisError newAnalysisError() { + return new DefaultAnalysisError(sensorStorage); + } /** * Return list of syntax highlighting applied for a given position in a file. The result is a list because in theory you 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 a0be68cbc24..9f61766afec 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 @@ -22,6 +22,7 @@ package org.sonar.api.batch.sensor.internal; import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens; +import org.sonar.api.batch.sensor.error.AnalysisError; 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; @@ -54,5 +55,9 @@ public interface SensorStorage { * @since 5.6 */ void store(DefaultSymbolTable symbolTable); - + + /** + * @since 6.0 + */ + void store(AnalysisError analysisError); } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisErrorTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisErrorTest.java new file mode 100644 index 00000000000..3b9f62a4856 --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisErrorTest.java @@ -0,0 +1,78 @@ +/* + * 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.error.internal; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.TextPointer; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.fs.internal.DefaultTextPointer; +import org.sonar.api.batch.sensor.internal.SensorStorage; +import static org.assertj.core.api.Assertions.assertThat; + +public class DefaultAnalysisErrorTest { + private InputFile inputFile; + private SensorStorage storage; + private TextPointer textPointer; + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Before + public void setUp() { + inputFile = new DefaultInputFile("module1", "src/File.java"); + textPointer = new DefaultTextPointer(5, 2); + storage = mock(SensorStorage.class); + } + + @Test + public void test_analysis_error() { + DefaultAnalysisError analysisError = new DefaultAnalysisError(storage); + analysisError.onFile(inputFile) + .at(textPointer) + .message("msg"); + + assertThat(analysisError.location()).isEqualTo(textPointer); + assertThat(analysisError.message()).isEqualTo("msg"); + assertThat(analysisError.inputFile()).isEqualTo(inputFile); + } + + @Test + public void test_save() { + DefaultAnalysisError analysisError = new DefaultAnalysisError(storage); + analysisError.onFile(inputFile).save(); + + verify(storage).store(analysisError); + verifyNoMoreInteractions(storage); + } + + @Test + public void test_must_have_file() { + exception.expect(NullPointerException.class); + new DefaultAnalysisError(storage).save(); + } +} 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 712e1eb0500..46fe16802a1 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 @@ -26,14 +26,18 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; +import org.sonar.api.batch.fs.internal.DefaultTextPointer; import org.sonar.api.batch.fs.internal.FileMetadata; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; import org.sonar.api.batch.sensor.coverage.CoverageType; import org.sonar.api.batch.sensor.coverage.NewCoverage; +import org.sonar.api.batch.sensor.error.AnalysisError; +import org.sonar.api.batch.sensor.error.NewAnalysisError; import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.issue.NewIssue; import org.sonar.api.batch.sensor.symbol.NewSymbolTable; @@ -101,6 +105,26 @@ public class SensorContextTesterTest { } @Test + public void testAnalysisErrors() { + assertThat(tester.allAnalysisErrors()).isEmpty(); + NewAnalysisError newAnalysisError = tester.newAnalysisError(); + + InputFile file = new DefaultInputFile("foo", "src/Foo.java"); + newAnalysisError.onFile(file) + .message("error") + .at(new DefaultTextPointer(5, 2)) + .save(); + + assertThat(tester.allAnalysisErrors()).hasSize(1); + AnalysisError analysisError = tester.allAnalysisErrors().iterator().next(); + + assertThat(analysisError.inputFile()).isEqualTo(file); + assertThat(analysisError.message()).isEqualTo("error"); + assertThat(analysisError.location()).isEqualTo(new DefaultTextPointer(5, 2)); + + } + + @Test public void testMeasures() { assertThat(tester.measures("foo:src/Foo.java")).isEmpty(); assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNull(); |