-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from Sagacify/staging
Bootstrap project
- Loading branch information
Showing
15 changed files
with
600 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,41 @@ | ||
# sonar-scala | ||
Sonarqube plugin for scala analysis | ||
|
||
# Set-up | ||
Intended for sonarqube 5.4 | ||
|
||
Download the latest relase into your sonar extentions/downloads folder. | ||
Restart sonarqube either using the update center or manually. | ||
|
||
# Build from source | ||
```mvn package``` | ||
|
||
# Test | ||
``` | ||
mvn test | ||
sonar-runner -D sonar.projectKey=Sagacify:sonar-scala | ||
``` | ||
|
||
# Info | ||
This plugin is not an evolution from the legacy sonar-scala-plugin of which versions can be found laying around such as [1and1/sonar-scala](https://github.com/1and1/sonar-scala). | ||
The previous plugin used the scala compiler to create its metrics which had the disadvantage of requiring a specific plugin per scala version. | ||
Instead, we are using the [scala-ide/scalariform](https://github.com/scala-ide/scalariform) library to parse the source code in a version independent way. | ||
|
||
# TODO | ||
* Add property to sepcify scala version (currently defaults to 2.11.8) | ||
* Integrate scalastyle | ||
* Integrate coverage metrics | ||
* Integrate scalawarts | ||
... | ||
|
||
# Credits | ||
Many existing projects have been used as inspiration. | ||
Here is a list of the main ones. | ||
|
||
[1and1/sonar-scala](https://github.com/1and1/sonar-scala) | ||
|
||
[SonarSource/sonar-java](https://github.com/SonarSource/sonar-java) | ||
|
||
[SonarSource/sonar-examples](https://github.com/SonarSource/sonar-examples) | ||
|
||
[NCR-CoDE/sonar-scalastyle](https://github.com/NCR-CoDE/sonar-scalastyle) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Launch the build of the docker image | ||
dependencies: | ||
override: | ||
- mvn dependency:resolve | ||
|
||
# Launch the test into the docker image | ||
test: | ||
override: | ||
- mvn test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.sonarsource.parent</groupId> | ||
<artifactId>parent</artifactId> | ||
<version>31</version> | ||
</parent> | ||
|
||
<artifactId>sonar-scala-plugin</artifactId> | ||
<packaging>sonar-plugin</packaging> | ||
<version>0.0.1-SNAPSHOT</version> | ||
|
||
<name>Sonar Scala Plugin</name> | ||
<description>Enables analysis of Scala projects into Sonar.</description> | ||
<url>http://github.com/sagacify/sonar-scala</url> | ||
<inceptionYear>2016</inceptionYear> | ||
|
||
<licenses> | ||
<license> | ||
<name>GNU LGPL 3</name> | ||
<url>http://www.gnu.org/licenses/lgpl.txt</url> | ||
<distribution>repo</distribution> | ||
</license> | ||
</licenses> | ||
|
||
<organization> | ||
<name>Sagacify</name> | ||
<url>https://www.sagacify.com</url> | ||
</organization> | ||
|
||
<developers> | ||
<developer> | ||
<id>aborsu</id> | ||
<name>Augustin Borsu</name> | ||
<email>[email protected]</email> | ||
<url>http://www.acelpb.com/</url> | ||
</developer> | ||
</developers> | ||
|
||
<scm> | ||
<connection>scm:git:[email protected]:sagacify/sonar-scala.git</connection> | ||
<developerConnection>scm:git:[email protected]:sagacify/sonar-scala.git</developerConnection> | ||
<url>https://github.com/sagacify/sonar-scala</url> | ||
<tag>HEAD</tag> | ||
</scm> | ||
|
||
<issueManagement> | ||
<url>https://github.com/sagacify/sonar-scala/issues</url> | ||
</issueManagement> | ||
|
||
<properties> | ||
<sonar.version>5.4</sonar.version> | ||
<sonar.pluginKey>scala</sonar.pluginKey> | ||
<sonar.pluginName>Scala</sonar.pluginName> | ||
<sonar.pluginClass>com.sagacify.sonar.scala.ScalaPlugin</sonar.pluginClass> | ||
|
||
<scala.version>2.11.8</scala.version> | ||
<scala.major.version>2.11</scala.major.version> | ||
|
||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.sonarsource.sonarqube</groupId> | ||
<artifactId>sonar-plugin-api</artifactId> | ||
<version>${sonar.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.scala-lang</groupId> | ||
<artifactId>scala-library</artifactId> | ||
<version>${scala.version}</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.scalariform</groupId> | ||
<artifactId>scalariform_${scala.major.version}</artifactId> | ||
<version>0.1.8</version> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>org.scala-lang</groupId> | ||
<artifactId>scala-library</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-api</artifactId> | ||
<version>1.6.2</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
|
||
<!-- unit tests --> | ||
<dependency> | ||
<groupId>org.scalatest</groupId> | ||
<artifactId>scalatest_${scala.major.version}</artifactId> | ||
<version>2.2.6</version> | ||
<scope>test</scope> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>org.scala-lang</groupId> | ||
<artifactId>scala-library</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.sonarsource.sonarqube</groupId> | ||
<artifactId>sonar-testing-harness</artifactId> | ||
<version>${sonar.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<!-- disable surefire --> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-surefire-plugin</artifactId> | ||
<configuration> | ||
<skipTests>true</skipTests> | ||
</configuration> | ||
</plugin> | ||
<!-- enable scalatest --> | ||
<plugin> | ||
<groupId>org.scalatest</groupId> | ||
<artifactId>scalatest-maven-plugin</artifactId> | ||
<version>1.0</version> | ||
<configuration> | ||
<reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory> | ||
<junitxml>.</junitxml> | ||
<filereports>WDF TestSuite.txt</filereports> | ||
</configuration> | ||
<executions> | ||
<execution> | ||
<id>test</id> | ||
<goals> | ||
<goal>test</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<!-- enable scala-maven --> | ||
<plugin> | ||
<groupId>net.alchim31.maven</groupId> | ||
<artifactId>scala-maven-plugin</artifactId> | ||
<version>3.2.2</version> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>compile</goal> | ||
<goal>testCompile</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
project | ||
target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
sbt.version=0.13.8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import sbt._ | ||
object MyBuild extends com.typesafe.sbt.pom.PomBuild |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
addSbtPlugin("com.typesafe.sbt" % "sbt-pom-reader" % "2.0.0") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Required metadata | ||
sonar.projectName=Sonar Scala Plugin | ||
sonar.projectVersion=0.0.1 | ||
|
||
# Comma-separated paths to directories with sources (required) | ||
sonar.sources=src | ||
sonar.exclusions=src/test/resources/**, | ||
|
||
# Encoding of the source files | ||
sonar.sourceEncoding=UTF-8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package com.sagacify.sonar.scala | ||
|
||
import scala.annotation.tailrec | ||
|
||
import scalariform.lexer.ScalaLexer | ||
import scalariform.lexer.Token | ||
import scalariform.lexer.Tokens.LINE_COMMENT | ||
import scalariform.lexer.Tokens.MULTILINE_COMMENT | ||
import scalariform.lexer.Tokens.XML_COMMENT | ||
import scalariform.lexer.Tokens.WS | ||
import scalariform.lexer.Tokens.EOF | ||
|
||
object Measures { | ||
|
||
/* applied on raw source code */ | ||
|
||
/* applied on lines of code */ | ||
|
||
/* applied on tokenised code */ | ||
|
||
@tailrec | ||
final def count_comment_lines(tokens: List[Token], i: Int = 0): Int = { | ||
tokens match { | ||
case Nil => i | ||
case token :: tail if token.tokenType.isComment => { | ||
token.tokenType match { | ||
case LINE_COMMENT => | ||
count_comment_lines(tail, i + 1) | ||
case MULTILINE_COMMENT => | ||
count_comment_lines(tail, i + token.rawText.count(_ == '\n') + 1) | ||
case XML_COMMENT => | ||
new scala.NotImplementedError("XML ?!"); i | ||
} | ||
} | ||
case _ :: tail => count_comment_lines(tail, i) | ||
} | ||
} | ||
|
||
@tailrec | ||
final def count_ncloc(tokens: List[Token], i: Int = 0): Int = { | ||
|
||
@tailrec | ||
def get_next_line(tokens: List[Token]): List[Token] = { | ||
tokens match { | ||
case Nil => Nil | ||
case token :: tail if token.tokenType == WS && | ||
token.text.contains('\n') => tail | ||
case token :: tail if token.tokenType == LINE_COMMENT => tail | ||
case token :: tail => get_next_line(tail) | ||
} | ||
} | ||
|
||
tokens match { | ||
case Nil => i | ||
case token :: tail if token.tokenType == WS => count_ncloc(tail, i) | ||
case token :: tail if token.tokenType == EOF => i | ||
case token :: tail => | ||
if( !token.tokenType.isNewline & !token.tokenType.isComment) { | ||
count_ncloc(get_next_line(tail), i + 1) | ||
} else { | ||
count_ncloc(tail, i) | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.sagacify.sonar.scala | ||
|
||
import scala.collection.JavaConversions._ | ||
import scala.collection.mutable.ListBuffer | ||
|
||
import org.sonar.api.config.Settings | ||
import org.sonar.api.Extension | ||
import org.sonar.api.resources.AbstractLanguage | ||
import org.sonar.api.SonarPlugin | ||
import scalariform.lexer.ScalaLexer | ||
import scalariform.lexer.Token | ||
|
||
/** | ||
* Defines Scala as a language for SonarQube. | ||
*/ | ||
class Scala(s: Settings) extends AbstractLanguage("scala", "Scala") { | ||
|
||
override def getFileSuffixes: Array[String] = Array("scala") | ||
|
||
} | ||
|
||
object Scala { | ||
|
||
def tokenize(sourceCode: String, scalaVersion: String): List[Token] = | ||
ScalaLexer.createRawLexer(sourceCode, false, scalaVersion).toList | ||
|
||
} | ||
|
||
/** | ||
* Plugin entry point. | ||
*/ | ||
class ScalaPlugin extends SonarPlugin { | ||
|
||
override def getExtensions: java.util.List[Class[_]] = | ||
ListBuffer[Class[_]] ( | ||
classOf[Scala], | ||
classOf[ScalaSensor] | ||
) | ||
|
||
override val toString = getClass.getSimpleName | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.sagacify.sonar.scala | ||
|
||
import scala.io.Source | ||
import scala.collection.JavaConversions._ | ||
|
||
import org.sonar.api.batch.fs.FileSystem | ||
import org.sonar.api.batch.Sensor | ||
import org.sonar.api.batch.SensorContext | ||
import org.sonar.api.measures.{CoreMetrics => CM} | ||
import org.sonar.api.resources.Project | ||
|
||
|
||
class ScalaSensor(scala: Scala, fs: FileSystem) extends Sensor { | ||
|
||
def shouldExecuteOnProject(project: Project): Boolean = { | ||
return fs.hasFiles(fs.predicates().hasLanguage(scala.getKey())); | ||
} | ||
|
||
def analyse(project: Project, context: SensorContext): Unit = { | ||
|
||
val charset = fs.encoding().toString() | ||
val version = "2.11.8" | ||
|
||
val inputFiles = fs.inputFiles(fs.predicates().hasLanguage(scala.getKey())) | ||
|
||
inputFiles.foreach{ inputFile => | ||
context.saveMeasure(inputFile, CM.FILES, 1.0); | ||
|
||
val sourceCode = Source.fromFile(inputFile.file, charset).mkString | ||
val tokens = Scala.tokenize(sourceCode, version) | ||
|
||
context.saveMeasure(inputFile, | ||
CM.COMMENT_LINES, | ||
Measures.count_comment_lines(tokens)) | ||
context.saveMeasure(inputFile, | ||
CM.NCLOC, | ||
Measures.count_ncloc(tokens)) | ||
|
||
// context.saveMeasure(input, CM.CLASSES, classes) | ||
// context.saveMeasure(input, CM.FUNCTIONS, methods) | ||
// context.saveMeasure(input, CM.ACCESSORS, accessors) | ||
// context.saveMeasure(input, CM.COMPLEXITY_IN_FUNCTIONS, complexityInMethods) | ||
// context.saveMeasure(input, CM.COMPLEXITY_IN_CLASSES, fileComplexity) | ||
// context.saveMeasure(input, CM.COMPLEXITY, fileComplexity) | ||
// context.saveMeasure(input, CM.PUBLIC_API, publicApiChecker.getPublicApi()) | ||
// context.saveMeasure(input, CM.PUBLIC_DOCUMENTED_API_DENSITY, publicApiChecker.getDocumentedPublicApiDensity()) | ||
// context.saveMeasure(input, CM.PUBLIC_UNDOCUMENTED_API, publicApiChecker.getUndocumentedPublicApi()) | ||
|
||
} | ||
} | ||
} | ||
|
Oops, something went wrong.