Permalink
Browse files

first commit

  • Loading branch information...
0 parents commit 7bed5eac68983ef85b0fbf4f90252d3d5d246636 @y-yoshinoya y-yoshinoya committed Jul 3, 2012
@@ -0,0 +1,6 @@
+target/
+project/target
+project/project/target
+*.class
+*.swp
+*.jar
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec java -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -Xss2M -XX:MaxPermSize=512m -Xmx1G -Dfile.encoding=UTF-8 -jar `dirname $0`/sbt-launch.jar "$@"
@@ -0,0 +1,3 @@
+set SCRIPT_DIR=%~dp0
+set JAVA_TOOL_OPTIONS='-Dfile.encoding=UTF8'
+java -XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled -Xss2M -XX:MaxPermSize=256m -Xmx512M -jar "%SCRIPT_DIR%sbt-launch.jar" %*
@@ -0,0 +1,21 @@
+sbtPlugin := true
+
+scalaVersion := "2.9.1"
+
+scalacOptions := Seq("-deprecation", "-unchecked")
+
+organization := "com.github.aselab"
+
+name := "scalastyle-sbt-plugin"
+
+version := "0.1-SNAPSHOT"
+
+libraryDependencies ++= Seq(
+ "org.scalastyle" %% "scalastyle" % "0.1.0-SNAPSHOT",
+ "org.specs2" %% "specs2" % "1.11" % "test"
+)
+
+resolvers ++= Seq(
+ "Sonatype Nexus Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
+)
+
@@ -0,0 +1,117 @@
+<scalastyle>
+ <name>Scalastyle standard configuration</name>
+ <check level="warning" class="org.scalastyle.file.FileTabChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.file.FileLengthChecker" enabled="true">
+ <parameters>
+ <parameter name="maxFileLength"><![CDATA[800]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.file.HeaderMatchesChecker" enabled="true">
+ <parameters>
+ <parameter name="header"><![CDATA[// Copyright (C) 2011-2012 the original author or authors.
+// See the LICENCE.txt file distributed with this work for additional
+// information regarding copyright ownership.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.SpacesAfterPlusChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.file.WhitespaceEndOfLineChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.SpacesBeforePlusChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.file.FileLineLengthChecker" enabled="true">
+ <parameters>
+ <parameter name="maxLineLength"><![CDATA[160]]></parameter>
+ <parameter name="tabSize"><![CDATA[4]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.ClassNamesChecker" enabled="true">
+ <parameters>
+ <parameter name="regex"><![CDATA[[A-Z][A-Za-z]*]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.ObjectNamesChecker" enabled="true">
+ <parameters>
+ <parameter name="regex"><![CDATA[[A-Z][A-Za-z]*]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.PackageObjectNamesChecker" enabled="true">
+ <parameters>
+ <parameter name="regex"><![CDATA[^[a-z][A-Za-z]*$]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.EqualsHashCodeChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.IllegalImportsChecker" enabled="true">
+ <parameters>
+ <parameter name="illegalImports"><![CDATA[sun._,java.awt._]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.ParameterNumberChecker" enabled="true">
+ <parameters>
+ <parameter name="maxParameters"><![CDATA[8]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.MagicNumberChecker" enabled="true">
+ <parameters>
+ <parameter name="ignore"><![CDATA[-1,0,1,2,3]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.NoWhitespaceBeforeLeftBracketChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.NoWhitespaceAfterLeftBracketChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.ReturnChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.NullChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.NoCloneChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.NoFinalizeChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.CovariantEqualsChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.StructuralTypeChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.file.RegexChecker" enabled="true">
+ <parameters>
+ <parameter name="regex"><![CDATA[println]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.NumberOfTypesChecker" enabled="true">
+ <parameters>
+ <parameter name="maxTypes"><![CDATA[30]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.CyclomaticComplexityChecker" enabled="true">
+ <parameters>
+ <parameter name="maximum"><![CDATA[10]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.UppercaseLChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.SimplifyBooleanExpressionChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.scalariform.IfBraceChecker" enabled="true">
+ <parameters>
+ <parameter name="singleLineAllowed"><![CDATA[true]]></parameter>
+ <parameter name="doubleLineAllowed"><![CDATA[false]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.MethodLengthChecker" enabled="true">
+ <parameters>
+ <parameter name="maxLength"><![CDATA[50]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.MethodNamesChecker" enabled="true">
+ <parameters>
+ <parameter name="regex"><![CDATA[^[a-z][A-Za-z0-9]*$]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.NumberOfMethodsInTypeChecker" enabled="true">
+ <parameters>
+ <parameter name="maxMethods"><![CDATA[30]]></parameter>
+ </parameters>
+ </check>
+ <check level="warning" class="org.scalastyle.scalariform.PublicMethodsHaveTypeChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.file.NewLineAtEofChecker" enabled="true"></check>
+ <check level="warning" class="org.scalastyle.file.NoNewLineAtEofChecker" enabled="false"></check>
+</scalastyle>
@@ -0,0 +1,46 @@
+package com.github.aselab.scalastyle
+
+import sbt._
+import Keys._
+
+object ScalaStylePlugin extends Plugin {
+ import PluginKeys._
+
+ val Settings = Seq(
+ scalaStyle <<= Tasks.scalaStyle,
+ generateConfig <<= Tasks.generateConfig,
+ scalaStyleTarget := file("target/scalastyle-result.xml"),
+ // TODO: to configuration file(HOCON format).
+ config := file("scalastyle-config.xml")
+ )
+}
+
+object PluginKeys {
+ lazy val scalaStyle = InputKey[Unit]("scalastyle")
+ lazy val scalaStyleTarget = SettingKey[File]("scalastyle-target")
+ lazy val config = SettingKey[File]("scalastyle-config")
+ lazy val generateConfig = InputKey[Unit]("scalastyle-generate-config")
+}
+
+object Tasks {
+ import PluginKeys._
+
+ val scalaStyle: Project.Initialize[sbt.InputTask[Unit]] = inputTask {
+ (_, config, scalaSource in Compile, scalaStyleTarget, streams) map { case (args, config, sourceDir, target, streams) =>
+ val logger = streams.log
+ if (config.exists) {
+ IO.write(target, ScalaStyle(config, sourceDir).toCheckStyleFormat)
+ logger.success("created: %s".format(target))
+ } else {
+ logger.error("not exists: %s".format(config))
+ }
+ }
+ }
+
+ val generateConfig: Project.Initialize[sbt.InputTask[Unit]] = inputTask {
+ (_, config, streams) map { case (args, to, streams) =>
+ IOUtil.copyJarResourses(getClass.getResource("/scalastyle-config.xml"), to.absolutePath, streams.log)
+ }
+ }
+}
+
@@ -0,0 +1,49 @@
+package com.github.aselab.scalastyle
+
+import sbt._
+
+case class ScalaStyle(errors: List[ScalaStyle.Alert]) {
+ def toCheckStyleFormat =
+ """<?xml version="1.0" encoding="UTF-8"?>
+ """ + <checkstyle version="5.0">{
+ errors.groupBy(_.file.absolutePath).map { case (k, v) =>
+ <file name={k}>{
+ v.map { e =>
+ e.column.map { column =>
+ <error line={e.line.toString} column={column.toString}
+ severity={e.warnLevel} message={e.message} source="org.scalastyle.Main"/>
+ }.getOrElse {
+ <error line={e.line.toString} severity={e.warnLevel}
+ message={e.message} source="org.scalastyle.Main"/>
+ }
+ }
+ }</file>
+ }
+ }</checkstyle>.toString
+}
+
+object ScalaStyle {
+ import org.scalastyle.Main.main
+
+ def apply(config: File, sourceDir: File): ScalaStyle = ScalaStyle(
+ SecurityUtil.notExit {
+ main(Array("-c", config.absolutePath, sourceDir.absolutePath))
+ }.split("\n").toList.flatMap(Alert(_))
+ )
+
+ case class Alert(warnLevel: String, file: File, message: String, line: Int, column: Option[Int] = None)
+
+ object Alert {
+ val lineRegex = """(.*) file=(.*) message=(.*) line=(\d+)""".r
+ val columnRegex = """(.*) file=(.*) message=(.*) line=(\d+) column=(\d+)""".r
+
+ def apply(line: String): Option[Alert] = Option(line match {
+ case lineRegex(warnLevel, f, message, line) =>
+ Alert(warnLevel, file(f), message, line.toInt)
+ case columnRegex(warnLevel, f, message, line, column) =>
+ Alert(warnLevel, file(f), message, line.toInt, Some(column.toInt))
+ case _ => null
+ })
+ }
+}
+
@@ -0,0 +1,83 @@
+package com.github.aselab.scalastyle
+
+import sbt._
+
+object SecurityUtil {
+ import java.security.Permission
+
+ def notExitSecurityManager(originalManager: SecurityManager) =
+ new SecurityManager {
+ // protect System.exit(0)
+ override def checkExit(code: Int): Unit =
+ throw new Exception("exit")
+
+ override def checkPermission(perm: Permission): Unit =
+ Option(originalManager).foreach(_.checkPermission(perm))
+
+ override def checkPermission(perm: Permission , obj: Object): Unit =
+ Option(originalManager).foreach(_.checkPermission(perm, obj))
+ }
+
+ /**
+ * Replace SecurityManager as notExitSecurityManager
+ */
+ def notExit(f: => Any) = {
+ import java.io._
+ val originalManager = System.getSecurityManager
+ val os = new ByteArrayOutputStream
+
+ System.setSecurityManager(notExitSecurityManager(originalManager))
+ try {
+ scala.Console.withOut(os) {
+ f
+ }
+ os.toString("utf-8")
+ } catch {
+ case e => os.toString("utf-8")
+ }finally {
+ System.setSecurityManager(originalManager)
+ }
+ }
+}
+
+object IOUtil {
+ implicit def enumToIterator[A](e : java.util.Enumeration[A]) = new Iterator[A] {
+ def next = e.nextElement
+ def hasNext = e.hasMoreElements
+ }
+
+ def copyJarResourses(url: java.net.URL, destination: String, logger: Logger) {
+ url.openConnection match {
+ case connection: java.net.JarURLConnection =>
+ val entryName = connection.getEntryName
+ val jarFile = connection.getJarFile
+ jarFile.entries.filter(_.getName.startsWith(entryName)).foreach { e =>
+ val fileName = e.getName.drop(entryName.size)
+ val target = file(destination) / fileName
+ val message = if (target.exists) "overrided: " else "created: "
+ if (!e.isDirectory) {
+ if (safeToCreateFile(target)) {
+ IO.transfer(jarFile.getInputStream(e), target)
+ logger.success(message + target)
+ }
+ } else {
+ IO.createDirectory(target)
+ if (!target.exists) logger.success("created: " + target)
+ }
+ }
+ }
+ }
+
+ def safeToCreateFile(file: File): Boolean = {
+ def askUser: Boolean = {
+ val question = "The file %s exists, do you want to override it? (y/n): ".format(file.getPath)
+ scala.Console.readLine(question).toLowerCase.headOption match {
+ case Some('y') => true
+ case Some('n') => false
+ case _ => askUser
+ }
+ }
+ if (file.exists) askUser else true
+ }
+}
+
Oops, something went wrong. Retry.

0 comments on commit 7bed5ea

Please sign in to comment.