Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit 810b1cb

Browse files
author
Albert Meltzer
committed
Checkers: report the failing token and offset
1 parent eb330f8 commit 810b1cb

16 files changed

+147
-144
lines changed

src/main/scala/org/scalastyle/scalariform/CyclomaticComplexityChecker.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class CyclomaticComplexityChecker extends CombinedChecker {
4949
f <- traverse(t)
5050
value = matches(f, ast.lines, maximum)
5151
if value > maximum
52-
} yield PositionError(t.position.get, List("" + value, "" + maximum))
52+
} yield PositionError(f.position.get, List("" + value, "" + maximum))
5353

5454
it
5555
}

src/main/scala/org/scalastyle/scalariform/EmptyInterpolatedStringChecker.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class EmptyInterpolatedStringChecker extends ScalariformChecker {
3030
List(left, right) <- ast.tokens.sliding(2)
3131
if left.tokenType == INTERPOLATION_ID && typesSupportingVariables.contains(left.text) &&
3232
interpolationRegex.findFirstIn(right.text).isEmpty
33-
} yield PositionError(right.offset)
33+
} yield PositionError(left.offset)
3434

3535
it.toList
3636
}

src/main/scala/org/scalastyle/scalariform/ImportsChecker.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,13 @@ class ImportOrderChecker extends ScalariformChecker {
213213
val CompilationUnit(statements, _) = ast
214214
statements.immediateChildren.flatMap { n =>
215215
val result = n match {
216-
case ImportClause(_, BlockImportExpr(prefix, selectors), _, _) =>
216+
case ImportClause(_, e @ BlockImportExpr(prefix, selectors), _, _) =>
217217
val text = exprToText(prefix.contents, if (lexicographic) selectors.tokens else Nil)
218-
checkImport(text, n.firstToken.offset) ++ checkSelectors(selectors)
218+
checkImport(text, e.firstToken.offset) ++ checkSelectors(selectors)
219219

220-
case ImportClause(_, Expr(contents), _, _) =>
220+
case ImportClause(_, e @ Expr(contents), _, _) =>
221221
val text = exprToText(contents)
222-
checkImport(text, n.firstToken.offset)
222+
checkImport(text, e.firstToken.offset)
223223

224224
case _ =>
225225
Nil
@@ -281,13 +281,13 @@ class ImportOrderChecker extends ScalariformChecker {
281281
val ImportSelectors(_, first, others, _) = selectors
282282

283283
val errors = new ListBuffer[ScalastyleError]()
284-
val names = Seq(first.contents.head.tokens.head.text) ++
285-
others.map(_._2.contents.head.tokens.head.text)
284+
val names = Seq(first.contents.head.tokens.head) ++
285+
others.map(_._2.contents.head.tokens.head)
286286

287287
if (names.size > 1) {
288288
names.sliding(2).foreach { case Seq(left, right) =>
289-
if (compareNames(left, right, isImport = false) > 0)
290-
errors += newError(selectors.firstToken.offset, "wrongOrderInSelector", right, left)
289+
if (compareNames(left.text, right.text, isImport = false) > 0)
290+
errors += newError(left.offset, "wrongOrderInSelector", right.text, left.text)
291291
}
292292
}
293293

src/main/scala/org/scalastyle/scalariform/NoWhitespaceBracketChecker.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class NoWhitespaceBeforeLeftBracketChecker extends ScalariformChecker {
3030
val it = for {
3131
List(left, right) <- ast.tokens.sliding(2)
3232
if right.tokenType == LBRACKET && charsBetweenTokens(left, right) > 0
33-
} yield PositionError(left.offset)
33+
} yield PositionError(right.offset)
3434

3535
it.toList
3636
}

src/main/scala/org/scalastyle/scalariform/NonASCIICharacterChecker.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package org.scalastyle.scalariform
1818

1919
import java.util.regex.Pattern
2020

21-
import _root_.scalariform.lexer.{Token, Tokens}
21+
import _root_.scalariform.lexer.{Comment, Token, Tokens}
2222
import _root_.scalariform.parser.CompilationUnit
2323
import org.scalastyle.PositionError
2424
import org.scalastyle.ScalariformChecker
@@ -35,7 +35,12 @@ class NonASCIICharacterChecker extends ScalariformChecker {
3535
getBoolean("allowStringLiterals", defaultAllowStringLiterals)
3636

3737
override def verify(ast: CompilationUnit): List[ScalastyleError] =
38-
ast.tokens.filter(hasNonAsciiChars).map(x => PositionError(x.offset))
38+
ast.tokens.flatMap(getTokenNonAsciiChars(_).map(PositionError(_)))
39+
40+
private def getTokenNonAsciiChars(x: Token): Option[Int] =
41+
x.associatedWhitespaceAndComments.tokens
42+
.collectFirst { case c: Comment if hasNonAsciiChars(c.token) => c.token.offset }
43+
.orElse(if (hasNonAsciiChars(x)) Some(x.offset) else None)
3944

4045
private def hasNonAsciiChars(x: Token) = {
4146
x.rawText.trim.nonEmpty &&

src/main/scala/org/scalastyle/scalariform/ScalaDocChecker.scala

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import _root_.scalariform.parser.TypeDefOrDcl
3535
import _root_.scalariform.parser.TypeParamClause
3636
import org.scalastyle.CombinedAst
3737
import org.scalastyle.CombinedChecker
38+
import org.scalastyle.LineColumn
3839
import org.scalastyle.LineError
3940
import org.scalastyle.Lines
4041
import org.scalastyle.ScalastyleError
@@ -106,28 +107,34 @@ class ScalaDocChecker extends CombinedChecker {
106107
* ``FullDefOrDcl`` -> ``PatDefOrDcl``, with the ScalaDoc attached to the ``FulDefOrDcl``, which
107108
* finds its way to us here in ``fallback``.
108109
*/
109-
private def findScalaDoc(token: Token, lines: Lines, fallback: HiddenTokens): Option[ScalaDoc] = {
110+
private def findScalaDoc(
111+
token: Token,
112+
lines: Lines,
113+
fallback: HiddenTokens
114+
)(f: ScalaDoc => List[ScalastyleError]): List[ScalastyleError] = {
110115
def toScalaDoc(ht: HiddenTokens): Option[ScalaDoc] =
111116
ht.rawTokens
112117
.find(_.isScalaDocComment)
113118
.map { commentToken =>
114-
val commentOffset = lines.toLineColumn(commentToken.offset).map(_.column).getOrElse(0)
115-
ScalaDoc.apply(commentToken, commentOffset)
119+
val lineColumn = lines.toLineColumn(commentToken.offset).getOrElse(LineColumn(0, 0))
120+
ScalaDoc(commentToken.rawText, lineColumn)
116121
}
117122

118-
toScalaDoc(token.associatedWhitespaceAndComments).orElse(toScalaDoc(fallback))
123+
toScalaDoc(token.associatedWhitespaceAndComments).orElse(toScalaDoc(fallback)).map(f).getOrElse {
124+
List(LineError(lines.toLine(token.offset).get, List(Missing)))
125+
}
119126
}
120127

121-
private def indentErrors(line: Int, style: DocIndentStyle)(scalaDoc: ScalaDoc): List[ScalastyleError] =
128+
private def indentErrors(style: DocIndentStyle)(scalaDoc: ScalaDoc): List[ScalastyleError] =
122129
if (style == AnyDocStyle || style == scalaDoc.indentStyle)
123130
Nil
124131
else if (SingleLineStyle == scalaDoc.indentStyle)
125132
Nil
126133
else
127-
List(LineError(line, List(InvalidDocStyle)))
134+
List(LineError(scalaDoc.line, List(InvalidDocStyle)))
128135

129136
// parse the parameters and report errors for the parameters (constructor or method)
130-
private def paramErrors(line: Int, paramClausesOpt: Option[ParamClauses])(
137+
private def paramErrors(paramClausesOpt: Option[ParamClauses])(
131138
scalaDoc: ScalaDoc
132139
): List[ScalastyleError] = {
133140
def params(xs: List[Token]): List[String] =
@@ -150,18 +157,16 @@ class ScalaDocChecker extends CombinedChecker {
150157
val extraScalaDocParams = scalaDoc.params.filterNot(param => paramNames.contains(param.name))
151158
val validScalaDocParams = scalaDoc.params.filter(param => paramNames.contains(param.name))
152159

160+
val line = scalaDoc.line
153161
missingScalaDocParams.map(missing => LineError(line, List(missingParam(missing)))) ++
154162
extraScalaDocParams.map(extra => LineError(line, List(extraParam(extra.name)))) ++
155163
validScalaDocParams.filter(_.text.isEmpty).map(empty => LineError(line, List(emptyParam(empty.name))))
156-
157-
// if (!scalaDoc.params.forall(p => paramNames.exists(name => p.name == name && !p.text.isEmpty))) List(LineError(line, List(MalformedParams)))
158-
// else Nil
159164
}
160165

161166
// parse the type parameters and report errors for the parameters (constructor or method)
162167
// scalastyle:off cyclomatic.complexity
163168

164-
private def tparamErrors(line: Int, tparamClausesOpt: Option[TypeParamClause])(
169+
private def tparamErrors(tparamClausesOpt: Option[TypeParamClause])(
165170
scalaDoc: ScalaDoc
166171
): List[ScalastyleError] = {
167172
def tparams(xs: List[Token], bracketDepth: Int): List[String] =
@@ -203,6 +208,7 @@ class ScalaDocChecker extends CombinedChecker {
203208

204209
val tparamNames = tparamClausesOpt.map(tc => tparams(tc.tokens, 0)).getOrElse(Nil)
205210

211+
val line = scalaDoc.line
206212
if (tparamNames.size != scalaDoc.typeParams.size)
207213
// bad param sizes
208214
List(LineError(line, List(MalformedTypeParams)))
@@ -216,13 +222,13 @@ class ScalaDocChecker extends CombinedChecker {
216222
// scalastyle:on cyclomatic.complexity
217223

218224
// parse the parameters and report errors for the return types
219-
private def returnErrors(line: Int, returnTypeOpt: Option[(Token, Type)])(
225+
private def returnErrors(returnTypeOpt: Option[(Token, Type)])(
220226
scalaDoc: ScalaDoc
221227
): List[ScalastyleError] = {
222228
val needsReturn = returnTypeOpt.exists { case (_, tpe) => tpe.firstToken.text != "Unit" }
223229

224230
if (needsReturn && scalaDoc.returns.isEmpty)
225-
List(LineError(line, List(MalformedReturn)))
231+
List(LineError(scalaDoc.line, List(MalformedReturn)))
226232
else
227233
Nil
228234
}
@@ -286,20 +292,17 @@ class ScalaDocChecker extends CombinedChecker {
286292
// class Foo, class Foo[A](a: A);
287293
// case class Foo(), case class Foo[A](a: A);
288294
// object Foo;
289-
val (_, line) = lines.findLineAndIndex(t.firstToken.offset).get
290295

291296
// we are checking parameters and type parameters
292297
val errors =
293298
if (shouldSkip(t))
294299
Nil
295300
else {
296-
findScalaDoc(t.firstToken, lines, fallback)
297-
.map { scalaDoc =>
298-
paramErrors(line, t.paramClausesOpt)(scalaDoc) ++
299-
tparamErrors(line, t.typeParamClauseOpt)(scalaDoc) ++
300-
indentErrors(line, indentStyle)(scalaDoc)
301-
}
302-
.getOrElse(List(LineError(line, List(Missing))))
301+
findScalaDoc(t.firstToken, lines, fallback) { scalaDoc =>
302+
paramErrors(t.paramClausesOpt)(scalaDoc) ++
303+
tparamErrors(t.typeParamClauseOpt)(scalaDoc) ++
304+
indentErrors(indentStyle)(scalaDoc)
305+
}
303306
}
304307

305308
// and we descend, because we're interested in seeing members of the types
@@ -309,50 +312,43 @@ class ScalaDocChecker extends CombinedChecker {
309312
)
310313
case t: FunDefOrDcl =>
311314
// def foo[A, B](a: Int): B = ...
312-
val (_, line) = lines.findLineAndIndex(t.firstToken.offset).get
313-
314315
// we are checking parameters, type parameters and returns
315316
val errors =
316317
if (shouldSkip(t))
317318
Nil
318319
else {
319-
findScalaDoc(t.firstToken, lines, fallback)
320-
.map { scalaDoc =>
321-
paramErrors(line, Some(t.paramClauses))(scalaDoc) ++
322-
tparamErrors(line, t.typeParamClauseOpt)(scalaDoc) ++
323-
returnErrors(line, t.returnTypeOpt)(scalaDoc) ++
324-
indentErrors(line, indentStyle)(scalaDoc)
325-
}
326-
.getOrElse(List(LineError(line, List(Missing))))
320+
findScalaDoc(t.firstToken, lines, fallback) { scalaDoc =>
321+
paramErrors(Some(t.paramClauses))(scalaDoc) ++
322+
tparamErrors(t.typeParamClauseOpt)(scalaDoc) ++
323+
returnErrors(t.returnTypeOpt)(scalaDoc) ++
324+
indentErrors(indentStyle)(scalaDoc)
325+
}
327326
}
328327

329328
// we don't descend any further
330329
errors
331330
case t: TypeDefOrDcl =>
332331
// type Foo = ...
333-
val (_, line) = lines.findLineAndIndex(t.firstToken.offset).get
334-
335332
// no params here
336333
val errors =
337334
if (shouldSkip(t)) Nil
338335
else
339-
findScalaDoc(t.firstToken, lines, fallback)
340-
.map(scalaDoc => indentErrors(line, indentStyle)(scalaDoc))
341-
.getOrElse(List(LineError(line, List(Missing))))
336+
findScalaDoc(t.firstToken, lines, fallback) { scalaDoc =>
337+
indentErrors(indentStyle)(scalaDoc)
338+
}
342339

343340
// we don't descend any further
344341
errors
345342

346343
case t: PatDefOrDcl =>
347344
// val a = ..., var a = ...
348-
val (_, line) = lines.findLineAndIndex(t.valOrVarToken.offset).get
349345
val errors =
350346
if (shouldSkip(t))
351347
Nil
352348
else {
353-
findScalaDoc(t.firstToken, lines, fallback)
354-
.map(scalaDoc => indentErrors(line, indentStyle)(scalaDoc))
355-
.getOrElse(List(LineError(line, List(Missing))))
349+
findScalaDoc(t.firstToken, lines, fallback) { scalaDoc =>
350+
indentErrors(indentStyle)(scalaDoc)
351+
}
356352
}
357353

358354
// we don't descend any further
@@ -440,13 +436,14 @@ object ScalaDocChecker {
440436

441437
/**
442438
* Take the ``raw`` and parse an instance of ``ScalaDoc``
443-
* @param raw the token containing the ScalaDoc
444-
* @param offset column number of scaladoc's first string
439+
* @param text the ScalaDoc text
440+
* @param lineColumn line and column number of scaladoc's first string
445441
* @return the parsed instance
446442
*/
447443
// scalastyle:off cyclomatic.complexity
448-
def apply(raw: Token, offset: Int): ScalaDoc = {
449-
val strings = raw.rawText.split("\\n").toList
444+
def apply(raw: String, lineColumn: LineColumn): ScalaDoc = {
445+
val offset = lineColumn.column
446+
val strings = raw.split("\\n").toList
450447

451448
val indentStyle = {
452449
def getStyle(xs: List[String], style: DocIndentStyle): DocIndentStyle =
@@ -494,7 +491,7 @@ object ScalaDocChecker {
494491
val typeParams = combineScalaDocFor(lines, "tparam", ScalaDocParameter)
495492
val returns = combineScalaDocFor(lines, "return", _ + _).headOption
496493

497-
ScalaDoc(raw.rawText, params, typeParams, returns, None, indentStyle)
494+
ScalaDoc(lineColumn.line, raw, params, typeParams, returns, None, indentStyle)
498495
}
499496
// scalastyle:on cyclomatic.complexity
500497
}
@@ -508,6 +505,7 @@ object ScalaDocChecker {
508505

509506
/**
510507
* Models the parsed ScalaDoc
508+
* @param line scaladoc line
511509
* @param text arbitrary text
512510
* @param params the parameters
513511
* @param typeParams the type parameters
@@ -516,6 +514,7 @@ object ScalaDocChecker {
516514
* @param indentStyle doc indent style
517515
*/
518516
private case class ScalaDoc(
517+
line: Int,
519518
text: String,
520519
params: List[ScalaDocParameter],
521520
typeParams: List[ScalaDocParameter],

src/main/scala/org/scalastyle/scalariform/SimplifyBooleanExpressionChecker.scala

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,20 @@ class SimplifyBooleanExpressionChecker extends ScalariformChecker {
3838
val it1 = for {
3939
List(left, right) <- ast.tokens.sliding(2);
4040
if (left.text == "!" && isBoolean(right))
41-
} yield PositionError(left.offset)
41+
} yield PositionError(right.offset)
4242

4343
val it2 = for {
4444
t <- localvisit(ast);
45-
if (matches(t))
46-
} yield PositionError(t.position.get)
45+
p <- matches(t)
46+
} yield PositionError(p)
4747

4848
(it1.toList ::: it2.toList).sortWith((a, b) => a.position < b.position)
4949
}
5050

51-
private def matches[T <: AstNode](t: Clazz[T]): Boolean = {
51+
private def matches[T <: AstNode](t: Clazz[T]): Option[Int] = {
5252
t match {
53-
case t: InfixExprClazz => matchesInfixOp(t.id) && (boolean(t.left) || boolean(t.right))
54-
case _ => false
53+
case t: InfixExprClazz if matchesInfixOp(t.id) => boolean(t.left).orElse(boolean(t.right))
54+
case _ => None
5555
}
5656
}
5757

@@ -74,9 +74,10 @@ class SimplifyBooleanExpressionChecker extends ScalariformChecker {
7474
case t: Any => visit(t, localvisit)
7575
}
7676

77-
private def boolean(expr: List[Clazz[_]]) =
78-
expr.size == 1 && expr(0)
79-
.isInstanceOf[GeneralTokensClazz] && expr(0).asInstanceOf[GeneralTokensClazz].bool
77+
private def boolean(expr: List[Clazz[_]]) = expr match {
78+
case List(t: GeneralTokensClazz) if t.bool => t.position
79+
case _ => None
80+
}
8081

8182
private def isBoolean(t: GeneralTokens): Boolean = t.tokens.size == 1 && isBoolean(t.tokens(0))
8283
private def isBoolean(t: Token): Boolean = Set(TRUE, FALSE).contains(t.tokenType)

src/main/scala/org/scalastyle/scalariform/TodoCommentChecker.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ class TodoCommentChecker extends CombinedChecker {
3434
def verify(ast: CombinedAst): List[ScalastyleError] = {
3535
val words = getString("words", defaultWords)
3636
val split = words.split("\\|").map(Pattern.quote).mkString("|")
37-
val regex = ("""(?i)(//|/\*|/\*\*|\*)\s?(""" + split + """)(:?)\s+""").r
37+
val regex = ("""(?i)(?:^//|^/\*|^/\*\*|\*)\s?(""" + split + """):?\s+""").r.unanchored
3838

3939
for {
4040
t <- ast.compilationUnit.tokens
4141
at <- t.associatedWhitespaceAndComments
4242
if Tokens.COMMENTS.contains(at.token.tokenType)
43-
if at.text.split("\n").exists(s => regex.findFirstIn(s).isDefined)
44-
} yield PositionError(at.token.offset, List(words))
43+
tag <- at.text.split("\n").view.collectFirst { case regex(tag) => tag }
44+
} yield PositionError(at.token.offset, List(tag))
4545
}
4646
}

src/test/scala/org/scalastyle/scalariform/CyclomaticComplexityCheckerTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class Foobar {
119119
"""
120120

121121
assertErrors(
122-
List(columnError(5, 6, List("4", "3")), columnError(21, 6, List("4", "3"))),
122+
List(columnError(5, 6, List("4", "3")), columnError(23, 8, List("4", "3"))),
123123
source,
124124
Map("maximum" -> "3")
125125
)

0 commit comments

Comments
 (0)