-
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.
feat(base): Add base plugin to build on
Base plugin adds a scala language, plugin and sensor. Base metrics consist of Non-comments lines of codes count and comment lines count. It is meant as a skeleton to build on.
- Loading branch information
Augustin Borsu
committed
Apr 30, 2016
1 parent
8598589
commit e085c25
Showing
8 changed files
with
536 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 |
---|---|---|
@@ -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,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()) | ||
|
||
} | ||
} | ||
} | ||
|
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,7 @@ | ||
class ScalaFile1 { | ||
val value = "value" | ||
|
||
def function: Unit = { | ||
println("function called.") | ||
} | ||
} |
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 @@ | ||
// Expected Header Comment | ||
|
||
class ScalaFile2 { | ||
val value = "value" | ||
|
||
def function: Unit = { | ||
println("function called.") | ||
} | ||
} |
Oops, something went wrong.