diff --git a/src/main/scala/org/scalastyle/Checker.scala b/src/main/scala/org/scalastyle/Checker.scala index b5817ed2..b3fa0a4d 100644 --- a/src/main/scala/org/scalastyle/Checker.scala +++ b/src/main/scala/org/scalastyle/Checker.scala @@ -50,11 +50,14 @@ case class Lines(lines: Array[Line], lastChar: Char) { None } + def toLine(position: Int): Option[Int] = + findLineAndIndex(position) map { case (_, index) => index } + def toLineColumn(position: Int): Option[LineColumn] = findLineAndIndex(position) map { case (line, index) => LineColumn(index, position - line.start) } - def toFullLineTuple(position: Int): Option[(LineColumn, LineColumn)] = - findLineAndIndex(position) map { case (line, index) => (LineColumn(index, 0), LineColumn(index + 1, 0)) } + def toFullLineTuple(position: Int): Option[(Int, Int)] = + findLineAndIndex(position) map { case (_, index) => (index, index + 1) } } @@ -71,9 +74,10 @@ class ScalastyleChecker[T <: FileSpec](classLoader: Option[ClassLoader] = None) private[this] def privateCheckFiles( configuration: ScalastyleConfiguration, files: Iterable[T] - ): Seq[Message[T]] = { - val checks = configuration.checks.filter(_.enabled) + ): List[Message[T]] = { val checkerUtils = new CheckerUtils(classLoader) + val checks = checkerUtils.createChecks(configuration.checks.filter(_.enabled)) + StartWork() :: files .flatMap(file => StartFile(file) :: checkerUtils.verifyFile(configuration, checks, file) ::: @@ -105,9 +109,10 @@ object Checker { ) } - def isObject(s: String): Boolean = - s == "java.lang.Object" || s == "Any" || s == "scala.Any" || s == "Object" + private val ObjectNames = Set("Any", "Object", "scala.Any", "java.lang.Object") + def isObject(s: String): Boolean = ObjectNames.contains(s) def isNotObject(s: String): Boolean = !isObject(s) + } class CheckerUtils(classLoader: Option[ClassLoader] = None) { @@ -125,39 +130,41 @@ class CheckerUtils(classLoader: Option[ClassLoader] = None) { def verifySource[T <: FileSpec]( configuration: ScalastyleConfiguration, - classes: List[ConfigurationChecker], + checks: => List[Checker[_]], file: T, source: String - ): List[Message[T]] = { - if (source.isEmpty) + ): List[Message[T]] = + if (source.isEmpty) { Nil - else { - val lines = Checker.parseLines(source) + } else { val scalariformAst = parseScalariform(source) - - val commentFilters = - if (configuration.commentFilter) - CommentFilter.findCommentFilters(scalariformAst.comments, lines) - else - Nil - - classes - .flatMap(cc => newInstance(cc.className, cc.level, cc.parameters, cc.customMessage, cc.customId)) - .flatMap(c => - c match { - case c: FileChecker => c.verify(file, c.level, lines, lines) - case c: ScalariformChecker => c.verify(file, c.level, scalariformAst.ast, lines) - case c: CombinedChecker => c.verify(file, c.level, CombinedAst(scalariformAst.ast, lines), lines) - case _ => Nil - } - ) - .filter(m => CommentFilter.filterApplies(m, commentFilters)) + verifyAst(configuration, checks, file, scalariformAst, source) } + + private def verifyAst[T <: FileSpec]( + configuration: ScalastyleConfiguration, + checks: List[Checker[_]], + file: T, + ast: ScalariformAst, + source: String + ): List[Message[T]] = { + val lines = Checker.parseLines(source) + val commentFilters = + if (configuration.commentFilter) CommentFilter.findCommentFilters(ast.comments, lines) else Nil + + checks + .flatMap { + case c: FileChecker => c.verify(file, c.level, lines, lines) + case c: ScalariformChecker => c.verify(file, c.level, ast.ast, lines) + case c: CombinedChecker => c.verify(file, c.level, CombinedAst(ast.ast, lines), lines) + case _ => Nil + } + .filter(m => CommentFilter.filterApplies(m, commentFilters)) } def verifyFile[T <: FileSpec]( configuration: ScalastyleConfiguration, - classes: List[ConfigurationChecker], + checks: List[Checker[_]], file: T ): List[Message[T]] = { try { @@ -165,7 +172,7 @@ class CheckerUtils(classLoader: Option[ClassLoader] = None) { case fs: RealFileSpec => readFile(fs.name, fs.encoding) case ss: SourceSpec => ss.contents } - verifySource(configuration, classes, file, s) + verifySource(configuration, checks, file, s) } catch { case e: Exception => List( @@ -213,6 +220,12 @@ class CheckerUtils(classLoader: Option[ClassLoader] = None) { } } + def createChecks(configuration: ScalastyleConfiguration): List[Checker[_]] = + createChecks(configuration.checks.filter(_.enabled)) + + def createChecks(classes: List[ConfigurationChecker]): List[Checker[_]] = + classes.flatMap(cc => newInstance(cc.className, cc.level, cc.parameters, cc.customMessage, cc.customId)) + private def newInstance( name: String, level: Level, diff --git a/src/main/scala/org/scalastyle/CommentFilter.scala b/src/main/scala/org/scalastyle/CommentFilter.scala index 839c101d..35effa7d 100644 --- a/src/main/scala/org/scalastyle/CommentFilter.scala +++ b/src/main/scala/org/scalastyle/CommentFilter.scala @@ -21,7 +21,7 @@ import scala.collection.mutable.ListBuffer import _root_.scalariform.lexer.Comment -case class CommentFilter(id: Option[String], start: Option[LineColumn], end: Option[LineColumn]) +case class CommentFilter(id: Option[String], start: Option[Int], end: Option[Int]) case class CommentInter(id: Option[String], position: Int, off: Boolean) object CommentFilter { @@ -63,18 +63,18 @@ object CommentFilter { val list = ListBuffer[CommentFilter]() val inMap = new mutable.HashMap[Option[String], Boolean]() - val start = new mutable.HashMap[Option[String], Option[LineColumn]]() + val start = new mutable.HashMap[Option[String], Option[Int]]() it.foreach { ci => (inMap.getOrElse(ci.id, false), ci.off) match { case (true, false) => // off then on, add a new CommentFilter - list += CommentFilter(ci.id, start.getOrElse(ci.id, None), lines.toLineColumn(ci.position)) + list += CommentFilter(ci.id, start.getOrElse(ci.id, None), lines.toLine(ci.position)) inMap.put(ci.id, false) start.remove(ci.id) case (true, true) => // off then off, do nothing case (false, false) => // on then on, do nothing case (false, true) => // on then off, reset start - start.put(ci.id, lines.toLineColumn(ci.position)) + start.put(ci.id, lines.toLine(ci.position)) inMap.put(ci.id, true) } } @@ -102,8 +102,8 @@ object CommentFilter { else { val m = se.lineNumber.get (cf.start, cf.end) match { - case (Some(s), Some(e)) => m >= s.line && m < e.line - case (Some(s), None) => m >= s.line + case (Some(s), Some(e)) => m >= s && m < e + case (Some(s), None) => m >= s case (None, Some(_)) => false // we just have an :off, filter doesn't apply case (None, None) => false // this isn't possible, say it doesn't apply } diff --git a/src/main/scala/org/scalastyle/scalariform/AbstractMethodChecker.scala b/src/main/scala/org/scalastyle/scalariform/AbstractMethodChecker.scala index 8b86a8a7..5df62d9b 100644 --- a/src/main/scala/org/scalastyle/scalariform/AbstractMethodChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/AbstractMethodChecker.scala @@ -101,18 +101,18 @@ abstract class AbstractMethodChecker extends ScalariformChecker { val it = for { t <- localvisit(ast.immediateChildren.head) f <- traverse(t) - if matches(f) - } yield PositionError(f.position.get, params(f)) + p <- matches(f) + } yield PositionError(p, params(f)) - it.toList + it } private def traverse(t: BaseClazz[AstNode]): ListType = { val l = t.subs.flatMap(traverse) - if (matches(t)) t :: l else l + if (matches(t).isDefined) t :: l else l } - def matches(t: BaseClazz[AstNode]): Boolean + def matches(t: BaseClazz[AstNode]): Option[Int] protected def getParams(p: ParamClauses): List[Param] = p.paramClausesAndNewlines @@ -132,10 +132,8 @@ abstract class AbstractMethodChecker extends ScalariformChecker { protected def getParamTypes(pc: ParamClauses): List[String] = getParams(pc).map(p => typename(p.paramTypeOpt.get._2)) - protected def matchFunDefOrDcl(t: BaseClazz[AstNode], fn: FunDefOrDcl => Boolean): Boolean = - t match { - case f: FunDefOrDclClazz => fn(f.t); case _ => false - } + protected def matchFunDefOrDcl(t: BaseClazz[AstNode], fn: FunDefOrDcl => Boolean): Option[Int] = + t.subs.collectFirst { case f: FunDefOrDclClazz if fn(f.t) => f.t.nameToken.offset } protected def methodMatch(name: String, paramTypesMatch: List[String] => Boolean)(t: FunDefOrDcl): Boolean = t.nameToken.text == name && paramTypesMatch(getParamTypes(t.paramClauses)) diff --git a/src/main/scala/org/scalastyle/scalariform/CovariantEqualsChecker.scala b/src/main/scala/org/scalastyle/scalariform/CovariantEqualsChecker.scala index 8aae6473..8ae9cec0 100644 --- a/src/main/scala/org/scalastyle/scalariform/CovariantEqualsChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/CovariantEqualsChecker.scala @@ -17,17 +17,16 @@ package org.scalastyle.scalariform import org.scalastyle.Checker + import scalariform.parser.AstNode import scalariform.parser.FunDefOrDcl class CovariantEqualsChecker extends AbstractMethodChecker { val errorKey = "covariant.equals" - def matches(t: BaseClazz[AstNode]): Boolean = { - val equalsObject = t.subs.exists(matchFunDefOrDcl(_, isEqualsObject)) - val equalsOther = t.subs.exists(matchFunDefOrDcl(_, isEqualsOther)) - - !equalsObject && equalsOther + def matches(t: BaseClazz[AstNode]): Option[Int] = { + val equalsObject = matchFunDefOrDcl(t, isEqualsObject).isEmpty + if (equalsObject) matchFunDefOrDcl(t, isEqualsOther) else None } private def isEqualsOther(t: FunDefOrDcl): Boolean = diff --git a/src/main/scala/org/scalastyle/scalariform/CyclomaticComplexityChecker.scala b/src/main/scala/org/scalastyle/scalariform/CyclomaticComplexityChecker.scala index e6a12f47..ea661dfe 100644 --- a/src/main/scala/org/scalastyle/scalariform/CyclomaticComplexityChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/CyclomaticComplexityChecker.scala @@ -18,7 +18,6 @@ package org.scalastyle.scalariform import _root_.scalariform.lexer.Token import _root_.scalariform.lexer.Tokens.CASE -import _root_.scalariform.lexer.Tokens.DO import _root_.scalariform.lexer.Tokens.FOR import _root_.scalariform.lexer.Tokens.IF import _root_.scalariform.lexer.Tokens.MATCH @@ -39,7 +38,7 @@ class CyclomaticComplexityChecker extends CombinedChecker { val DefaultCountCases = true private lazy val maximum = getInt("maximum", DefaultMaximum) private lazy val countCases = getBoolean("countCases", DefaultCountCases) - private val defaultTokens = Set(IF, WHILE, DO, FOR) + private val defaultTokens = Set(IF, WHILE, FOR) case class FunDefOrDclClazz(t: FunDefOrDcl, position: Option[Int], subs: List[FunDefOrDclClazz]) extends Clazz[FunDefOrDcl]() @@ -50,7 +49,7 @@ class CyclomaticComplexityChecker extends CombinedChecker { f <- traverse(t) value = matches(f, ast.lines, maximum) if value > maximum - } yield PositionError(t.position.get, List("" + value, "" + maximum)) + } yield PositionError(f.position.get, List("" + value, "" + maximum)) it } diff --git a/src/main/scala/org/scalastyle/scalariform/EmptyInterpolatedStringChecker.scala b/src/main/scala/org/scalastyle/scalariform/EmptyInterpolatedStringChecker.scala index 81159553..d1e8b387 100644 --- a/src/main/scala/org/scalastyle/scalariform/EmptyInterpolatedStringChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/EmptyInterpolatedStringChecker.scala @@ -30,7 +30,7 @@ class EmptyInterpolatedStringChecker extends ScalariformChecker { List(left, right) <- ast.tokens.sliding(2) if left.tokenType == INTERPOLATION_ID && typesSupportingVariables.contains(left.text) && interpolationRegex.findFirstIn(right.text).isEmpty - } yield PositionError(right.offset) + } yield PositionError(left.offset) it.toList } diff --git a/src/main/scala/org/scalastyle/scalariform/EqualsHashCodeChecker.scala b/src/main/scala/org/scalastyle/scalariform/EqualsHashCodeChecker.scala index a7893cab..39164f96 100644 --- a/src/main/scala/org/scalastyle/scalariform/EqualsHashCodeChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/EqualsHashCodeChecker.scala @@ -22,11 +22,15 @@ import scalariform.parser.FunDefOrDcl class EqualsHashCodeChecker extends AbstractMethodChecker { val errorKey = "equals.hash.code" - def matches(t: BaseClazz[AstNode]): Boolean = { - val hc = t.subs.exists(matchFunDefOrDcl(_, isHashCode)) - val eq = t.subs.exists(matchFunDefOrDcl(_, isEqualsObject)) + def matches(t: BaseClazz[AstNode]): Option[Int] = { + val hc = matchFunDefOrDcl(t, isHashCode) + val eq = matchFunDefOrDcl(t, isEqualsObject) - (hc && !eq) || (!hc && eq) + if (hc.isDefined) { + if (eq.isDefined) None else hc + } else { + if (eq.isDefined) eq else None + } } private def isHashCode(t: FunDefOrDcl): Boolean = methodMatch("hashCode", noParameter() _)(t) diff --git a/src/main/scala/org/scalastyle/scalariform/ForBraceChecker.scala b/src/main/scala/org/scalastyle/scalariform/ForBraceChecker.scala index 449be603..c6e7a5a8 100644 --- a/src/main/scala/org/scalastyle/scalariform/ForBraceChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/ForBraceChecker.scala @@ -45,9 +45,9 @@ class ForBraceChecker extends CombinedChecker { private def validSingleLine(t: ForExpr, lines: Lines) = { singleLineAllowed && { val singleLine = for { - start <- lines.toLineColumn(t.forToken.offset) - end <- lines.toLineColumn(t.tokens.last.offset) - if start.line == end.line + start <- lines.toLine(t.forToken.offset) + end <- lines.toLine(t.tokens.last.offset) + if start == end } yield () singleLine.isDefined diff --git a/src/main/scala/org/scalastyle/scalariform/IfBraceChecker.scala b/src/main/scala/org/scalastyle/scalariform/IfBraceChecker.scala index 39b4c2e3..c7b35ca4 100644 --- a/src/main/scala/org/scalastyle/scalariform/IfBraceChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/IfBraceChecker.scala @@ -21,7 +21,6 @@ import _root_.scalariform.parser.Expr import _root_.scalariform.parser.IfExpr import org.scalastyle.CombinedAst import org.scalastyle.CombinedChecker -import org.scalastyle.LineColumn import org.scalastyle.Lines import org.scalastyle.PositionError import org.scalastyle.ScalastyleError @@ -69,11 +68,11 @@ class IfBraceChecker extends CombinedChecker { singleLineAllowed: Boolean, doubleLineAllowed: Boolean ): Boolean = { - val ifLine = lines.toLineColumn(t.t.ifToken.offset) + val ifLine = lines.toLine(t.t.ifToken.offset) val ifBodyLine = firstLineOfGeneralTokens(t.t.body, lines) val (elseLine, elseBodyLine) = t.t.elseClause match { - case Some(e) => (lines.toLineColumn(e.elseToken.offset), firstLineOfGeneralTokens(e.elseBody, lines)) + case Some(e) => (lines.toLine(e.elseToken.offset), firstLineOfGeneralTokens(e.elseBody, lines)) case None => (None, None) } @@ -90,9 +89,9 @@ class IfBraceChecker extends CombinedChecker { } } - private[this] def sameLine(l1: Option[LineColumn], l2: Option[LineColumn]) = + private[this] def sameLine(l1: Option[Int], l2: Option[Int]) = (l1, l2) match { - case (Some(x), Some(y)) => x.line == y.line + case (Some(x), Some(y)) => x == y case _ => true } @@ -102,7 +101,7 @@ class IfBraceChecker extends CombinedChecker { body.contents.head match { case e: BlockExpr => None case e: IfExpr => None - case e: Any => lines.toLineColumn(e.tokens.head.offset) + case e: Any => lines.toLine(e.tokens.head.offset) } } else None diff --git a/src/main/scala/org/scalastyle/scalariform/ImportsChecker.scala b/src/main/scala/org/scalastyle/scalariform/ImportsChecker.scala index 37908b02..fa4ce614 100644 --- a/src/main/scala/org/scalastyle/scalariform/ImportsChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/ImportsChecker.scala @@ -213,13 +213,13 @@ class ImportOrderChecker extends ScalariformChecker { val CompilationUnit(statements, _) = ast statements.immediateChildren.flatMap { n => val result = n match { - case ImportClause(_, BlockImportExpr(prefix, selectors), _, _) => + case ImportClause(_, e @ BlockImportExpr(prefix, selectors), _, _) => val text = exprToText(prefix.contents, if (lexicographic) selectors.tokens else Nil) - checkImport(text, n.firstToken.offset) ++ checkSelectors(selectors) + checkImport(text, e.firstToken.offset) ++ checkSelectors(selectors) - case ImportClause(_, Expr(contents), _, _) => + case ImportClause(_, e @ Expr(contents), _, _) => val text = exprToText(contents) - checkImport(text, n.firstToken.offset) + checkImport(text, e.firstToken.offset) case _ => Nil @@ -281,13 +281,13 @@ class ImportOrderChecker extends ScalariformChecker { val ImportSelectors(_, first, others, _) = selectors val errors = new ListBuffer[ScalastyleError]() - val names = Seq(first.contents.head.tokens.head.text) ++ - others.map(_._2.contents.head.tokens.head.text) + val names = Seq(first.contents.head.tokens.head) ++ + others.map(_._2.contents.head.tokens.head) if (names.size > 1) { names.sliding(2).foreach { case Seq(left, right) => - if (compareNames(left, right, isImport = false) > 0) - errors += newError(selectors.firstToken.offset, "wrongOrderInSelector", right, left) + if (compareNames(left.text, right.text, isImport = false) > 0) + errors += newError(left.offset, "wrongOrderInSelector", right.text, left.text) } } diff --git a/src/main/scala/org/scalastyle/scalariform/LowercasePatternMatchChecker.scala b/src/main/scala/org/scalastyle/scalariform/LowercasePatternMatchChecker.scala index 5d80eb42..b6dbd884 100644 --- a/src/main/scala/org/scalastyle/scalariform/LowercasePatternMatchChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/LowercasePatternMatchChecker.scala @@ -17,7 +17,7 @@ package org.scalastyle.scalariform import _root_.scalariform.lexer.Token -import _root_.scalariform.lexer.Tokens.VARID +import _root_.scalariform.lexer.Tokens._ // scalastyle:ignore underscore.import import _root_.scalariform.parser.CasePattern import _root_.scalariform.parser.CompilationUnit import org.scalastyle.PositionError @@ -31,18 +31,26 @@ class LowercasePatternMatchChecker extends ScalariformChecker { final def verify(ast: CompilationUnit): List[ScalastyleError] = { val it = for { f <- visit(map)(ast.immediateChildren.head) - if matches(f) - } yield PositionError(f.pattern.firstToken.offset) + t <- matches(f.pattern.tokens, Nil) + } yield PositionError(t.offset) it } - private def matches(t: CasePattern) = { - t.pattern.tokens match { - case List(t: Token) => t.tokenType == VARID && t.text.length() > 0 && t.text(0).isLower - case _ => false + @scala.annotation.tailrec + private def matches(tokens: List[Token], res: List[Token]): List[Token] = + tokens.headOption match { + case None => res + case Some(t @ Token(VARID, text, _, _)) if text.headOption.exists(_.isLower) => + val tail = tokens.tail + tail.headOption match { + case Some(Token(COMMA | RPAREN | AT, _, _, _)) => + matches(tail.tail, t :: res) + case None => t :: res + case _ => matches(tail.tail, res) + } + case _ => matches(tokens.tail, res) } - } private def map(t: CasePattern): List[CasePattern] = List(t) ::: visit(map)(t.pattern) ::: visit(map)(t.guardOption) diff --git a/src/main/scala/org/scalastyle/scalariform/MethodLengthChecker.scala b/src/main/scala/org/scalastyle/scalariform/MethodLengthChecker.scala index 8418b92a..8f8bf71c 100644 --- a/src/main/scala/org/scalastyle/scalariform/MethodLengthChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/MethodLengthChecker.scala @@ -16,12 +16,13 @@ package org.scalastyle.scalariform -import _root_.scalariform.parser.FunDefOrDcl -import org.scalastyle.CombinedAst -import org.scalastyle.CombinedChecker -import org.scalastyle.Lines -import org.scalastyle.PositionError -import org.scalastyle.ScalastyleError +// scalastyle:off underscore.import +import scala.annotation.tailrec + +import _root_.scalariform.lexer._ +import _root_.scalariform.parser._ + +import org.scalastyle._ import org.scalastyle.scalariform.VisitorHelper.Clazz import org.scalastyle.scalariform.VisitorHelper.visit @@ -38,75 +39,116 @@ class MethodLengthChecker extends CombinedChecker { case class FunDefOrDclClazz(t: FunDefOrDcl, position: Option[Int], subs: List[FunDefOrDclClazz]) extends Clazz[FunDefOrDcl]() + @tailrec + private def getInnerExpr(expr: Expr): ExprElement = expr.contents match { + case List(subexpr) => + subexpr match { + case t: Expr => getInnerExpr(t) + case t: Any => t + } + case _ => expr + } + + private def getNextToken(tokens: List[Token], ignoreComments: Boolean): Option[Token] = + tokens.tail.headOption match { + case x @ Some(tok) if !ignoreComments => + tok.associatedWhitespaceAndComments.tokens.collectFirst { case t: Comment => t.token }.orElse(x) + case x: Any => x + } + + private def getNextLastToken(tokens: List[Token], ignoreComments: Boolean): Option[Token] = { + val lastTwoTokens = tokens.drop(tokens.length - 2) + val lastComment = lastTwoTokens.lastOption match { + case Some(tok) if !ignoreComments => + tok.associatedWhitespaceAndComments.tokens.reverse.find(_.isInstanceOf[Comment]).map(_.token) + case _ => None + } + lastComment.orElse(lastTwoTokens.headOption) + } + def verify(ast: CombinedAst): List[ScalastyleError] = { val maxLength = getInt("maxLength", DefaultMaximumLength) val ignoreComments = getBoolean("ignoreComments", DefaultIgnoreComments) val ignoreEmpty = getBoolean("ignoreEmpty", DefaultIgnoreEmpty) + val lines = ast.lines val it = for { t <- localvisit(ast.compilationUnit.immediateChildren.head) f <- traverse(t) - if matches(f, ast.lines, maxLength, ignoreComments, ignoreEmpty) - } yield PositionError(t.position.get, List("" + maxLength)) + body <- f.t.funBodyOpt match { + case Some(t: ProcFunBody) => Some(t.bodyBlock) + case Some(t: ExprFunBody) => Some(getInnerExpr(t.body)) + case _ => None + } + isBlock = body.isInstanceOf[BlockExpr] + tokens = body.tokens + headToken <- if (isBlock) getNextToken(tokens, ignoreComments) else tokens.headOption + lastToken <- if (isBlock) getNextLastToken(tokens, ignoreComments) else tokens.lastOption + begLineColumn <- lines.toLineColumn(headToken.offset) + endLineColumn <- lines.toLineColumn(lastToken.lastCharacterOffset) + numLines = methodLength(lines.lines, begLineColumn, endLineColumn, ignoreComments, ignoreEmpty) + if numLines > maxLength + } yield PositionError(t.position.get, List(s"$numLines > $maxLength")) it } private def traverse(t: FunDefOrDclClazz): List[FunDefOrDclClazz] = t :: t.subs.flatMap(traverse) - private def matches( - t: FunDefOrDclClazz, - lines: Lines, - maxLines: Int, + // scalastyle:off method.length cyclomatic.complexity + private def methodLength( + lines: Array[Line], + begLineColumn: LineColumn, // included, 1-based + endLineColumn: LineColumn, // included, 1-based ignoreComments: Boolean, ignoreEmpty: Boolean - ) = { + ): Int = { + val begLine = begLineColumn.line - 1 // 0-based, included if (ignoreComments) { - val count = for { - (_, start) <- lines.findLineAndIndex(t.t.defToken.offset) - (_, end) <- lines.findLineAndIndex(t.t.tokens.last.offset) - } yield { - var count = 0 - var multilineComment = false - - // do not count deftoken line and end block line - for (i <- (start + 1) until end) { - val lineText = - lines.lines(i - 1).text.trim // zero based index, therefore "-1" when accessing the line - if (ignoreEmpty && lineText.isEmpty) { - // do nothing - } else if (lineText.startsWith(SinglelineComment)) { - // do nothing - } else { - if (lineText.contains(MultilineCommentsOpener)) - // multiline comment start /* - // this line won't be counted even if - // there exists any token before /* - multilineComment = true - if (!multilineComment) - count = count + 1 - if (lineText.contains(MultilineCommentsCloser)) - // multiline comment end */ - // this line won't be counted even if - // there exists any token after */ - multilineComment = false + var count = 0 + var multilineComment = false + val endLine = endLineColumn.line - 1 // 0-based, included + for { + i <- begLine to endLine + lineText = lines(i).text + slcIndex = lineText.indexOf(SinglelineComment) + if !(slcIndex == 0 || ignoreEmpty && lineText.isEmpty) + } { + val begIndex = if (i == begLine) begLineColumn.column else 0 + val endIndex = { + val idx = if (slcIndex < 0) lineText.length else slcIndex + if (i == endLine) math.min(endLineColumn.column + 1, idx) else idx + } + @tailrec + def iter(index: Int, res: Boolean = false): Boolean = { + val delim = if (multilineComment) MultilineCommentsCloser else MultilineCommentsOpener + val nextIndex = { + val idx = lineText.indexOf(delim, index) + if (idx < 0 || idx > endIndex) endIndex else idx + } + val nextRes = res || !multilineComment && { + val idx = lineText.indexWhere(!Character.isSpaceChar(_), index) + idx >= 0 && idx < nextIndex + } + if (nextIndex == endIndex) { nextRes } + else { + multilineComment = !multilineComment + iter(nextIndex + delim.length, nextRes) } } - count + if (iter(begIndex)) count += 1 } - count.get > maxLines + count } else { - val head = lines.toLineColumn(t.t.defToken.offset).get.line + 1 - val tail = lines.toLineColumn(t.t.tokens.last.offset).get.line - 1 - val emptyLines = if (ignoreEmpty) { - lines.lines - .slice(head - 1, tail) // extract actual method content - .count(_.text.isEmpty) // count empty lines - } else - 0 - (tail - head + 1) - emptyLines > maxLines + val endLine = endLineColumn.line // 0-based, excluded + if (ignoreEmpty) { + lines.view.slice(begLine, endLine).count(_.text.nonEmpty) + } else { + endLine - begLine + } } } + // scalastyle:on method.length private def localvisit(ast: Any): List[FunDefOrDclClazz] = ast match { diff --git a/src/main/scala/org/scalastyle/scalariform/NoCloneChecker.scala b/src/main/scala/org/scalastyle/scalariform/NoCloneChecker.scala index a4389b79..7a2b92ef 100644 --- a/src/main/scala/org/scalastyle/scalariform/NoCloneChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/NoCloneChecker.scala @@ -22,8 +22,8 @@ import scalariform.parser.FunDefOrDcl class NoCloneChecker extends AbstractMethodChecker { val errorKey = "no.clone" - def matches(t: BaseClazz[AstNode]): Boolean = - t.subs.exists(matchFunDefOrDcl(_, isClone)) + def matches(t: BaseClazz[AstNode]): Option[Int] = + matchFunDefOrDcl(t, isClone) private def isClone(t: FunDefOrDcl): Boolean = methodMatch("clone", noParameter() _)(t) } diff --git a/src/main/scala/org/scalastyle/scalariform/NoFinalizeChecker.scala b/src/main/scala/org/scalastyle/scalariform/NoFinalizeChecker.scala index ebdcfb1a..cbc5cafc 100644 --- a/src/main/scala/org/scalastyle/scalariform/NoFinalizeChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/NoFinalizeChecker.scala @@ -22,8 +22,8 @@ import scalariform.parser.FunDefOrDcl class NoFinalizeChecker extends AbstractMethodChecker { val errorKey = "no.finalize" - def matches(t: BaseClazz[AstNode]): Boolean = - t.subs.exists(matchFunDefOrDcl(_, isFinalize)) + def matches(t: BaseClazz[AstNode]): Option[Int] = + matchFunDefOrDcl(t, isFinalize) private def isFinalize(t: FunDefOrDcl): Boolean = methodMatch("finalize", noParameter() _)(t) } diff --git a/src/main/scala/org/scalastyle/scalariform/NoWhitespaceBracketChecker.scala b/src/main/scala/org/scalastyle/scalariform/NoWhitespaceBracketChecker.scala index 2260b3b5..faf9f1c6 100644 --- a/src/main/scala/org/scalastyle/scalariform/NoWhitespaceBracketChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/NoWhitespaceBracketChecker.scala @@ -30,7 +30,7 @@ class NoWhitespaceBeforeLeftBracketChecker extends ScalariformChecker { val it = for { List(left, right) <- ast.tokens.sliding(2) if right.tokenType == LBRACKET && charsBetweenTokens(left, right) > 0 - } yield PositionError(left.offset) + } yield PositionError(right.offset) it.toList } diff --git a/src/main/scala/org/scalastyle/scalariform/NonASCIICharacterChecker.scala b/src/main/scala/org/scalastyle/scalariform/NonASCIICharacterChecker.scala index dde82836..59794d3d 100644 --- a/src/main/scala/org/scalastyle/scalariform/NonASCIICharacterChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/NonASCIICharacterChecker.scala @@ -18,7 +18,7 @@ package org.scalastyle.scalariform import java.util.regex.Pattern -import _root_.scalariform.lexer.{Token, Tokens} +import _root_.scalariform.lexer.{Comment, Token, Tokens} import _root_.scalariform.parser.CompilationUnit import org.scalastyle.PositionError import org.scalastyle.ScalariformChecker @@ -35,7 +35,12 @@ class NonASCIICharacterChecker extends ScalariformChecker { getBoolean("allowStringLiterals", defaultAllowStringLiterals) override def verify(ast: CompilationUnit): List[ScalastyleError] = - ast.tokens.filter(hasNonAsciiChars).map(x => PositionError(x.offset)) + ast.tokens.flatMap(getTokenNonAsciiChars(_).map(PositionError(_))) + + private def getTokenNonAsciiChars(x: Token): Option[Int] = + x.associatedWhitespaceAndComments.tokens + .collectFirst { case c: Comment if hasNonAsciiChars(c.token) => c.token.offset } + .orElse(if (hasNonAsciiChars(x)) Some(x.offset) else None) private def hasNonAsciiChars(x: Token) = { x.rawText.trim.nonEmpty && diff --git a/src/main/scala/org/scalastyle/scalariform/NumberOfMethodsInTypeChecker.scala b/src/main/scala/org/scalastyle/scalariform/NumberOfMethodsInTypeChecker.scala index 84936b7b..fb14f48c 100644 --- a/src/main/scala/org/scalastyle/scalariform/NumberOfMethodsInTypeChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/NumberOfMethodsInTypeChecker.scala @@ -25,8 +25,8 @@ class NumberOfMethodsInTypeChecker extends AbstractMethodChecker { override def params(t: BaseClazz[AstNode]): List[String] = List("" + getInt("maxMethods", DefaultMaxMethods)) - def matches(t: BaseClazz[AstNode]): Boolean = { + def matches(t: BaseClazz[AstNode]): Option[Int] = { val maxMethods = getInt("maxMethods", DefaultMaxMethods) - t.subs.size > maxMethods + if (t.subs.size > maxMethods) t.position else None } } diff --git a/src/main/scala/org/scalastyle/scalariform/ScalaDocChecker.scala b/src/main/scala/org/scalastyle/scalariform/ScalaDocChecker.scala index be3733ef..324fb156 100644 --- a/src/main/scala/org/scalastyle/scalariform/ScalaDocChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/ScalaDocChecker.scala @@ -35,6 +35,7 @@ import _root_.scalariform.parser.TypeDefOrDcl import _root_.scalariform.parser.TypeParamClause import org.scalastyle.CombinedAst import org.scalastyle.CombinedChecker +import org.scalastyle.LineColumn import org.scalastyle.LineError import org.scalastyle.Lines import org.scalastyle.ScalastyleError @@ -106,26 +107,34 @@ class ScalaDocChecker extends CombinedChecker { * ``FullDefOrDcl`` -> ``PatDefOrDcl``, with the ScalaDoc attached to the ``FulDefOrDcl``, which * finds its way to us here in ``fallback``. */ - private def findScalaDoc(token: Token, lines: Lines, fallback: HiddenTokens): Option[ScalaDoc] = { + private def findScalaDoc( + token: Token, + lines: Lines, + fallback: HiddenTokens + )(f: ScalaDoc => List[ScalastyleError]): List[ScalastyleError] = { def toScalaDoc(ht: HiddenTokens): Option[ScalaDoc] = ht.rawTokens .find(_.isScalaDocComment) .map { commentToken => - val commentOffset = lines.toLineColumn(commentToken.offset).map(_.column).getOrElse(0) - ScalaDoc.apply(commentToken, commentOffset) + val lineColumn = lines.toLineColumn(commentToken.offset).getOrElse(LineColumn(0, 0)) + ScalaDoc(commentToken.rawText, lineColumn) } - toScalaDoc(token.associatedWhitespaceAndComments).orElse(toScalaDoc(fallback)) + toScalaDoc(token.associatedWhitespaceAndComments).orElse(toScalaDoc(fallback)).map(f).getOrElse { + List(LineError(lines.toLine(token.offset).get, List(Missing))) + } } - private def indentErrors(line: Int, style: DocIndentStyle)(scalaDoc: ScalaDoc): List[ScalastyleError] = + private def indentErrors(style: DocIndentStyle)(scalaDoc: ScalaDoc): List[ScalastyleError] = if (style == AnyDocStyle || style == scalaDoc.indentStyle) Nil + else if (SingleLineStyle == scalaDoc.indentStyle) + Nil else - List(LineError(line, List(InvalidDocStyle))) + List(LineError(scalaDoc.line, List(InvalidDocStyle))) // parse the parameters and report errors for the parameters (constructor or method) - private def paramErrors(line: Int, paramClausesOpt: Option[ParamClauses])( + private def paramErrors(paramClausesOpt: Option[ParamClauses])( scalaDoc: ScalaDoc ): List[ScalastyleError] = { def params(xs: List[Token]): List[String] = @@ -148,18 +157,16 @@ class ScalaDocChecker extends CombinedChecker { val extraScalaDocParams = scalaDoc.params.filterNot(param => paramNames.contains(param.name)) val validScalaDocParams = scalaDoc.params.filter(param => paramNames.contains(param.name)) + val line = scalaDoc.line missingScalaDocParams.map(missing => LineError(line, List(missingParam(missing)))) ++ extraScalaDocParams.map(extra => LineError(line, List(extraParam(extra.name)))) ++ validScalaDocParams.filter(_.text.isEmpty).map(empty => LineError(line, List(emptyParam(empty.name)))) - -// if (!scalaDoc.params.forall(p => paramNames.exists(name => p.name == name && !p.text.isEmpty))) List(LineError(line, List(MalformedParams))) -// else Nil } // parse the type parameters and report errors for the parameters (constructor or method) // scalastyle:off cyclomatic.complexity - private def tparamErrors(line: Int, tparamClausesOpt: Option[TypeParamClause])( + private def tparamErrors(tparamClausesOpt: Option[TypeParamClause])( scalaDoc: ScalaDoc ): List[ScalastyleError] = { def tparams(xs: List[Token], bracketDepth: Int): List[String] = @@ -201,6 +208,7 @@ class ScalaDocChecker extends CombinedChecker { val tparamNames = tparamClausesOpt.map(tc => tparams(tc.tokens, 0)).getOrElse(Nil) + val line = scalaDoc.line if (tparamNames.size != scalaDoc.typeParams.size) // bad param sizes List(LineError(line, List(MalformedTypeParams))) @@ -214,13 +222,13 @@ class ScalaDocChecker extends CombinedChecker { // scalastyle:on cyclomatic.complexity // parse the parameters and report errors for the return types - private def returnErrors(line: Int, returnTypeOpt: Option[(Token, Type)])( + private def returnErrors(returnTypeOpt: Option[(Token, Type)])( scalaDoc: ScalaDoc ): List[ScalastyleError] = { val needsReturn = returnTypeOpt.exists { case (_, tpe) => tpe.firstToken.text != "Unit" } if (needsReturn && scalaDoc.returns.isEmpty) - List(LineError(line, List(MalformedReturn))) + List(LineError(scalaDoc.line, List(MalformedReturn))) else Nil } @@ -261,7 +269,8 @@ class ScalaDocChecker extends CombinedChecker { // pick the ScalaDoc "attached" to the modifier, which actually means // ScalaDoc of the following member val scalaDocs = for { - token <- t.tokens + tree <- t.annotations ++ t.modifiers + token <- tree.tokens comment <- token.associatedWhitespaceAndComments if comment.token.isScalaDocComment } yield comment @@ -283,20 +292,17 @@ class ScalaDocChecker extends CombinedChecker { // class Foo, class Foo[A](a: A); // case class Foo(), case class Foo[A](a: A); // object Foo; - val (_, line) = lines.findLineAndIndex(t.firstToken.offset).get // we are checking parameters and type parameters val errors = if (shouldSkip(t)) Nil else { - findScalaDoc(t.firstToken, lines, fallback) - .map { scalaDoc => - paramErrors(line, t.paramClausesOpt)(scalaDoc) ++ - tparamErrors(line, t.typeParamClauseOpt)(scalaDoc) ++ - indentErrors(line, indentStyle)(scalaDoc) - } - .getOrElse(List(LineError(line, List(Missing)))) + findScalaDoc(t.firstToken, lines, fallback) { scalaDoc => + paramErrors(t.paramClausesOpt)(scalaDoc) ++ + tparamErrors(t.typeParamClauseOpt)(scalaDoc) ++ + indentErrors(indentStyle)(scalaDoc) + } } // and we descend, because we're interested in seeing members of the types @@ -306,50 +312,43 @@ class ScalaDocChecker extends CombinedChecker { ) case t: FunDefOrDcl => // def foo[A, B](a: Int): B = ... - val (_, line) = lines.findLineAndIndex(t.firstToken.offset).get - // we are checking parameters, type parameters and returns val errors = if (shouldSkip(t)) Nil else { - findScalaDoc(t.firstToken, lines, fallback) - .map { scalaDoc => - paramErrors(line, Some(t.paramClauses))(scalaDoc) ++ - tparamErrors(line, t.typeParamClauseOpt)(scalaDoc) ++ - returnErrors(line, t.returnTypeOpt)(scalaDoc) ++ - indentErrors(line, indentStyle)(scalaDoc) - } - .getOrElse(List(LineError(line, List(Missing)))) + findScalaDoc(t.firstToken, lines, fallback) { scalaDoc => + paramErrors(Some(t.paramClauses))(scalaDoc) ++ + tparamErrors(t.typeParamClauseOpt)(scalaDoc) ++ + returnErrors(t.returnTypeOpt)(scalaDoc) ++ + indentErrors(indentStyle)(scalaDoc) + } } // we don't descend any further errors case t: TypeDefOrDcl => // type Foo = ... - val (_, line) = lines.findLineAndIndex(t.firstToken.offset).get - // no params here val errors = if (shouldSkip(t)) Nil else - findScalaDoc(t.firstToken, lines, fallback) - .map(scalaDoc => indentErrors(line, indentStyle)(scalaDoc)) - .getOrElse(List(LineError(line, List(Missing)))) + findScalaDoc(t.firstToken, lines, fallback) { scalaDoc => + indentErrors(indentStyle)(scalaDoc) + } // we don't descend any further errors case t: PatDefOrDcl => // val a = ..., var a = ... - val (_, line) = lines.findLineAndIndex(t.valOrVarToken.offset).get val errors = if (shouldSkip(t)) Nil else { - findScalaDoc(t.firstToken, lines, fallback) - .map(scalaDoc => indentErrors(line, indentStyle)(scalaDoc)) - .getOrElse(List(LineError(line, List(Missing)))) + findScalaDoc(t.firstToken, lines, fallback) { scalaDoc => + indentErrors(indentStyle)(scalaDoc) + } } // we don't descend any further @@ -407,6 +406,7 @@ object ScalaDocChecker { object ScalaDocStyle extends DocIndentStyle object JavaDocStyle extends DocIndentStyle object AnyDocStyle extends DocIndentStyle + object SingleLineStyle extends DocIndentStyle object UndefinedDocStyle extends DocIndentStyle def getStyleFrom(name: String): DocIndentStyle = @@ -436,13 +436,14 @@ object ScalaDocChecker { /** * Take the ``raw`` and parse an instance of ``ScalaDoc`` - * @param raw the token containing the ScalaDoc - * @param offset column number of scaladoc's first string + * @param text the ScalaDoc text + * @param lineColumn line and column number of scaladoc's first string * @return the parsed instance */ // scalastyle:off cyclomatic.complexity - def apply(raw: Token, offset: Int): ScalaDoc = { - val strings = raw.rawText.split("\\n").toList + def apply(raw: String, lineColumn: LineColumn): ScalaDoc = { + val offset = lineColumn.column + val strings = raw.split("\\n").toList val indentStyle = { def getStyle(xs: List[String], style: DocIndentStyle): DocIndentStyle = @@ -458,15 +459,14 @@ object ScalaDocChecker { style match { case ScalaDocStyle | JavaDocStyle => if (lineStyle == style) getStyle(tail, style) else AnyDocStyle - case AnyDocStyle => - AnyDocStyle case UndefinedDocStyle => getStyle(tail, lineStyle) + case _ => style } case Nil => if (style == UndefinedDocStyle) AnyDocStyle else style } - getStyle(strings.tail, UndefinedDocStyle) + if (strings.lengthCompare(1) <= 0) SingleLineStyle else getStyle(strings.tail, UndefinedDocStyle) } val lines = strings.flatMap(x => @@ -491,7 +491,7 @@ object ScalaDocChecker { val typeParams = combineScalaDocFor(lines, "tparam", ScalaDocParameter) val returns = combineScalaDocFor(lines, "return", _ + _).headOption - ScalaDoc(raw.rawText, params, typeParams, returns, None, indentStyle) + ScalaDoc(lineColumn.line, raw, params, typeParams, returns, None, indentStyle) } // scalastyle:on cyclomatic.complexity } @@ -505,6 +505,7 @@ object ScalaDocChecker { /** * Models the parsed ScalaDoc + * @param line scaladoc line * @param text arbitrary text * @param params the parameters * @param typeParams the type parameters @@ -513,6 +514,7 @@ object ScalaDocChecker { * @param indentStyle doc indent style */ private case class ScalaDoc( + line: Int, text: String, params: List[ScalaDocParameter], typeParams: List[ScalaDocParameter], diff --git a/src/main/scala/org/scalastyle/scalariform/SimplifyBooleanExpressionChecker.scala b/src/main/scala/org/scalastyle/scalariform/SimplifyBooleanExpressionChecker.scala index c377beab..825ae681 100644 --- a/src/main/scala/org/scalastyle/scalariform/SimplifyBooleanExpressionChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/SimplifyBooleanExpressionChecker.scala @@ -38,20 +38,20 @@ class SimplifyBooleanExpressionChecker extends ScalariformChecker { val it1 = for { List(left, right) <- ast.tokens.sliding(2); if (left.text == "!" && isBoolean(right)) - } yield PositionError(left.offset) + } yield PositionError(right.offset) val it2 = for { t <- localvisit(ast); - if (matches(t)) - } yield PositionError(t.position.get) + p <- matches(t) + } yield PositionError(p) (it1.toList ::: it2.toList).sortWith((a, b) => a.position < b.position) } - private def matches[T <: AstNode](t: Clazz[T]): Boolean = { + private def matches[T <: AstNode](t: Clazz[T]): Option[Int] = { t match { - case t: InfixExprClazz => matchesInfixOp(t.id) && (boolean(t.left) || boolean(t.right)) - case _ => false + case t: InfixExprClazz if matchesInfixOp(t.id) => boolean(t.left).orElse(boolean(t.right)) + case _ => None } } @@ -74,9 +74,10 @@ class SimplifyBooleanExpressionChecker extends ScalariformChecker { case t: Any => visit(t, localvisit) } - private def boolean(expr: List[Clazz[_]]) = - expr.size == 1 && expr(0) - .isInstanceOf[GeneralTokensClazz] && expr(0).asInstanceOf[GeneralTokensClazz].bool + private def boolean(expr: List[Clazz[_]]) = expr match { + case List(t: GeneralTokensClazz) if t.bool => t.position + case _ => None + } private def isBoolean(t: GeneralTokens): Boolean = t.tokens.size == 1 && isBoolean(t.tokens(0)) private def isBoolean(t: Token): Boolean = Set(TRUE, FALSE).contains(t.tokenType) diff --git a/src/main/scala/org/scalastyle/scalariform/TodoCommentChecker.scala b/src/main/scala/org/scalastyle/scalariform/TodoCommentChecker.scala index 7a57d671..c1295f2d 100644 --- a/src/main/scala/org/scalastyle/scalariform/TodoCommentChecker.scala +++ b/src/main/scala/org/scalastyle/scalariform/TodoCommentChecker.scala @@ -34,13 +34,13 @@ class TodoCommentChecker extends CombinedChecker { def verify(ast: CombinedAst): List[ScalastyleError] = { val words = getString("words", defaultWords) val split = words.split("\\|").map(Pattern.quote).mkString("|") - val regex = ("""(?i)(//|/\*|/\*\*|\*)\s?(""" + split + """)(:?)\s+""").r + val regex = ("""(?i)(?:^//|^/\*|^/\*\*|\*)\s?(""" + split + """):?\s+""").r.unanchored for { t <- ast.compilationUnit.tokens at <- t.associatedWhitespaceAndComments if Tokens.COMMENTS.contains(at.token.tokenType) - if at.text.split("\n").exists(s => regex.findFirstIn(s).isDefined) - } yield PositionError(at.token.offset, List(words)) + tag <- at.text.split("\n").view.collectFirst { case regex(tag) => tag } + } yield PositionError(at.token.offset, List(tag)) } } diff --git a/src/test/scala/org/scalastyle/CommentFilterTest.scala b/src/test/scala/org/scalastyle/CommentFilterTest.scala index 08d86e30..ee9ccc19 100644 --- a/src/test/scala/org/scalastyle/CommentFilterTest.scala +++ b/src/test/scala/org/scalastyle/CommentFilterTest.scala @@ -37,7 +37,7 @@ class CommentFilterTest extends AssertionsForJUnit { @Test def testOffOn(): Unit = { assertCommentFilter( - List(CommentFilter(None, Some(LineColumn(2, 0)), Some(LineColumn(3, 0)))), + List(CommentFilter(None, Some(2), Some(3))), """ // scalastyle:off // scalastyle:on""" @@ -46,7 +46,7 @@ class CommentFilterTest extends AssertionsForJUnit { @Test def testOffOnVariousWhitespace(): Unit = { assertCommentFilter( - List(CommentFilter(None, Some(LineColumn(2, 0)), Some(LineColumn(3, 1)))), + List(CommentFilter(None, Some(2), Some(3))), """ // scalastyle:off // scalastyle:on """ @@ -56,8 +56,8 @@ class CommentFilterTest extends AssertionsForJUnit { @Test def testOffOnIds(): Unit = { assertCommentFilter( List( - CommentFilter(Some("magic.number"), Some(LineColumn(2, 0)), Some(LineColumn(4, 0))), - CommentFilter(Some("class.name"), Some(LineColumn(3, 0)), Some(LineColumn(5, 1))) + CommentFilter(Some("magic.number"), Some(2), Some(4)), + CommentFilter(Some("class.name"), Some(3), Some(5)) ), """ // scalastyle:off magic.number @@ -70,9 +70,9 @@ class CommentFilterTest extends AssertionsForJUnit { @Test def testOffOnMultipleIds(): Unit = { assertCommentFilter( List( - CommentFilter(Some("magic.number"), Some(LineColumn(2, 0)), Some(LineColumn(4, 0))), - CommentFilter(Some("class.name"), Some(LineColumn(3, 0)), Some(LineColumn(5, 1))), - CommentFilter(Some("object.name"), Some(LineColumn(2, 0)), None) + CommentFilter(Some("magic.number"), Some(2), Some(4)), + CommentFilter(Some("class.name"), Some(3), Some(5)), + CommentFilter(Some("object.name"), Some(2), None) ), """ // scalastyle:off magic.number object.name @@ -85,9 +85,9 @@ class CommentFilterTest extends AssertionsForJUnit { @Test def testOffOnOpenEnds(): Unit = { assertCommentFilter( List( - CommentFilter(Some("magic.number"), Some(LineColumn(2, 0)), Some(LineColumn(3, 0))), - CommentFilter(Some("object.name"), Some(LineColumn(5, 1)), None), - CommentFilter(Some("class.name"), Some(LineColumn(2, 0)), None) + CommentFilter(Some("magic.number"), Some(2), Some(3)), + CommentFilter(Some("object.name"), Some(5), None), + CommentFilter(Some("class.name"), Some(2), None) ), """ // scalastyle:off magic.number class.name @@ -105,9 +105,9 @@ class CommentFilterTest extends AssertionsForJUnit { some code // scalastyle:ignore """ val expected = List( - CommentFilter(None, Some(LineColumn(2, 0)), Some(LineColumn(3, 0))), - CommentFilter(Some("test"), Some(LineColumn(3, 0)), Some(LineColumn(4, 0))), - CommentFilter(None, Some(LineColumn(4, 0)), Some(LineColumn(5, 0))) + CommentFilter(None, Some(2), Some(3)), + CommentFilter(Some("test"), Some(3), Some(4)), + CommentFilter(None, Some(4), Some(5)) ) assertCommentFilter(expected, source) } @@ -120,10 +120,10 @@ some code // scalastyle:ignore // scalastyle:off magic.number """ val expected = List( - CommentFilter(Some("magic.number"), Some(LineColumn(3, 0)), Some(LineColumn(4, 0))), - CommentFilter(Some("magic.number"), Some(LineColumn(5, 0)), Some(LineColumn(6, 0))), - CommentFilter(Some("magic.number"), Some(LineColumn(2, 0)), Some(LineColumn(4, 0))), - CommentFilter(Some("magic.number"), Some(LineColumn(6, 0)), None) + CommentFilter(Some("magic.number"), Some(3), Some(4)), + CommentFilter(Some("magic.number"), Some(5), Some(6)), + CommentFilter(Some("magic.number"), Some(2), Some(4)), + CommentFilter(Some("magic.number"), Some(6), None) ) assertCommentFilter(expected, source) } @@ -150,13 +150,13 @@ class foobar { } """ val expected = List( - CommentFilter(Some("class.name"), Some(LineColumn(6, 0)), Some(LineColumn(7, 0))), - CommentFilter(None, Some(LineColumn(10, 0)), Some(LineColumn(11, 0))), - CommentFilter(Some("class.name"), Some(LineColumn(14, 0)), Some(LineColumn(15, 0))), - CommentFilter(Some("magic.number"), Some(LineColumn(18, 0)), Some(LineColumn(19, 0))), - CommentFilter(None, Some(LineColumn(11, 2)), Some(LineColumn(13, 2))), - CommentFilter(None, Some(LineColumn(15, 2)), Some(LineColumn(17, 2))), - CommentFilter(None, Some(LineColumn(19, 2)), None) + CommentFilter(Some("class.name"), Some(6), Some(7)), + CommentFilter(None, Some(10), Some(11)), + CommentFilter(Some("class.name"), Some(14), Some(15)), + CommentFilter(Some("magic.number"), Some(18), Some(19)), + CommentFilter(None, Some(11), Some(13)), + CommentFilter(None, Some(15), Some(17)), + CommentFilter(None, Some(19), None) ) assertCommentFilter(expected, source) } diff --git a/src/test/scala/org/scalastyle/SourceFileParserTest.scala b/src/test/scala/org/scalastyle/SourceFileParserTest.scala index ac2a5525..31ceb76c 100644 --- a/src/test/scala/org/scalastyle/SourceFileParserTest.scala +++ b/src/test/scala/org/scalastyle/SourceFileParserTest.scala @@ -28,11 +28,11 @@ class SourceFileParserTest extends AssertionsForJUnit { def parseEmptyFile(): Unit = { val configPath = "src/test/resources/config/scalastyle_config.xml" val config = ScalastyleConfiguration.readFromXml(configPath) - val checks = config.checks.filter(_.enabled) val sourcePath = new File("src/test/resources/testfiles/EmptyClass.scala") val sourceFile = new DirectoryFileSpec(sourcePath.getAbsolutePath(), encoding = None, sourcePath.getAbsoluteFile()) - val msgs = new CheckerUtils().verifyFile(config, checks, sourceFile) + val utils = new CheckerUtils() + val msgs = utils.verifyFile(config, utils.createChecks(config), sourceFile) assertEquals(Nil, msgs) } } diff --git a/src/test/scala/org/scalastyle/file/CheckerTest.scala b/src/test/scala/org/scalastyle/file/CheckerTest.scala index 49957782..e9fc43a4 100644 --- a/src/test/scala/org/scalastyle/file/CheckerTest.scala +++ b/src/test/scala/org/scalastyle/file/CheckerTest.scala @@ -48,9 +48,12 @@ trait CheckerTest { ConfigurationChecker(classUnderTest.getName(), WarningLevel, true, params, customMessage, customId) ) val configuration = ScalastyleConfiguration("", commentFilter, classes) + val utils = new CheckerUtils() + val checks = utils.createChecks(configuration) + def sort(vals: Seq[Message[_]]): String = vals.map(_.toString).sorted.mkString("\n") assertEquals( - expected.mkString("\n"), - new CheckerUtils().verifySource(configuration, classes, NullFileSpec, source).mkString("\n") + sort(expected), + sort(utils.verifySource(configuration, checks, NullFileSpec, source)) ) } diff --git a/src/test/scala/org/scalastyle/scalariform/ClassNamesCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/ClassNamesCheckerTest.scala index 91bd6ce5..d7730f3a 100644 --- a/src/test/scala/org/scalastyle/scalariform/ClassNamesCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/ClassNamesCheckerTest.scala @@ -398,10 +398,10 @@ class FieldNamesCheckerTest extends AssertionsForJUnit with CheckerTest { |class foobar { | val myField1 = "one" | var myField2 = 2 - | val myField3 - | var myField4 - | val myField51; val myField52 = 52 - | var myField61; var myField62 = 62 + | val myField3 = 3 + | var myField4 = 4 + | val myField51 = 51; val myField52 = 52 + | var myField61 = 61; var myField62 = 62 |} """.stripMargin @@ -416,10 +416,10 @@ class FieldNamesCheckerTest extends AssertionsForJUnit with CheckerTest { |class foobar { | val MyField1 = "one" | var MyField2 = 2 - | val MyField3 - | var MyField4 - | val myField51; val MyField52 = 52 - | var myField61; var MyField62 = 62 + | val MyField3 = 3 + | var MyField4 = 4 + | val my51 = 51; val MyField52 = 52 + | var my61 = 61; var MyField62 = 62 |} """.stripMargin @@ -437,19 +437,23 @@ class FieldNamesCheckerTest extends AssertionsForJUnit with CheckerTest { } @Test def testDestructuring(): Unit = { - val source = """val (a, b, c) = f() + val source = """class a { + |val (a, b, c) = f() |val Case(a, Case(b, c)) = ff() + |} """.stripMargin - val badSource = """val (a, B, c) = f() + val badSource = """class a { + |val (a, B, c) = f() |val Case(Aa, Case(A, B())) = ff() + |} """.stripMargin assertErrors(List(), source) assertErrors( List( - columnError(1, 8, List("^[a-z][A-Za-z0-9]*$")), - columnError(2, 9, List("^[a-z][A-Za-z0-9]*$")), - columnError(2, 18, List("^[a-z][A-Za-z0-9]*$")) + columnError(2, 8, List("^[a-z][A-Za-z0-9]*$")), + columnError(3, 9, List("^[a-z][A-Za-z0-9]*$")), + columnError(3, 18, List("^[a-z][A-Za-z0-9]*$")) ), badSource ) @@ -457,19 +461,21 @@ class FieldNamesCheckerTest extends AssertionsForJUnit with CheckerTest { @Test def testDestructuringWithTypesOK(): Unit = { val source = - """val (foo: Foo, bar: Bar) = baz - |""".stripMargin + """class a { + |val (foo: Foo, bar: Bar) = baz + |}""".stripMargin assertErrors(List(), source) } @Test def testDestructuringWithTypesKO(): Unit = { val source = - """val (BBB: Foo, AAA: Bar) = baz - |""".stripMargin + """class a { + |val (b_bb: Foo, a_aa: Bar) = baz + |}""".stripMargin assertErrors( - List(columnError(1, 5, List("^[a-z][A-Za-z0-9]*$")), columnError(1, 15, List("^[a-z][A-Za-z0-9]*$"))), + List(columnError(2, 5, List("^[a-z][A-Za-z0-9]*$")), columnError(2, 16, List("^[a-z][A-Za-z0-9]*$"))), source ) } diff --git a/src/test/scala/org/scalastyle/scalariform/CovariantEqualsCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/CovariantEqualsCheckerTest.scala index daf07a83..b0b0b6af 100644 --- a/src/test/scala/org/scalastyle/scalariform/CovariantEqualsCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/CovariantEqualsCheckerTest.scala @@ -48,7 +48,7 @@ class CovariantEqualsNoObjectKO { } """ - assertErrors(List(columnError(4, 6)), source) + assertErrors(List(columnError(5, 6)), source) } @Test def testObjectOK(): Unit = { @@ -73,6 +73,6 @@ object CovariantEqualsNoObjectKO { } """ - assertErrors(List(columnError(4, 7)), source) + assertErrors(List(columnError(5, 6)), source) } } diff --git a/src/test/scala/org/scalastyle/scalariform/CyclomaticComplexityCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/CyclomaticComplexityCheckerTest.scala index 0151197f..8b349b83 100644 --- a/src/test/scala/org/scalastyle/scalariform/CyclomaticComplexityCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/CyclomaticComplexityCheckerTest.scala @@ -39,6 +39,7 @@ class Foobar { 5 match { case 4 => case 5 => + case 6 => case _ => } } else { @@ -49,7 +50,6 @@ class Foobar { 3 } } - def barbar(i: Int): Int = { if (i == 1) { 5 @@ -64,7 +64,8 @@ class Foobar { var f = 0 while (f > 0) {} do {} while (f > 0) - for (t <- List()) + for (t <- List()) {} + for (t <- List()) yield {} 3 } } @@ -118,7 +119,7 @@ class Foobar { """ assertErrors( - List(columnError(5, 6, List("4", "3")), columnError(21, 6, List("4", "3"))), + List(columnError(5, 6, List("4", "3")), columnError(23, 8, List("4", "3"))), source, Map("maximum" -> "3") ) diff --git a/src/test/scala/org/scalastyle/scalariform/EmptyInterpolatedStringCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/EmptyInterpolatedStringCheckerTest.scala index fb72d94e..1cce6c7a 100644 --- a/src/test/scala/org/scalastyle/scalariform/EmptyInterpolatedStringCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/EmptyInterpolatedStringCheckerTest.scala @@ -57,7 +57,7 @@ class Foobar { val foo = s"foo" } """ - assertErrors(List(columnError(5, 13)), source) + assertErrors(List(columnError(5, 12)), source) } @Test def testMultiple(): Unit = { @@ -70,7 +70,7 @@ class Foobar { val baz = s" baz " } """ - assertErrors(List(columnError(5, 13), columnError(6, 13), columnError(7, 13)), source) + assertErrors(List(columnError(5, 12), columnError(6, 12), columnError(7, 12)), source) } @Test def testMix(): Unit = { @@ -84,7 +84,7 @@ class Foobar { val baz = s" baz " } """ - assertErrors(List(columnError(5, 13), columnError(6, 13), columnError(8, 13)), source) + assertErrors(List(columnError(5, 12), columnError(6, 12), columnError(8, 12)), source) } @Test def testRaw(): Unit = { @@ -96,7 +96,7 @@ class Foobar { val bar = raw"test" } """ - assertErrors(List(columnError(5, 13)), source) + assertErrors(List(columnError(5, 12)), source) } } diff --git a/src/test/scala/org/scalastyle/scalariform/EqualsHashCodeCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/EqualsHashCodeCheckerTest.scala index d3e13443..af9ffd40 100644 --- a/src/test/scala/org/scalastyle/scalariform/EqualsHashCodeCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/EqualsHashCodeCheckerTest.scala @@ -48,7 +48,7 @@ class HashCodeOnlyKO { } """ - assertErrors(List(columnError(4, 6)), source) + assertErrors(List(columnError(5, 6)), source) } @Test def testEqualsOnlyKO(): Unit = { @@ -60,7 +60,7 @@ class EqualsOnlyKO { } """ - assertErrors(List(columnError(4, 6)), source) + assertErrors(List(columnError(5, 6)), source) } @Test def testEqualsOnlyAnyKO(): Unit = { @@ -72,7 +72,7 @@ class EqualsOnlyKO { } """ - assertErrors(List(columnError(4, 6)), source) + assertErrors(List(columnError(5, 6)), source) } @Test def testEqualsWrongSignatureOK(): Unit = { @@ -112,7 +112,7 @@ class OuterKO { } """ - assertErrors(List(columnError(4, 6), columnError(6, 8)), source) + assertErrors(List(columnError(5, 6), columnError(7, 8)), source) } @Test def testOuterOKInnerKO(): Unit = { @@ -128,7 +128,7 @@ class OuterOK { } """ - assertErrors(List(columnError(6, 8)), source) + assertErrors(List(columnError(7, 8)), source) } @Test def testObjectInnerKO(): Unit = { @@ -142,7 +142,7 @@ object Object { } """ - assertErrors(List(columnError(5, 8)), source) + assertErrors(List(columnError(6, 8)), source) } @Test def testMultipleClasses(): Unit = { @@ -158,6 +158,6 @@ class Class2 { } """ - assertErrors(List(columnError(4, 6), columnError(8, 6)), source) + assertErrors(List(columnError(5, 6), columnError(9, 6)), source) } } diff --git a/src/test/scala/org/scalastyle/scalariform/ImportsCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/ImportsCheckerTest.scala index 7413f27b..00567c2e 100644 --- a/src/test/scala/org/scalastyle/scalariform/ImportsCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/ImportsCheckerTest.scala @@ -313,7 +313,7 @@ class ImportOrderCheckerTest extends AssertionsForJUnit with CheckerTest { val expected = List( columnError( 3, - 0, + 7, errorKey = errorKey("wrongOrderInGroup"), args = List("foobar.Bar", "foobar.subpackage.Foo") ) @@ -329,7 +329,7 @@ class ImportOrderCheckerTest extends AssertionsForJUnit with CheckerTest { """.stripMargin val expected = List( - columnError(3, 21, errorKey = errorKey("wrongOrderInSelector"), args = List("Files", "Paths")) + columnError(3, 22, errorKey = errorKey("wrongOrderInSelector"), args = List("Files", "Paths")) ) assertErrors(expected, source, params = params) @@ -361,22 +361,22 @@ class ImportOrderCheckerTest extends AssertionsForJUnit with CheckerTest { """.stripMargin val expected = List( - columnError(5, 20, errorKey = errorKey("wrongOrderInSelector"), args = List("Cipher", "Mac")), - columnError(6, 0, errorKey = errorKey("wrongOrderInGroup"), args = List("java.lang.", "javax.crypto.")), - columnError(6, 17, errorKey = errorKey("wrongOrderInSelector"), args = List("Boolean", "Long")), - columnError(7, 0, errorKey = errorKey("wrongOrderInGroup"), args = List("java.lang._", "java.lang.")), - columnError(9, 0, errorKey = errorKey("noEmptyLine")), - columnError(10, 0, errorKey = errorKey("missingEmptyLine"), args = List("java", "scala")), + columnError(5, 21, errorKey = errorKey("wrongOrderInSelector"), args = List("Cipher", "Mac")), + columnError(6, 7, errorKey = errorKey("wrongOrderInGroup"), args = List("java.lang.", "javax.crypto.")), + columnError(6, 18, errorKey = errorKey("wrongOrderInSelector"), args = List("Boolean", "Long")), + columnError(7, 7, errorKey = errorKey("wrongOrderInGroup"), args = List("java.lang._", "java.lang.")), + columnError(9, 7, errorKey = errorKey("noEmptyLine")), + columnError(10, 7, errorKey = errorKey("missingEmptyLine"), args = List("java", "scala")), columnError( 14, - 0, + 7, errorKey = errorKey("wrongOrderInGroup"), args = List("my.org.project1.MyClass", "org.apache.Foo") ), - columnError(18, 0, errorKey = errorKey("tooManyEmptyLines"), args = List("2", "others", "project2")), + columnError(18, 7, errorKey = errorKey("tooManyEmptyLines"), args = List("2", "others", "project2")), columnError( 19, - 0, + 7, errorKey = errorKey("wrongGroup"), args = List("javax.swing.JTree", "java", "project2") ) @@ -418,55 +418,55 @@ class ImportOrderCheckerTest extends AssertionsForJUnit with CheckerTest { """.stripMargin val expected = List( - columnError(5, 20, errorKey = errorKey("wrongOrderInSelector"), args = List("Cipher", "Mac")), + columnError(5, 21, errorKey = errorKey("wrongOrderInSelector"), args = List("Cipher", "Mac")), columnError( 6, - 0, + 7, errorKey = errorKey("wrongOrderInGroup"), args = List("java.lang.{Long=>JLong,Boolean=>JBoolean}", "javax.crypto.{Mac,Cipher}") ), - columnError(6, 17, errorKey = errorKey("wrongOrderInSelector"), args = List("Boolean", "Long")), + columnError(6, 18, errorKey = errorKey("wrongOrderInSelector"), args = List("Boolean", "Long")), columnError( 7, - 0, + 7, errorKey = errorKey("wrongOrderInGroup"), args = List("java.lang._", "java.lang.{Long=>JLong,Boolean=>JBoolean}") ), - columnError(9, 0, errorKey = errorKey("noEmptyLine")), - columnError(10, 0, errorKey = errorKey("missingEmptyLine"), args = List("java", "scala")), + columnError(9, 7, errorKey = errorKey("noEmptyLine")), + columnError(10, 7, errorKey = errorKey("missingEmptyLine"), args = List("java", "scala")), columnError( 14, - 0, + 7, errorKey = errorKey("wrongOrderInGroup"), args = List("my.org.project1.MyClass", "org.apache.Foo") ), columnError( 16, - 0, + 7, errorKey = errorKey("wrongOrderInGroup"), args = List("my.org.project3.SomeClass", "my.org.project3.Someclass") ), columnError( 20, - 0, + 7, errorKey = errorKey("wrongGroup"), args = List("javax.swing.JTree", "java", "project2") ), columnError( 22, - 0, + 7, errorKey = errorKey("wrongOrderInGroup"), args = List("my.org.project2.xyz.Abc", "my.org.project2.xyz.{Aaa=>Bba}") ), columnError( 24, - 0, + 7, errorKey = errorKey("wrongOrderInGroup"), args = List("my.org.project2.xyz.{Aab=>Bbb}", "my.org.project2.xyz.{Aac=>Bbc}") ), columnError( 25, - 0, + 7, errorKey = errorKey("wrongOrderInGroup"), args = List("my.org.project2.xyz._", "my.org.project2.xyz.{Aab=>Bbb}") ) diff --git a/src/test/scala/org/scalastyle/scalariform/LowercasePatternMatchCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/LowercasePatternMatchCheckerTest.scala index 85272767..226d95d7 100644 --- a/src/test/scala/org/scalastyle/scalariform/LowercasePatternMatchCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/LowercasePatternMatchCheckerTest.scala @@ -42,7 +42,7 @@ class F1 { } """ - assertErrors(List(), source) + assertErrors(List(columnError(10, 14), columnError(10, 17)), source) } @Test def testKO(): Unit = { @@ -61,6 +61,6 @@ class F1 { } """ - assertErrors(List(columnError(11, 9)), source) + assertErrors(List(columnError(10, 14), columnError(10, 17), columnError(11, 9)), source) } } diff --git a/src/test/scala/org/scalastyle/scalariform/MethodLengthCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/MethodLengthCheckerTest.scala index c2145fc8..0a49100a 100644 --- a/src/test/scala/org/scalastyle/scalariform/MethodLengthCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/MethodLengthCheckerTest.scala @@ -88,10 +88,23 @@ class F2() { 4 (7) 5 (8) } + def method3() = { + 1 + 2 + /** (3) + * (4) + */ (5) + 3 (6) + 4 (7) + } } """ - assertErrors(List(), source, Map("maxLength" -> "5", "ignoreComments" -> "true")) + assertErrors( + List(columnError(5, 6, List("6 > 5"))), + source, + Map("maxLength" -> "5", "ignoreComments" -> "true") + ) } @Test def testIgnoreEmpty(): Unit = { @@ -140,7 +153,11 @@ class F2() { } """ - assertErrors(List(columnError(5, 6, List("4"))), source, Map("maxLength" -> "4", "ignoreEmpty" -> "true")) + assertErrors( + List(columnError(5, 6, List("5 > 4"))), + source, + Map("maxLength" -> "4", "ignoreEmpty" -> "true") + ) } @Test def testIgnoreEmptyAndComments(): Unit = { @@ -173,10 +190,29 @@ class F2() { 5 (12) } + def method3() = { + + 1 (2) + 2 (3) + // (4) + + 3 (6) + 4 (7) + /** (8) + * (9) + */ + + 5 (12) + + } } """ - assertErrors(List(), source, Map("maxLength" -> "5", "ignoreComments" -> "true", "ignoreEmpty" -> "true")) + assertErrors( + List(columnError(14, 6, List("6 > 5"))), + source, + Map("maxLength" -> "5", "ignoreComments" -> "true", "ignoreEmpty" -> "true") + ) } @Test def testNotIgnoreComments(): Unit = { @@ -205,7 +241,7 @@ class F2() { """ assertErrors( - List(columnError(5, 6, List("5")), columnError(13, 6, List("5"))), + List(columnError(5, 6, List("6 > 5")), columnError(13, 6, List("6 > 5"))), source, Map("maxLength" -> "5", "ignoreComments" -> "false") ) @@ -214,6 +250,7 @@ class F2() { @Test def testIgnoreCommentsComplicated(): Unit = { val source = """ class F3() { + def method1() = { 1 // (2) /* */ @@ -222,9 +259,8 @@ class F3() { (4) /* * (5) */ (6) - 4 (7) - 5 (8) } + def method2() = { // /* (1) 1 (2) @@ -234,10 +270,34 @@ class F3() { 5 (7) 6 (8) } + + def method3() = { + 1 // + (2) /* */ + 2 + 3 + (4) /* + * (5) + */ (6) + 4 (7) + } + + def method4() = { + // /* (1) + 1 (2) + 2 (3) + 3 (5) + 4 (6) + 5 (7) + } } """ assertErrors( - List(columnError(14, 6, List("5"))), + List( + columnError(4, 6, List("6 > 5")), + columnError(14, 6, List("6 > 5")), + columnError(24, 6, List("7 > 5")) + ), source, Map("maxLength" -> "5", "ignoreComments" -> "true") ) diff --git a/src/test/scala/org/scalastyle/scalariform/NamedArgumentCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/NamedArgumentCheckerTest.scala index 61b19e61..36e26635 100644 --- a/src/test/scala/org/scalastyle/scalariform/NamedArgumentCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/NamedArgumentCheckerTest.scala @@ -9,55 +9,59 @@ class NamedArgumentCheckerTest extends AssertionsForJUnit with CheckerTest { val classUnderTest = classOf[NamedArgumentChecker] @Test def testDefault(): Unit = { - val source = """b(b = true) + val source = """object a { + |b(b = true) |i(i = 1) |l(l = 1L) |f(f = 1.2) |c(c = 'a') |n(n = null) - """.stripMargin - val badSource = """b(true) + }""".stripMargin + val badSource = """object a { + |b(true) |i(1) |l(1L) |f(1.2) |c('a') |n(null) - """.stripMargin + }""".stripMargin assertErrors(List.empty, source) assertErrors( List( - columnError(1, 2), columnError(2, 2), columnError(3, 2), columnError(4, 2), columnError(5, 2), - columnError(6, 2) + columnError(6, 2), + columnError(7, 2) ), badSource ) } @Test def testString(): Unit = { - val source = """s1(s = "abc") + val source = """object a { + |s1(s = "abc") |s2(s = s"a$bc") - """.stripMargin - val badSource = """s1("abc") + }""".stripMargin + val badSource = """object a { + |s1("abc") |s2(s"a${b}c") - """.stripMargin + }""".stripMargin assertErrors(List.empty, source, Map("checkString" -> "true")) - assertErrors(List(columnError(1, 3), columnError(2, 3)), badSource, Map("checkString" -> "true")) + assertErrors(List(columnError(2, 3), columnError(3, 3)), badSource, Map("checkString" -> "true")) } @Test def testIgnore(): Unit = { - val source1 = """setF(1)""" - val source2 = """f(1)""" + val source1 = """object a { setF(1) }""" + val source2 = """object a { f(1) }""" assertErrors(List.empty, source1) - assertErrors(List(columnError(1, 2)), source2) + assertErrors(List(columnError(1, 13)), source2) - assertErrors(List(columnError(1, 5)), source1, Map("ignoreMethod" -> "^f$")) + assertErrors(List(columnError(1, 16)), source1, Map("ignoreMethod" -> "^f$")) assertErrors(List.empty, source2, Map("ignoreMethod" -> "^f$")) } diff --git a/src/test/scala/org/scalastyle/scalariform/NoCloneCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/NoCloneCheckerTest.scala index f5489389..1bb572bd 100644 --- a/src/test/scala/org/scalastyle/scalariform/NoCloneCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/NoCloneCheckerTest.scala @@ -47,7 +47,7 @@ class CloneKO { } """ - assertErrors(List(columnError(4, 6)), source) + assertErrors(List(columnError(5, 6)), source) } @Test def testObjectOK(): Unit = { @@ -71,6 +71,6 @@ object CloneKO { } """ - assertErrors(List(columnError(4, 7)), source) + assertErrors(List(columnError(5, 6)), source) } } diff --git a/src/test/scala/org/scalastyle/scalariform/NoFinalizeCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/NoFinalizeCheckerTest.scala index df5263d2..4a45c355 100644 --- a/src/test/scala/org/scalastyle/scalariform/NoFinalizeCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/NoFinalizeCheckerTest.scala @@ -47,7 +47,7 @@ class CloneKO { } """ - assertErrors(List(columnError(4, 6)), source) + assertErrors(List(columnError(5, 6)), source) } @Test def testObjectOK(): Unit = { @@ -71,6 +71,6 @@ object CloneKO { } """ - assertErrors(List(columnError(4, 7)), source) + assertErrors(List(columnError(5, 6)), source) } } diff --git a/src/test/scala/org/scalastyle/scalariform/NoWhitespaceBracketCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/NoWhitespaceBracketCheckerTest.scala index 44286376..c0881307 100644 --- a/src/test/scala/org/scalastyle/scalariform/NoWhitespaceBracketCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/NoWhitespaceBracketCheckerTest.scala @@ -44,7 +44,7 @@ package foobar class Foobar [T] { } """ - assertErrors(List(columnError(4, 6)), source) + assertErrors(List(columnError(4, 13)), source) } @Test def testTwoSpaces(): Unit = { @@ -55,7 +55,7 @@ class Foobar [ Barbar [T]] { } """ - assertErrors(List(columnError(4, 6), columnError(4, 15)), source) + assertErrors(List(columnError(4, 13), columnError(4, 22)), source) } } diff --git a/src/test/scala/org/scalastyle/scalariform/NonASCIICharacterCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/NonASCIICharacterCheckerTest.scala index 8dbf4d55..554abab7 100644 --- a/src/test/scala/org/scalastyle/scalariform/NonASCIICharacterCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/NonASCIICharacterCheckerTest.scala @@ -70,7 +70,7 @@ class NonASCIICharacterCheckerTest extends AssertionsForJUnit with CheckerTest { |} | """.stripMargin - assertErrors(List(columnError(2, 14), columnError(5, 6), columnError(6, 6)), source) + assertErrors(List(columnError(3, 0), columnError(5, 6), columnError(6, 6)), source) } @Test def testStringNotOK(): Unit = { diff --git a/src/test/scala/org/scalastyle/scalariform/ProcedureDeclarationCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/ProcedureDeclarationCheckerTest.scala index a781be63..7942cf4c 100644 --- a/src/test/scala/org/scalastyle/scalariform/ProcedureDeclarationCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/ProcedureDeclarationCheckerTest.scala @@ -46,7 +46,7 @@ abstract class OK { val foo: Unit = new scala.collection.mutable.HashMap {def foobar() = {}} def bar() = { new scala.collection.mutable.HashMap {def foobar() = {}} } def bar2() = new scala.collection.mutable.HashMap {def foobar2() = {}} - val bar3 + val bar3: String } """ diff --git a/src/test/scala/org/scalastyle/scalariform/ScalaDocCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/ScalaDocCheckerTest.scala index f9f10e41..4b2fcb56 100644 --- a/src/test/scala/org/scalastyle/scalariform/ScalaDocCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/ScalaDocCheckerTest.scala @@ -82,7 +82,7 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { assertErrors(Nil, source format doc) assertErrors(List(lineError(1, List(Missing))), source format "") assertErrors( - List(lineError(5, List(missingParam("a"))), lineError(5, List(missingParam("b")))), + List(lineError(2, List(missingParam("a"))), lineError(2, List(missingParam("b")))), source format missingParamDoc ) } @@ -129,7 +129,7 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { List(traitSource, classSource, caseClassSource).foreach { source => assertErrors(Nil, source format doc) assertErrors(List(lineError(1, List(Missing))), source format "") - assertErrors(List(lineError(5, List(MalformedTypeParams))), source format malformedDoc) + assertErrors(List(lineError(2, List(MalformedTypeParams))), source format malformedDoc) } } @@ -155,7 +155,7 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { assertErrors(Nil, doc + source) assertErrors(List(lineError(1, List(Missing))), source) - assertErrors(List(lineError(5, List(MalformedTypeParams))), malformedDoc + source) + assertErrors(List(lineError(2, List(MalformedTypeParams))), malformedDoc + source) } @Test def publicMethodWithEverything(): Unit = { @@ -246,15 +246,15 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { assertErrors(Nil, source format doc(false)) assertErrors(if (checked) List(lineError(6, List(Missing))) else Nil, source format "") assertErrors( - if (checked) List(lineError(15, List(missingParam("b")))) else Nil, + if (checked) List(lineError(7, List(missingParam("b")))) else Nil, source format missingParamsDoc(false) ) assertErrors( - if (checked) List(lineError(15, List(MalformedTypeParams))) else Nil, + if (checked) List(lineError(7, List(MalformedTypeParams))) else Nil, source format missingTypeParamsDoc(false) ) assertErrors( - if (checked) List(lineError(15, List(MalformedReturn))) else Nil, + if (checked) List(lineError(7, List(MalformedReturn))) else Nil, source format missingReturnDoc ) } @@ -263,11 +263,11 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { assertErrors(Nil, source format doc(false)) assertErrors(if (checked) List(lineError(6, List(Missing))) else Nil, source format "") assertErrors( - if (checked) List(lineError(14, List(missingParam("b")))) else Nil, + if (checked) List(lineError(7, List(missingParam("b")))) else Nil, source format missingParamsDoc(true) ) assertErrors( - if (checked) List(lineError(14, List(MalformedTypeParams))) else Nil, + if (checked) List(lineError(7, List(MalformedTypeParams))) else Nil, source format missingTypeParamsDoc(true) ) } @@ -317,7 +317,7 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { |} """.stripMargin - assertErrors(List(lineError(22, List(emptyParam("c")))), source) + assertErrors(List(lineError(7, List(emptyParam("c")))), source) } @Test def valsVarsAndTypes(): Unit = { @@ -328,10 +328,10 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { | * Top-level doc | */ """.stripMargin - def source(container: String) = + def source(container: String, args: String = "") = s""" |$tlDoc - |$container Foo { + |$container Foo $args { | %s${what} |} """.stripMargin @@ -342,7 +342,7 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { | */ """.stripMargin - List(source("class"), source("case class"), source("object ")).foreach { source => + List(source("class"), source("case class", "()"), source("object ")).foreach { source => assertErrors(Nil, source format doc) assertErrors(if (checked) List(lineError(8, List(Missing))) else Nil, source format "") } @@ -421,7 +421,7 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { val cases = Seq( Seq("val a = 1", "var a = 2") -> "PatDefOrDcl", - Seq("class A", "case class A", "object A", "trait A") -> "TmplDef", + Seq("class A", "case class A()", "object A", "trait A") -> "TmplDef", Seq("type B = A") -> "TypeDefOrDcl", Seq("def A(): Unit") -> "FunDefOrDcl" ) @@ -429,7 +429,11 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { for { (declerations, ignoreTokenType) <- cases decleration <- declerations - } assertErrors(Nil, decleration, Map("ignoreTokenTypes" -> ignoreTokenType)) + } assertErrors( + Nil, + s"/** */ object a { $decleration }", + Map("ignoreTokenTypes" -> ignoreTokenType) + ) } @Test def ignoreOverridden(): Unit = { @@ -456,8 +460,8 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { class c""" assertErrors(List.empty, source) - assertErrors(List(lineError(5, List(InvalidDocStyle))), source, Map("indentStyle" -> "scaladoc")) - assertErrors(List(lineError(5, List(InvalidDocStyle))), source, Map("indentStyle" -> "javadoc")) + assertErrors(List(lineError(2, List(InvalidDocStyle))), source, Map("indentStyle" -> "scaladoc")) + assertErrors(List(lineError(2, List(InvalidDocStyle))), source, Map("indentStyle" -> "javadoc")) } @Test def indentStyleScaladoc(): Unit = { @@ -469,7 +473,7 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { assertErrors(List.empty, source) assertErrors(List.empty, source, Map("indentStyle" -> "scaladoc")) - assertErrors(List(lineError(5, List(InvalidDocStyle))), source, Map("indentStyle" -> "javadoc")) + assertErrors(List(lineError(2, List(InvalidDocStyle))), source, Map("indentStyle" -> "javadoc")) } @Test def indentStyleJavadoc(): Unit = { @@ -480,7 +484,7 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { class c""" assertErrors(List.empty, source) - assertErrors(List(lineError(5, List(InvalidDocStyle))), source, Map("indentStyle" -> "scaladoc")) + assertErrors(List(lineError(2, List(InvalidDocStyle))), source, Map("indentStyle" -> "scaladoc")) assertErrors(List.empty, source, Map("indentStyle" -> "javadoc")) } @@ -495,7 +499,8 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { | implicit def test = 1 | } """.stripMargin - assertErrors(List.empty, sourceScalaDoc, Map("indentStyle" -> "scaladoc")) + assertErrors(List(lineError(2, List(Missing))), sourceScalaDoc, Map("indentStyle" -> "scaladoc")) + assertErrors(List.empty, s"/** */ $sourceScalaDoc", Map("indentStyle" -> "scaladoc")) val sourceJavaDoc = """ @@ -506,7 +511,7 @@ class ScalaDocCheckerTest extends AssertionsForJUnit with CheckerTest { | implicit def test = 1 | } """.stripMargin - - assertErrors(List.empty, sourceJavaDoc, Map("indentStyle" -> "javadoc")) + assertErrors(List(lineError(2, List(Missing))), sourceJavaDoc, Map("indentStyle" -> "javadoc")) + assertErrors(List.empty, s"/** */ $sourceJavaDoc", Map("indentStyle" -> "javadoc")) } } diff --git a/src/test/scala/org/scalastyle/scalariform/SimplifyBooleanExpressionCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/SimplifyBooleanExpressionCheckerTest.scala index b57d1a8e..8fe5bbb3 100644 --- a/src/test/scala/org/scalastyle/scalariform/SimplifyBooleanExpressionCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/SimplifyBooleanExpressionCheckerTest.scala @@ -38,7 +38,7 @@ object Foobar { val foo04 = (b != false) }""" - assertErrors(List(columnError(6, 15), columnError(7, 15), columnError(8, 15), columnError(9, 15)), source) + assertErrors(List(columnError(6, 20), columnError(7, 20), columnError(8, 20), columnError(9, 20)), source) } @Test def testErrors(): Unit = { val source = """ @@ -51,7 +51,7 @@ object Foobar { val foo03 = !true }""" - assertErrors(List(columnError(6, 15), columnError(7, 14), columnError(8, 14)), source) + assertErrors(List(columnError(6, 20), columnError(7, 15), columnError(8, 15)), source) } @Test def testErrors2(): Unit = { @@ -66,7 +66,7 @@ object Foobar { val foo07 = false && b }""" - assertErrors(List(columnError(6, 14), columnError(7, 14), columnError(8, 14), columnError(9, 14)), source) + assertErrors(List(columnError(6, 19), columnError(7, 14), columnError(8, 19), columnError(9, 14)), source) } @Test def testErrors3(): Unit = { @@ -81,7 +81,7 @@ object Foobar { val foo11 = false || b }""" - assertErrors(List(columnError(6, 14), columnError(7, 14), columnError(8, 14), columnError(9, 14)), source) + assertErrors(List(columnError(6, 19), columnError(7, 14), columnError(8, 19), columnError(9, 14)), source) } @Test def testOK(): Unit = { @@ -95,6 +95,6 @@ object Foobar { val foo14 = b && (true) }""" - assertErrors(List(columnError(8, 14)), source) + assertErrors(List(columnError(8, 20)), source) } } diff --git a/src/test/scala/org/scalastyle/scalariform/TodoCommentCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/TodoCommentCheckerTest.scala index 0f1f6264..4da4d45c 100644 --- a/src/test/scala/org/scalastyle/scalariform/TodoCommentCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/TodoCommentCheckerTest.scala @@ -24,7 +24,6 @@ import org.scalatestplus.junit.AssertionsForJUnit class TodoCommentCheckerTest extends AssertionsForJUnit with CheckerTest { val key = "todo.comment" - val text = "TODO|FIXME" val classUnderTest = classOf[TodoCommentChecker] @Test def testSourceWithoutTodoComments(): Unit = { @@ -93,15 +92,15 @@ class TodoCommentCheckerTest extends AssertionsForJUnit with CheckerTest { assertErrors( List( - columnError(5, 2, List(text)), - columnError(9, 4, List(text)), - columnError(12, 2, List(text)), - columnError(15, 24, List(text)), - columnError(17, 29, List(text)), - columnError(19, 22, List(text)), - columnError(21, 2, List(text)), - columnError(26, 3, List(text)), - columnError(27, 3, List(text)) + columnError(5, 2, List("TODO")), + columnError(9, 4, List("Todo")), + columnError(12, 2, List("ToDo")), + columnError(15, 24, List("todo")), + columnError(17, 29, List("TODO")), + columnError(19, 22, List("TODO")), + columnError(21, 2, List("TODO")), + columnError(26, 3, List("TODO")), + columnError(27, 3, List("TODO")) ), source ) @@ -170,15 +169,15 @@ class TodoCommentCheckerTest extends AssertionsForJUnit with CheckerTest { assertErrors( List( - columnError(5, 2, List(text)), - columnError(9, 4, List(text)), - columnError(12, 2, List(text)), - columnError(15, 24, List(text)), - columnError(17, 29, List(text)), - columnError(19, 22, List(text)), - columnError(21, 2, List(text)), - columnError(26, 3, List(text)), - columnError(27, 3, List(text)) + columnError(5, 2, List("FIXME")), + columnError(9, 4, List("Fixme")), + columnError(12, 2, List("FixMe")), + columnError(15, 24, List("fixme")), + columnError(17, 29, List("FIXME")), + columnError(19, 22, List("FIXME")), + columnError(21, 2, List("FIXME")), + columnError(26, 3, List("FIXME")), + columnError(27, 3, List("FIXME")) ), source ) @@ -206,16 +205,15 @@ class TodoCommentCheckerTest extends AssertionsForJUnit with CheckerTest { |} """.stripMargin - val words = "fixme|afaire" assertErrors( List( - columnError(5, 2, List(words)), - columnError(9, 4, List(words)), - columnError(12, 2, List(words)), - columnError(17, 3, List(words)) + columnError(5, 2, List("AFAIRE")), + columnError(9, 4, List("afaire")), + columnError(12, 2, List("AFaire")), + columnError(17, 3, List("FIXME")) ), source, - params = Map("words" -> words) + params = Map("words" -> "fixme|afaire") ) } } diff --git a/src/test/scala/org/scalastyle/scalariform/VarFieldCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/VarFieldCheckerTest.scala index dda7c817..67854f90 100644 --- a/src/test/scala/org/scalastyle/scalariform/VarFieldCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/VarFieldCheckerTest.scala @@ -31,7 +31,7 @@ class VarFieldCheckerTest extends AssertionsForJUnit with CheckerTest { class C1 { var f1 = 1 val f2 = 1 - var f3 + var f3: Int def m1() = { var v1 = 1 v1 @@ -49,7 +49,7 @@ class C1 { v4 } def m5() = { - var v5, v6 + var v5, v6 = m2() 1 } } diff --git a/src/test/scala/org/scalastyle/scalariform/VarLocalCheckerTest.scala b/src/test/scala/org/scalastyle/scalariform/VarLocalCheckerTest.scala index 43c5366e..30f7f352 100644 --- a/src/test/scala/org/scalastyle/scalariform/VarLocalCheckerTest.scala +++ b/src/test/scala/org/scalastyle/scalariform/VarLocalCheckerTest.scala @@ -31,7 +31,7 @@ class VarLocalCheckerTest extends AssertionsForJUnit with CheckerTest { class C1 { var f1 = 1 val f2 = 1 - var f3 + var f3: Int def m1() = { var v1 = 1 v1 @@ -49,7 +49,7 @@ class C1 { v4 } def m5() = { - var v5, v6 + var v5, v6 = m2() 1 } }