Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.13.6 #527

Merged
merged 8 commits into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ jobs:
- 2.12.11
- 2.12.12
- 2.12.13
- 2.13.3
- 2.13.4
- 2.13.5
- 2.13.6
steps:
- uses: actions/checkout@v2
- uses: olafurpg/setup-scala@v10
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ Scapegoat

[![Codecov](https://img.shields.io/codecov/c/github/sksamuel/scapegoat)](https://codecov.io/gh/sksamuel/scapegoat)
[<img src="https://img.shields.io/maven-central/v/com.sksamuel.scapegoat/scalac-scapegoat-plugin_2.11.12.svg?label=latest%20release%20for%202.11.12"/>](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22scalac-scapegoat-plugin_2.11.12%22)
[<img src="https://img.shields.io/maven-central/v/com.sksamuel.scapegoat/scalac-scapegoat-plugin_2.12.11.svg?label=latest%20release%20for%202.12.11"/>](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22scalac-scapegoat-plugin_2.12.11%22)
[<img src="https://img.shields.io/maven-central/v/com.sksamuel.scapegoat/scalac-scapegoat-plugin_2.13.5.svg?label=latest%20release%20for%202.13.5"/>](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22scalac-scapegoat-plugin_2.13.5%22)
[<img src="https://img.shields.io/maven-central/v/com.sksamuel.scapegoat/scalac-scapegoat-plugin_2.12.13.svg?label=latest%20release%20for%202.12.13"/>](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22scalac-scapegoat-plugin_2.12.13%22)
[<img src="https://img.shields.io/maven-central/v/com.sksamuel.scapegoat/scalac-scapegoat-plugin_2.13.6.svg?label=latest%20release%20for%202.13.6"/>](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22scalac-scapegoat-plugin_2.13.6%22)
[![Scala Steward badge](https://img.shields.io/badge/Scala_Steward-helping-blue.svg?style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAMAAAARSr4IAAAAVFBMVEUAAACHjojlOy5NWlrKzcYRKjGFjIbp293YycuLa3pYY2LSqql4f3pCUFTgSjNodYRmcXUsPD/NTTbjRS+2jomhgnzNc223cGvZS0HaSD0XLjbaSjElhIr+AAAAAXRSTlMAQObYZgAAAHlJREFUCNdNyosOwyAIhWHAQS1Vt7a77/3fcxxdmv0xwmckutAR1nkm4ggbyEcg/wWmlGLDAA3oL50xi6fk5ffZ3E2E3QfZDCcCN2YtbEWZt+Drc6u6rlqv7Uk0LdKqqr5rk2UCRXOk0vmQKGfc94nOJyQjouF9H/wCc9gECEYfONoAAAAASUVORK5CYII=)](https://scala-steward.org)

Scapegoat is a Scala static code analyzer, what is more colloquially known as a code lint tool or linter. Scapegoat works in a similar vein to Java's [FindBugs](http://findbugs.sourceforge.net/) or [checkstyle](http://checkstyle.sourceforge.net/), or Scala's [Scalastyle](https://github.com/scalastyle/scalastyle).
Expand Down
53 changes: 24 additions & 29 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ developers := List(
)
)

scalaVersion := "2.13.5"
crossScalaVersions := Seq("2.11.12", "2.12.11", "2.12.14", "2.13.6", "2.13.3", "2.13.4", "2.13.5")
scalaVersion := "2.13.6"
crossScalaVersions := Seq("2.11.12", "2.12.12", "2.12.13", "2.12.14", "2.13.3", "2.13.4", "2.13.5", "2.13.6")
autoScalaLibrary := false
crossVersion := CrossVersion.full
crossTarget := {
Expand Down Expand Up @@ -75,18 +75,18 @@ scalacOptions := {
common ++ (scalaBinaryVersion.value match {
case "2.11" => scalac11Options
case "2.12" => scalac12Options
case "2.13" => scalac13Options ++ (
scalaVersion.value.split('.') match {
case "2.13" =>
scalac13Options ++ (scalaVersion.value.split('.') match {
case Array(_, _, patch) if Set("0", "1", "2")(patch) => Seq("-Xlint:nullary-override")
case _ => Seq.empty[String]
case _ => Seq.empty[String]
})
})
}
javacOptions ++= Seq("-source", "1.8", "-target", "1.8")

// because that's where "PluginRunner" is
fullClasspath in console in Compile ++= (fullClasspath in Test).value
initialCommands in console := s"""
Compile / console / fullClasspath ++= (Test / fullClasspath).value
console / initialCommands := s"""
import com.sksamuel.scapegoat._
def check(code: String) = {
val runner = new PluginRunner { val inspections = ScapegoatConfig.inspections }
Expand All @@ -100,54 +100,49 @@ def check(code: String) = {
"""

libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value % "provided",
"org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided",
"org.scala-lang.modules" %% "scala-xml" % "1.3.0" excludeAll (
ExclusionRule(organization = "org.scala-lang")
),
"org.scala-lang.modules" %% "scala-collection-compat" % "2.4.4" excludeAll (
ExclusionRule(organization = "org.scala-lang")
"org.scala-lang" % "scala-reflect" % scalaVersion.value % "provided",
"org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided",
"org.scala-lang.modules" %% "scala-xml" % "1.3.0" excludeAll ExclusionRule(organization = "org.scala-lang"),
"org.scala-lang.modules" %% "scala-collection-compat" % "2.4.4" excludeAll ExclusionRule(organization =
"org.scala-lang"
),
"org.scala-lang" % "scala-compiler" % scalaVersion.value % "test",
"org.scalatest" %% "scalatest" % "3.2.9" % "test",
"org.scalatest" %% "scalatest" % "3.2.9" % "test",
"org.mockito" % "mockito-all" % "1.10.19" % "test",
"joda-time" % "joda-time" % "2.10.10" % "test",
"joda-time" % "joda-time" % "2.10.10" % "test",
"org.joda" % "joda-convert" % "2.2.1" % "test",
"org.slf4j" % "slf4j-api" % "1.7.30" % "test"
)

// Test
fork in (Test, run) := true
logBuffered in Test := false
parallelExecution in Test := false
Test / run / fork := true
Test / logBuffered := false
Test / parallelExecution := false

// ScalaTest reporter config:
// -o - standard output,
// D - show all durations,
// T - show reminder of failed and cancelled tests with short stack traces,
// F - show full stack traces.
testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-oDTF")
Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-oDTF")

// Assembly
// include the scala xml and compat modules into the final jar, shaded
assemblyShadeRules in assembly := Seq(
assembly / assemblyShadeRules := Seq(
ShadeRule.rename("scala.xml.**" -> "scapegoat.xml.@1").inAll,
ShadeRule.rename("scala.collection.compat.**" -> "scapegoat.compat.@1").inAll
)
packageBin in Compile := crossTarget.value / (assemblyJarName in assembly).value
Compile / packageBin := crossTarget.value / (assembly / assemblyJarName).value
makePom := makePom.dependsOn(assembly).value
test in assembly := {} // do not run tests during assembly
publishArtifact in Test := false
assembly / test := {} // do not run tests during assembly
Test / publishArtifact := false

// Scalafix
scalafixDependencies in ThisBuild += "com.nequissimus" %% "sort-imports" % "0.3.1"
ThisBuild / scalafixDependencies += "com.nequissimus" %% "sort-imports" % "0.3.1"
addCommandAlias("fix", "all compile:scalafix test:scalafix; fixImports")
addCommandAlias("fixImports", "compile:scalafix SortImports; test:scalafix SortImports")
addCommandAlias("fixCheck", "compile:scalafix --check; test:scalafix --check; fixCheckImports")
addCommandAlias("fixCheckImports", "compile:scalafix --check SortImports; test:scalafix --check SortImports")

// Scalafmt
scalafmtOnCompile in ThisBuild :=
sys.env
.get("GITHUB_ACTIONS")
.forall(_.toLowerCase == "false")
ThisBuild / scalafmtOnCompile := sys.env.get("GITHUB_ACTIONS").forall(_.toLowerCase == "false")
6 changes: 3 additions & 3 deletions src/main/scala/com/sksamuel/scapegoat/Feedback.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class Feedback(
def shouldPrint(warning: Warning): Boolean =
configuration.consoleOutput && warning.hasMinimalLevelOf(configuration.minimalLevel)

def infos = warnings(Levels.Info)
def errors = warnings(Levels.Error)
def warns = warnings(Levels.Warning)
def infos: Seq[Warning] = warnings(Levels.Info)
def errors: Seq[Warning] = warnings(Levels.Error)
def warns: Seq[Warning] = warnings(Levels.Warning)
def warnings(level: Level): Seq[Warning] = warnings.filter(_.level == level)

def warn(
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/com/sksamuel/scapegoat/Inspection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ abstract class Inspection(
val explanation: String
) {

val self = this
val self: Inspection = this

def inspector(context: InspectionContext): Inspector

Expand Down Expand Up @@ -88,7 +88,7 @@ final case class InspectionContext(global: Global, feedback: Feedback) {
symbol != null &&
symbol.annotations.exists(an => isSkipAnnotation(an) && isThisDisabled(an))

protected def continue(tree: Tree) = super.traverse(tree)
protected def continue(tree: Tree): Unit = super.traverse(tree)

protected def inspect(tree: Tree): Unit

Expand All @@ -109,7 +109,7 @@ final case class InspectionContext(global: Global, feedback: Feedback) {
}

protected def isArray(tree: Tree): Boolean = tree.tpe.typeSymbol.fullName == "scala.Array"
protected def isTraversable(tree: Tree): Boolean = tree.tpe <:< typeOf[Traversable[Any]]
protected def isIterable(tree: Tree): Boolean = tree.tpe <:< typeOf[Iterable[Any]]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly related #289 & #294.

protected def isSeq(t: Tree): Boolean = t.tpe <:< typeOf[Seq[Any]]
protected def isIndexedSeq(t: Tree): Boolean = t.tpe <:< typeOf[IndexedSeq[Any]]
protected def isSet(t: Tree, allowMutableSet: Boolean = true): Boolean = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.sksamuel.scapegoat.inspections

import scala.collection.mutable
import scala.collection.mutable.ListBuffer

import com.sksamuel.scapegoat.{Inspection, InspectionContext, Inspector, Levels}
Expand All @@ -16,17 +15,17 @@ class VariableShadowing

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._

private val contexts = new mutable.Stack[ListBuffer[String]]()
private var contexts: List[ListBuffer[String]] = Nil
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A var List is better than a mutable.Stack, so replacing it. Behavior is kept.


private def isDefined(name: String): Boolean = contexts exists (_.contains(name.trim))

private def enter(): Unit = contexts.push(new ListBuffer[String])
private def exit(): Unit = contexts.pop()
private def enter(): Unit = contexts = new ListBuffer[String] :: contexts
private def exit(): Unit = contexts = contexts.drop(1)

override def inspect(tree: Tree): Unit = {
tree match {
Expand All @@ -43,7 +42,7 @@ class VariableShadowing
exit()
case ValDef(_, TermName(name), _, _) =>
if (isDefined(name)) context.warn(tree.pos, self, tree.toString.take(200))
contexts.top.append(name.trim)
contexts.head.append(name.trim)
case Match(_, cases) =>
cases.foreach {
case CaseDef(Bind(name, _), _, _) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class AvoidSizeEqualsZero

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._
Expand All @@ -27,7 +27,7 @@ class AvoidSizeEqualsZero
override def inspect(tree: Tree): Unit = {
tree match {
case Apply(Select(Select(q, Size | Length), TermName("$eq$eq")), List(Literal(Constant(0))))
if isTraversable(q) =>
if isIterable(q) =>
context.warn(tree.pos, self, tree.toString.take(100))
case _ => continue(tree)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class AvoidSizeNotEqualsZero

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._
Expand All @@ -28,7 +28,7 @@ class AvoidSizeNotEqualsZero
case Apply(
Select(Select(q, Length | Size), TermName("$bang$eq") | TermName("$greater")),
List(Literal(Constant(0)))
) if isTraversable(q) =>
) if isIterable(q) =>
context.warn(tree.pos, self, tree.toString.take(100))
case _ => continue(tree)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ExistsSimplifiableToContains

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._
Expand All @@ -26,7 +26,7 @@ class ExistsSimplifiableToContains

private def doesElementTypeMatch(container: Tree, value: Tree): Boolean = {
val valueType = value.tpe.underlying.typeSymbol.tpe
val traversableType = container.tpe.underlying.baseType(typeOf[Traversable[Any]].typeSymbol)
val traversableType = container.tpe.underlying.baseType(typeOf[Iterable[Any]].typeSymbol)
traversableType.typeArgs.exists(t => valueType <:< t || valueType =:= t)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class NegationIsEmpty

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._
Expand All @@ -25,7 +25,7 @@ class NegationIsEmpty

override def inspect(tree: Tree): Unit = {
tree match {
case Select(Select(lhs, IsEmpty), Bang) if isTraversable(lhs) =>
case Select(Select(lhs, IsEmpty), Bang) if isIterable(lhs) =>
context.warn(tree.pos, self, tree.toString.take(100))
case _ => continue(tree)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class NegationNonEmpty

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._
Expand All @@ -25,7 +25,7 @@ class NegationNonEmpty

override def inspect(tree: Tree): Unit = {
tree match {
case Select(Select(lhs, IsEmpty), Bang) if isTraversable(lhs) =>
case Select(Select(lhs, IsEmpty), Bang) if isIterable(lhs) =>
context.warn(tree.pos, self, tree.toString.take(100))
case _ => continue(tree)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ class ReverseFunc

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._

override def inspect(tree: Tree): Unit = {
tree match {
case Select(Select(c, TermName("reverse")), TermName(FuncReplace(_, _)))
if c.tpe <:< typeOf[Traversable[Any]] =>
if c.tpe <:< typeOf[Iterable[Any]] =>
context.warn(tree.pos, self, tree.toString.take(500))
case Select(
Apply(arrayOps1, List(Select(Apply(arrayOps2, List(_)), TermName("reverse")))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ class ReverseTailReverse

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._

override def inspect(tree: Tree): Unit = {
tree match {
case Select(Select(Select(c, TermName("reverse")), TermName("tail")), TermName("reverse"))
if isTraversable(c) =>
if isIterable(c) =>
context.warn(tree.pos, self, tree.toString.take(500))
case Select(
Apply(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class ReverseTakeReverse

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._
Expand All @@ -22,7 +22,7 @@ class ReverseTakeReverse
case Select(
Apply(Select(Select(c, TermName("reverse")), TermName("take")), _),
TermName("reverse")
) if isTraversable(c) =>
) if isIterable(c) =>
context.warn(tree.pos, self, tree.toString.take(500))
case Select(
Apply(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ class UnsafeTraversableMethods

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._

override def inspect(tree: Tree): Unit = {
tree match {
case Select(left, TermName(method)) =>
if (isTraversable(left) && unsafeMethods.contains(method))
if (isIterable(left) && unsafeMethods.contains(method))
context.warn(tree.pos, self, tree.toString.take(500))
case _ => continue(tree)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class UseLog10

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ class UseLog1P

def inspector(context: InspectionContext): Inspector =
new Inspector(context) {
override def postTyperTraverser =
override def postTyperTraverser: context.Traverser =
new context.Traverser {

import context.global._

def isMathPackage(pack: String) =
def isMathPackage(pack: String): Boolean =
pack == "scala.math.package" ||
pack == "java.lang.Math" ||
pack == "java.lang.StrictMath"
Expand Down
Loading