Skip to content

Commit

Permalink
Move Cobertura into the Scala-Plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
miklein committed Dec 18, 2014
1 parent bac5d30 commit 6319538
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 82 deletions.
7 changes: 0 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@

<scala.version>2.10.4</scala.version>
<scala.major.version>2.10</scala.major.version>

<cobertura.version>3.3.2</cobertura.version>

<sonar.language>scala</sonar.language>
</properties>
Expand All @@ -62,11 +60,6 @@
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.sonar.plugins</groupId>
<artifactId>sonar-cobertura-plugin</artifactId>
<version>${cobertura.version}</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-compiler</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,46 +27,55 @@
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
import org.sonar.plugins.cobertura.api.AbstractCoberturaParser;
import org.sonar.plugins.cobertura.api.CoberturaUtils;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.plugins.scala.language.Scala;

public class CoberturaSensor implements Sensor, CoverageExtension {
private static final Logger LOG = LoggerFactory.getLogger(CoberturaSensor.class);

private final FileSystem fileSystem;

private static final AbstractCoberturaParser COBERTURA_PARSER = new ScalaCoberturaParser();
private static final Logger LOG = LoggerFactory.getLogger(CoberturaSensor.class);

public static final String COBERTURA_REPORTS_PATH_PROPERTY ="sonar.cobertura.reportPath";
private FileSystem fileSystem;;
private PathResolver pathResolver;
private Settings settings;

public CoberturaSensor(FileSystem fileSystem) {
this.fileSystem = fileSystem;
}

public boolean shouldExecuteOnProject(Project project) {
if(fileSystem.languages().contains(Scala.KEY)){
LOG.info("CoberturaSensor will be executed");
return true;
} else {
LOG.info("CoberturaSensor will NOT be executed");
return false;
}
}

public void analyse(Project project, SensorContext context) {
File report = CoberturaUtils.getReport(project);
if (report != null) {
parseReport(report, context);
}
}

protected void parseReport(File xmlFile, final SensorContext context) {
LOG.info("parsing {}", xmlFile);
COBERTURA_PARSER.parseReport(xmlFile, context);
public CoberturaSensor(FileSystem fileSystem, PathResolver pathResolver, Settings settings) {
this.pathResolver = pathResolver;
this.settings = settings;
this.fileSystem = fileSystem;
}

public boolean shouldExecuteOnProject(Project project) {
if(fileSystem.languages().contains(Scala.KEY)){
LOG.info("CoberturaSensor will be executed");
return true;
} else {
LOG.info("CoberturaSensor will NOT be executed");
return false;
}
}

@Override
public String toString() {
return "Scala CoberturaSensor";
public void analyse(Project project, SensorContext context) {
String path = settings.getString(COBERTURA_REPORTS_PATH_PROPERTY);
File report = pathResolver.relativeFile(fileSystem.baseDir(), path);
if (!report.isFile()) {
LOG.warn("Cobertura report not found at {}", report);
return;
}
parseReport(report, context);
}

protected void parseReport(File xmlFile, SensorContext context) {
LOG.info("parsing {}", xmlFile);
ScalaCoberturaReportParser.parseReport(xmlFile, context, fileSystem);
}

@Override
public String toString() {
return "Scala CoberturaSensor";
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Sonar Scala Plugin
* Copyright (C) 2011 - 2014 All contributors
* [email protected]
*
* 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 02
*/
package org.sonar.plugins.scala.cobertura;

import static java.util.Locale.ENGLISH;
import static org.sonar.api.utils.ParsingUtils.parseNumber;

import java.io.File;
import java.text.ParseException;
import java.util.Map;

import javax.xml.stream.XMLStreamException;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.measures.CoverageMeasuresBuilder;
import org.sonar.api.measures.Measure;
import org.sonar.api.utils.StaxParser;
import org.sonar.api.utils.XmlParserException;

import com.google.common.collect.Maps;

public class ScalaCoberturaReportParser {

private static final Logger LOG = LoggerFactory.getLogger(ScalaCoberturaReportParser.class);
private final SensorContext context;
private FileSystem fileSystem;

private ScalaCoberturaReportParser(SensorContext context, FileSystem fileSystem) {
this.context = context;
this.fileSystem = fileSystem;
}

/**
* Parse a Cobertura xml report and create measures accordingly
* @param fileSystem
*/
public static void parseReport(File xmlFile, SensorContext context, FileSystem fileSystem) {
new ScalaCoberturaReportParser(context, fileSystem).parse(xmlFile);
}

private void parse(File xmlFile) {
try {
StaxParser parser = new StaxParser(new StaxParser.XmlStreamHandler() {

public void stream(SMHierarchicCursor rootCursor) throws XMLStreamException {
rootCursor.advance();
collectPackageMeasures(rootCursor.descendantElementCursor("package"));
}
});
parser.parse(xmlFile);
} catch (XMLStreamException e) {
throw new XmlParserException(e);
}
}

private void collectPackageMeasures(SMInputCursor pack) throws XMLStreamException {
while (pack.getNext() != null) {
Map<String, CoverageMeasuresBuilder> builderByFilename = Maps.newHashMap();
collectFileMeasures(pack.descendantElementCursor("class"), builderByFilename);
for (Map.Entry<String, CoverageMeasuresBuilder> entry : builderByFilename.entrySet()) {
String className = sanitizeFilename(entry.getKey());
String filename = className.replace('.', '/') + ".scala";
FilePredicates filePredicates = fileSystem.predicates();
InputFile resource = fileSystem.inputFile(filePredicates.matchesPathPattern("**/*" + filename));
if (resource != null){
for (Measure measure : entry.getValue().createMeasures()) {
context.saveMeasure(resource, measure);
}
}else{
LOG.warn("Resource not found: {}", entry.getKey());
}
}
}
}

// private boolean resourceExists(Resource file) {
// return context.getResource(file) != null;
// }

private void collectFileMeasures(SMInputCursor clazz, Map<String, CoverageMeasuresBuilder> builderByFilename) throws XMLStreamException {
while (clazz.getNext() != null) {
String fileName = clazz.getAttrValue("filename");
CoverageMeasuresBuilder builder = builderByFilename.get(fileName);
if (builder == null) {
builder = CoverageMeasuresBuilder.create();
builderByFilename.put(fileName, builder);
}
collectFileData(clazz, builder);
}
}

private void collectFileData(SMInputCursor clazz, CoverageMeasuresBuilder builder) throws XMLStreamException {
SMInputCursor line = clazz.childElementCursor("lines").advance().childElementCursor("line");
while (line.getNext() != null) {
int lineId = Integer.parseInt(line.getAttrValue("number"));
try {
builder.setHits(lineId, (int) parseNumber(line.getAttrValue("hits"), ENGLISH));
} catch (ParseException e) {
throw new XmlParserException(e);
}

String isBranch = line.getAttrValue("branch");
String text = line.getAttrValue("condition-coverage");
if (StringUtils.equals(isBranch, "true") && StringUtils.isNotBlank(text)) {
String[] conditions = StringUtils.split(StringUtils.substringBetween(text, "(", ")"), "/");
builder.setConditions(lineId, Integer.parseInt(conditions[1]), Integer.parseInt(conditions[0]));
}
}
}

private static String sanitizeFilename(String s) {
String fileName = FilenameUtils.removeExtension(s);
fileName = fileName.replace('/', '.').replace('\\', '.');
return fileName;
}

}

0 comments on commit 6319538

Please sign in to comment.