@@ -32,6 +32,7 @@ import org.sonar.xoo.lang.SymbolReferencesSensor; | |||
import org.sonar.xoo.lang.SyntaxHighlightingSensor; | |||
import org.sonar.xoo.lang.XooCpdMapping; | |||
import org.sonar.xoo.lang.XooTokenizer; | |||
import org.sonar.xoo.rule.AnalysisErrorSensor; | |||
import org.sonar.xoo.rule.ChecksSensor; | |||
import org.sonar.xoo.rule.CreateIssueByInternalKeySensor; | |||
import org.sonar.xoo.rule.CustomMessageSensor; | |||
@@ -118,6 +119,9 @@ public class XooPlugin implements Plugin { | |||
ItCoverageSensor.class, | |||
OverallCoverageSensor.class, | |||
// Analysis errors | |||
AnalysisErrorSensor.class, | |||
// Tests | |||
TestExecutionSensor.class, | |||
CoveragePerTestSensor.class, |
@@ -0,0 +1,95 @@ | |||
/* | |||
* 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.xoo.rule; | |||
import java.io.IOException; | |||
import java.nio.file.Files; | |||
import java.nio.file.Path; | |||
import java.util.List; | |||
import org.apache.commons.lang.StringUtils; | |||
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.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.xoo.Xoo; | |||
public class AnalysisErrorSensor implements Sensor { | |||
private static final Logger LOG = Loggers.get(AnalysisErrorSensor.class); | |||
private static final String ERROR_EXTENSION = ".error"; | |||
@Override | |||
public void describe(SensorDescriptor descriptor) { | |||
descriptor | |||
.name("Xoo Analysis Error Sensor") | |||
.onlyOnLanguages(Xoo.KEY); | |||
} | |||
@Override | |||
public void execute(SensorContext context) { | |||
for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) { | |||
processFileError(file, context); | |||
} | |||
} | |||
private void processFileError(InputFile inputFile, SensorContext context) { | |||
Path ioFile = inputFile.file().toPath(); | |||
Path errorFile = ioFile.resolveSibling(ioFile.getFileName() + ERROR_EXTENSION).toAbsolutePath(); | |||
if (Files.exists(errorFile) && Files.isRegularFile(errorFile)) { | |||
LOG.debug("Processing " + errorFile.toString()); | |||
try { | |||
List<String> lines = Files.readAllLines(errorFile, context.fileSystem().encoding()); | |||
for (String line : lines) { | |||
if (StringUtils.isBlank(line) || line.startsWith("#")) { | |||
continue; | |||
} | |||
processLine(line, inputFile, context); | |||
} | |||
} catch (IOException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
} | |||
private void processLine(String fileLine, InputFile inputFile, SensorContext context) { | |||
String[] textPointer = fileLine.split(","); | |||
if (textPointer.length != 3) { | |||
throw new IllegalStateException("Invalid format in error file"); | |||
} | |||
try { | |||
int line = Integer.parseInt(textPointer[0]); | |||
int lineOffset = Integer.parseInt(textPointer[1]); | |||
String msg = textPointer[2]; | |||
context.newAnalysisError() | |||
.onFile(inputFile) | |||
.at(inputFile.newPointer(line, lineOffset)) | |||
.message(msg) | |||
.save(); | |||
} catch (NumberFormatException e) { | |||
throw new IllegalStateException("Invalid format in error file", e); | |||
} | |||
} | |||
} |
@@ -35,10 +35,10 @@ public class XooPluginTest { | |||
public void provide_extensions_for_5_5() { | |||
Plugin.Context context = new Plugin.Context(new SonarRuntime(Version.parse("5.5"), SonarProduct.SONARQUBE, SonarQubeSide.SCANNER)); | |||
new XooPlugin().define(context); | |||
assertThat(context.getExtensions()).hasSize(41).contains(CpdTokenizerSensor.class); | |||
assertThat(context.getExtensions()).hasSize(42).contains(CpdTokenizerSensor.class); | |||
context = new Plugin.Context(new SonarRuntime(Version.parse("5.4"), SonarProduct.SONARLINT, null)); | |||
new XooPlugin().define(context); | |||
assertThat(context.getExtensions()).hasSize(40).doesNotContain(CpdTokenizerSensor.class); | |||
assertThat(context.getExtensions()).hasSize(41).doesNotContain(CpdTokenizerSensor.class); | |||
} | |||
} |
@@ -0,0 +1,79 @@ | |||
/* | |||
* 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.xoo.rule; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
import java.nio.file.Files; | |||
import java.nio.file.Path; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import static org.assertj.core.api.Assertions.*; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultTextPointer; | |||
import org.sonar.api.batch.sensor.error.AnalysisError; | |||
import org.sonar.api.batch.sensor.internal.SensorContextTester; | |||
public class AnalysisErrorSensorTest { | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
private AnalysisErrorSensor sensor; | |||
private SensorContextTester context; | |||
@Before | |||
public void setUp() { | |||
sensor = new AnalysisErrorSensor(); | |||
} | |||
private void createErrorFile(Path baseDir) throws IOException { | |||
Path srcDir = baseDir.resolve("src"); | |||
Files.createDirectories(srcDir); | |||
Path errorFile = srcDir.resolve("foo.xoo.error"); | |||
List<String> errors = new ArrayList<>(); | |||
errors.add("1,4,my error"); | |||
Files.write(errorFile, errors, StandardCharsets.UTF_8); | |||
} | |||
@Test | |||
public void test() throws IOException { | |||
Path baseDir = temp.newFolder().toPath().toAbsolutePath(); | |||
createErrorFile(baseDir); | |||
DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setLanguage("xoo"); | |||
context = SensorContextTester.create(baseDir); | |||
context.fileSystem().add(inputFile); | |||
sensor.execute(context); | |||
assertThat(context.allAnalysisErrors()).hasSize(1); | |||
AnalysisError error = context.allAnalysisErrors().iterator().next(); | |||
assertThat(error.inputFile()).isEqualTo(inputFile); | |||
assertThat(error.location()).isEqualTo(new DefaultTextPointer(1, 4)); | |||
assertThat(error.message()).isEqualTo("my error"); | |||
} | |||
} |
@@ -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(); | |||
} |
@@ -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(); | |||
} |
@@ -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(); | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; |
@@ -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; |
@@ -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); | |||
} | |||
} |
@@ -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 |
@@ -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); | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
@@ -100,6 +104,26 @@ public class SensorContextTesterTest { | |||
assertThat(tester.allIssues()).hasSize(2); | |||
} | |||
@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(); |
@@ -31,6 +31,7 @@ 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.NewAnalysisError; | |||
import org.sonar.api.batch.sensor.highlighting.NewHighlighting; | |||
import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting; | |||
import org.sonar.api.batch.sensor.internal.SensorStorage; | |||
@@ -42,6 +43,7 @@ import org.sonar.api.batch.sensor.symbol.NewSymbolTable; | |||
import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.api.utils.Version; | |||
import org.sonar.scanner.sensor.noop.NoOpNewAnalysisError; | |||
import org.sonar.scanner.sensor.noop.NoOpNewCpdTokens; | |||
import org.sonar.scanner.sensor.noop.NoOpNewHighlighting; | |||
import org.sonar.scanner.sensor.noop.NoOpNewSymbolTable; | |||
@@ -51,6 +53,7 @@ public class DefaultSensorContext implements SensorContext { | |||
private static final NoOpNewHighlighting NO_OP_NEW_HIGHLIGHTING = new NoOpNewHighlighting(); | |||
private static final NoOpNewSymbolTable NO_OP_NEW_SYMBOL_TABLE = new NoOpNewSymbolTable(); | |||
private static final NoOpNewCpdTokens NO_OP_NEW_CPD_TOKENS = new NoOpNewCpdTokens(); | |||
private static final NoOpNewAnalysisError NO_OP_NEW_ANALYSIS_ERROR = new NoOpNewAnalysisError(); | |||
private final Settings settings; | |||
private final FileSystem fs; | |||
@@ -145,4 +148,9 @@ public class DefaultSensorContext implements SensorContext { | |||
return new DefaultCpdTokens(settings, sensorStorage); | |||
} | |||
@Override | |||
public NewAnalysisError newAnalysisError() { | |||
return NO_OP_NEW_ANALYSIS_ERROR; | |||
} | |||
} |
@@ -37,6 +37,7 @@ import org.sonar.api.batch.measure.MetricFinder; | |||
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.highlighting.internal.SyntaxHighlightingRule; | |||
import org.sonar.api.batch.sensor.internal.SensorStorage; | |||
@@ -288,4 +289,9 @@ public class DefaultSensorStorage implements SensorStorage { | |||
return blockSize; | |||
} | |||
@Override | |||
public void store(AnalysisError analysisError) { | |||
// no op | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
/* | |||
* 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.scanner.sensor.noop; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.TextPointer; | |||
import org.sonar.api.batch.sensor.error.NewAnalysisError; | |||
public class NoOpNewAnalysisError implements NewAnalysisError { | |||
@Override | |||
public NewAnalysisError onFile(InputFile inputFile) { | |||
// no op | |||
return this; | |||
} | |||
@Override | |||
public NewAnalysisError message(String message) { | |||
// no op | |||
return this; | |||
} | |||
@Override | |||
public NewAnalysisError at(TextPointer location) { | |||
// no op | |||
return this; | |||
} | |||
@Override | |||
public void save() { | |||
// no op | |||
} | |||
} |