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

Commit

Permalink
Method checkers: report method position, not class
Browse files Browse the repository at this point in the history
  • Loading branch information
Albert Meltzer committed Jul 15, 2021
1 parent 2a98b4f commit 6dc457a
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class CovariantEqualsNoObjectKO {
}
"""

assertErrors(List(columnError(4, 6)), source)
assertErrors(List(columnError(5, 6)), source)
}

@Test def testObjectOK(): Unit = {
Expand All @@ -73,6 +73,6 @@ object CovariantEqualsNoObjectKO {
}
"""

assertErrors(List(columnError(4, 7)), source)
assertErrors(List(columnError(5, 6)), source)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class HashCodeOnlyKO {
}
"""

assertErrors(List(columnError(4, 6)), source)
assertErrors(List(columnError(5, 6)), source)
}

@Test def testEqualsOnlyKO(): Unit = {
Expand All @@ -60,7 +60,7 @@ class EqualsOnlyKO {
}
"""

assertErrors(List(columnError(4, 6)), source)
assertErrors(List(columnError(5, 6)), source)
}

@Test def testEqualsOnlyAnyKO(): Unit = {
Expand All @@ -72,7 +72,7 @@ class EqualsOnlyKO {
}
"""

assertErrors(List(columnError(4, 6)), source)
assertErrors(List(columnError(5, 6)), source)
}

@Test def testEqualsWrongSignatureOK(): Unit = {
Expand Down Expand Up @@ -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 = {
Expand All @@ -128,7 +128,7 @@ class OuterOK {
}
"""

assertErrors(List(columnError(6, 8)), source)
assertErrors(List(columnError(7, 8)), source)
}

@Test def testObjectInnerKO(): Unit = {
Expand All @@ -142,7 +142,7 @@ object Object {
}
"""

assertErrors(List(columnError(5, 8)), source)
assertErrors(List(columnError(6, 8)), source)
}

@Test def testMultipleClasses(): Unit = {
Expand All @@ -158,6 +158,6 @@ class Class2 {
}
"""

assertErrors(List(columnError(4, 6), columnError(8, 6)), source)
assertErrors(List(columnError(5, 6), columnError(9, 6)), source)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class CloneKO {
}
"""

assertErrors(List(columnError(4, 6)), source)
assertErrors(List(columnError(5, 6)), source)
}

@Test def testObjectOK(): Unit = {
Expand All @@ -71,6 +71,6 @@ object CloneKO {
}
"""

assertErrors(List(columnError(4, 7)), source)
assertErrors(List(columnError(5, 6)), source)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class CloneKO {
}
"""

assertErrors(List(columnError(4, 6)), source)
assertErrors(List(columnError(5, 6)), source)
}

@Test def testObjectOK(): Unit = {
Expand All @@ -71,6 +71,6 @@ object CloneKO {
}
"""

assertErrors(List(columnError(4, 7)), source)
assertErrors(List(columnError(5, 6)), source)
}
}

0 comments on commit 6dc457a

Please sign in to comment.