/** Create issue report according to issue list generated during SonarQube analysis. */ public static SonarQubeIssuesReport extractIssueReport( ProjectIssues projectIssues, InputFileCache inputFileCache, File projectBaseDir) { SonarQubeIssuesReport result = new SonarQubeIssuesReport(); for (Issue issue : projectIssues.issues()) { if (!issue.isNew()) { LOGGER.debug("Issue {} is not a new issue and so, not added to the report", issue.key()); } else { String key = issue.key(); String severity = issue.severity(); String rule = issue.ruleKey().toString(); String message = issue.message(); int line = 0; if (issue.line() != null) { line = issue.line(); } InputFile inputFile = inputFileCache.getInputFile(issue.componentKey()); if (inputFile == null) { LOGGER.debug("Issue {} is not linked to a file, not added to the report", issue.key()); } else { String path = new PathResolver().relativePath(projectBaseDir, inputFile.file()); // Create the issue and Add to report SonarQubeIssue stashIssue = new SonarQubeIssue(key, severity, message, rule, path, line); result.add(stashIssue); } } } return result; }
/** * Check if the xml file starts with a prolog "<?xml version="1.0" ?>" if so, check if there * is any characters prefixing it. */ private void checkForCharactersBeforeProlog(FileSystem fileSystem) { try { int lineNb = 1; Pattern firstTagPattern = Pattern.compile("<[a-zA-Z?]+"); boolean hasBOM = false; for (String line : Files.readLines(inputFile.file(), fileSystem.encoding())) { if (lineNb == 1 && line.startsWith(BOM_CHAR)) { hasBOM = true; characterDeltaForHighlight = -1; } Matcher m = firstTagPattern.matcher(line); if (m.find()) { int column = line.indexOf(m.group()); if (XML_PROLOG_START_TAG.equals(m.group()) && !isFileBeginning(lineNb, column, hasBOM)) { hasCharsBeforeProlog = true; } break; } lineNb++; } if (hasCharsBeforeProlog) { processCharBeforePrologInFile(fileSystem, lineNb); } } catch (IOException e) { LOG.warn("Unable to analyse file {}", inputFile.absolutePath(), e); } }
@VisibleForTesting protected void analyseFiles( SensorContext context, List<TreeVisitor> treeVisitors, Iterable<InputFile> inputFiles, ProgressReport progressReport) { boolean success = false; try { for (InputFile inputFile : inputFiles) { // check for cancellation of the analysis (by SonarQube or SonarLint). See SONARJS-761. if (context.getSonarQubeVersion().isGreaterThanOrEqual(V6_0) && context.isCancelled()) { throw new CancellationException( "Analysis interrupted because the SensorContext is in cancelled state"); } if (!isExcluded(inputFile.file())) { analyse(context, inputFile, treeVisitors); } progressReport.nextFile(); } success = true; } catch (CancellationException e) { // do not propagate the exception LOG.debug(e.toString()); } finally { stopProgressReport(progressReport, success); } }
public void finish() { progressReport.stop(count + "/" + total + " files analyzed"); if (!allFilesToBlame.isEmpty()) { LOG.warn("Missing blame information for the following files:"); for (InputFile f : allFilesToBlame) { LOG.warn(" * " + f.absolutePath()); } LOG.warn("This may lead to missing/broken features in SonarQube"); } }
private static void validateLine(BlameLine line, int lineId, InputFile file) { Preconditions.checkArgument( StringUtils.isNotBlank(line.revision()), "Blame revision is blank for file %s at line %s", file.relativePath(), lineId); Preconditions.checkArgument( line.date() != null, "Blame date is null for file %s at line %s", file.relativePath(), lineId); }
private static void validateMaxLine(Map<Integer, Integer> m, InputFile inputFile) { int maxLine = inputFile.lines(); for (int l : m.keySet()) { if (l > maxLine) { throw new IllegalStateException( String.format( "Can't create measure for line %d for file '%s' with %d lines", l, inputFile.absolutePath(), maxLine)); } } }
private long getDevelopmentCost(DecoratorContext context) { InputFile file = fs.inputFile(fs.predicates().hasRelativePath(context.getResource().getKey())); if (file != null) { String language = file.language(); return getMeasureValue(context, sqaleRatingSettings.getSizeMetric(language, metrics)) * sqaleRatingSettings.getDevCost(language); } else { Collection<Measure> childrenMeasures = context.getChildrenMeasures(CoreMetrics.DEVELOPMENT_COST); Double sum = sum(childrenMeasures); return sum.longValue(); } }
private void scanFile( SensorContext sensorContext, InputFile inputFile, List<TreeVisitor> visitors, ScriptTree scriptTree) { JavaScriptVisitorContext context = new JavaScriptVisitorContext(scriptTree, inputFile.file(), sensorContext.settings()); highlightSymbols(sensorContext.newSymbolTable().onFile(inputFile), context); List<Issue> fileIssues = new ArrayList<>(); for (TreeVisitor visitor : visitors) { if (visitor instanceof CharsetAwareVisitor) { ((CharsetAwareVisitor) visitor).setCharset(fileSystem.encoding()); } if (visitor instanceof JavaScriptCheck) { fileIssues.addAll(((JavaScriptCheck) visitor).scanFile(context)); } else { visitor.scanTree(context); } } saveFileIssues(sensorContext, fileIssues, inputFile); }
@Test public void should_register_tests() throws URISyntaxException { SensorContextTester context = SensorContextTester.create(new File("")); MutableTestCase testCase = mock(MutableTestCase.class); when(testCase.setDurationInMs(anyLong())).thenReturn(testCase); when(testCase.setStatus(any(TestCase.Status.class))).thenReturn(testCase); when(testCase.setMessage(anyString())).thenReturn(testCase); when(testCase.setStackTrace(anyString())).thenReturn(testCase); when(testCase.setType(anyString())).thenReturn(testCase); MutableTestPlan testPlan = mock(MutableTestPlan.class); when(testPlan.addTestCase(anyString())).thenReturn(testCase); when(perspectives.as( eq(MutableTestPlan.class), argThat( new ArgumentMatcher<InputFile>() { @Override public boolean matches(Object o) { if (o instanceof InputFile) { return ":ch.hortis.sonar.mvn.mc.MetricsCollectorRegistryTest" .equals(((InputFile) o).key()); } return false; } }))) .thenReturn(testPlan); parser.collect(context, getDir("multipleReports"), true); verify(testPlan).addTestCase("testGetUnKnownCollector"); verify(testPlan).addTestCase("testGetJDependsCollector"); }
private void analyse( SensorContext sensorContext, InputFile inputFile, List<TreeVisitor> visitors) { ScriptTree scriptTree; try { scriptTree = (ScriptTree) parser.parse(new java.io.File(inputFile.absolutePath())); scanFile(sensorContext, inputFile, visitors, scriptTree); } catch (RecognitionException e) { checkInterrupted(e); LOG.error("Unable to parse file: " + inputFile.absolutePath()); LOG.error(e.getMessage()); processRecognitionException(e, sensorContext, inputFile); } catch (Exception e) { checkInterrupted(e); processException(e, sensorContext, inputFile); throw new AnalysisException("Unable to analyse file: " + inputFile.absolutePath(), e); } }
public void validate(Measure<?> measure, InputFile inputFile) { Metric<?> metric = measure.getMetric(); if (!isLineMetrics(metric)) { return; } Map<Integer, Integer> m = KeyValueFormat.parseIntInt(measure.getData()); validatePositiveLine(m, inputFile.absolutePath()); validateMaxLine(m, inputFile); }
@Override public boolean accept(InputFile inputFile) { if (filters.length > 0) { DeprecatedContext context = new DeprecatedContext(inputFile); for (FileSystemFilter filter : filters) { if (!filter.accept(inputFile.file(), context)) { return false; } } } return true; }
@Override public MutableTestCase setCoverageBlock(InputFile mainFile, List<Integer> lines) { Preconditions.checkArgument( mainFile.type() == Type.MAIN, "Test file can only cover a main file"); DefaultInputFile coveredFile = (DefaultInputFile) mainFile; if (coverageBlocksByTestedFile.containsKey(coveredFile)) { throw new CoverageAlreadyExistsException( "The link between " + name() + " and " + coveredFile.key() + " already exists"); } coverageBlocksByTestedFile.put(coveredFile, new DefaultCoverageBlock(this, coveredFile, lines)); return this; }
@Override public synchronized void blameResult(InputFile file, List<BlameLine> lines) { Preconditions.checkNotNull(file); Preconditions.checkNotNull(lines); Preconditions.checkArgument( allFilesToBlame.contains(file), "It was not expected to blame file %s", file.relativePath()); if (lines.size() != file.lines()) { LOG.debug( "Ignoring blame result since provider returned {} blame lines but file {} has {} lines", lines.size(), file.relativePath(), file.lines()); return; } BatchComponent batchComponent = componentCache.get(file); Builder scmBuilder = BatchReport.Changesets.newBuilder(); scmBuilder.setComponentRef(batchComponent.batchId()); Map<String, Integer> changesetsIdByRevision = new HashMap<>(); int lineId = 1; for (BlameLine line : lines) { validateLine(line, lineId, file); Integer changesetId = changesetsIdByRevision.get(line.revision()); if (changesetId == null) { addChangeset(scmBuilder, line); changesetId = scmBuilder.getChangesetCount() - 1; changesetsIdByRevision.put(line.revision(), changesetId); } scmBuilder.addChangesetIndexByLine(changesetId); lineId++; } writer.writeComponentChangesets(scmBuilder.build()); allFilesToBlame.remove(file); count++; progressReport.message(count + "/" + total + " files analyzed"); }
private static void saveLineIssue( SensorContext sensorContext, InputFile inputFile, RuleKey ruleKey, LineIssue issue) { NewIssue newIssue = sensorContext.newIssue(); NewIssueLocation primaryLocation = newIssue .newLocation() .message(issue.message()) .on(inputFile) .at(inputFile.selectLine(issue.line())); saveIssue(newIssue, primaryLocation, ruleKey, issue); }
/** * Create a temporary file without any character before the prolog and update the following * attributes in order to correctly report issues: * * <ul> * <li>lineDeltaForIssue * <li>file */ private void processCharBeforePrologInFile(FileSystem fileSystem, int lineDelta) { try { String content = Files.toString(inputFile.file(), fileSystem.encoding()); File tempFile = new File(fileSystem.workDir(), inputFile.file().getName()); int index = content.indexOf(XML_PROLOG_START_TAG); Files.write(content.substring(index), tempFile, fileSystem.encoding()); noCharBeforePrologFile = tempFile; if (index != -1) { characterDeltaForHighlight += index; } if (lineDelta > 1) { lineDeltaForIssue = lineDelta - 1; } } catch (IOException e) { LOG.warn("Unable to analyse file {}", inputFile.absolutePath(), e); } }
private void processRecognitionException( RecognitionException e, SensorContext sensorContext, InputFile inputFile) { if (parsingErrorRuleKey != null) { NewIssue newIssue = sensorContext.newIssue(); NewIssueLocation primaryLocation = newIssue .newLocation() .message(e.getMessage()) .on(inputFile) .at(inputFile.selectLine(e.getLine())); newIssue.forRule(parsingErrorRuleKey).at(primaryLocation).save(); } if (sensorContext.getSonarQubeVersion().isGreaterThanOrEqual(V6_0)) { sensorContext .newAnalysisError() .onFile(inputFile) .at(inputFile.newPointer(e.getLine(), 0)) .message(e.getMessage()) .save(); } }
private static NewIssueLocation newLocation( InputFile inputFile, NewIssue issue, IssueLocation location) { TextRange range = inputFile.newRange( location.startLine(), location.startLineOffset(), location.endLine(), location.endLineOffset()); NewIssueLocation newLocation = issue.newLocation().on(inputFile).at(range); if (location.message() != null) { newLocation.message(location.message()); } return newLocation; }
@Override public void visitToken(Token token) { if (!token.isGeneratedCode()) { String text; if (ignoreIdentifiers && token.getType().equals(GenericTokenType.IDENTIFIER)) { text = "_I"; } else if (ignoreLiterals && token.getType().equals(CxxTokenType.NUMBER)) { text = "_N"; } else if (ignoreLiterals && token.getType().equals(CxxTokenType.STRING)) { text = "_S"; } else if (ignoreLiterals && token.getType().equals(CxxTokenType.CHARACTER)) { text = "_C"; } else if (token.getType().equals(GenericTokenType.EOF)) { return; } else { text = token.getValue(); } try { TextRange range = inputFile.newRange( token.getLine(), token.getColumn(), token.getLine(), token.getColumn() + token.getValue().length()); cpdTokens.addToken(range, text); } catch (Exception e) { // ignore range errors: parsing errors could lead to wrong location data LOG.debug( "CPD error in file '{}' at line:{}, column:{}", getContext().getFile().getAbsoluteFile(), token.getLine(), token.getColumn()); } } }
public String getFilePath() { return inputFile.absolutePath(); }
@Override public FileType type() { String type = inputFile.type().name(); return FileType.valueOf(type); }
@Override public String relativePath() { return inputFile.relativePath(); }
@Override public String canonicalPath() { return inputFile.absolutePath(); }
public File getIOFile() { return noCharBeforePrologFile != null ? noCharBeforePrologFile : inputFile.file(); }
@Override public boolean apply(InputFile f) { return type == f.type(); }