Skip to content

Commit

Permalink
Merge pull request #1871 from dedis/work-be2-thibault-linter_master
Browse files Browse the repository at this point in the history
[BE2] Work on more rules for linter
  • Loading branch information
t1b00 committed Jun 17, 2024
2 parents 0450bf5 + 9c32274 commit 62b1a2e
Show file tree
Hide file tree
Showing 29 changed files with 874 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ object ArraysInFormat {
val str = f"Here are my cool elements ${array}" // assert: ArraysInFormat
val str2 = s"Here are my cool elements ${array}" // assert: ArraysInFormat
String.format("Here are my cool elements %d", array) // assert: ArraysInFormat
"Here are my cool elements %d".format(array) // assert: ArraysInFormat
val str3 = "Here are my cool elements %d"
str3.format(array) // assert: ArraysInFormat
String.format("Here are my cool elements %d", array) /* assert: ArraysInFormat
^^^^^
Array passed to format / interpolate string
*/

"Here are my cool elements %d".format(13) // scalafix: ok;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ package fix
object EmptyInterpolatedString {
def test(): Unit = {
print(f"Here's my cute interpolation") // assert: EmptyInterpolatedString
print(s"Here's my amazing interpolationg") // assert: EmptyInterpolatedString
print(String.format("I'm hungry!")) // assert: EmptyInterpolatedString
print(s"Here's my amazing interpolation") // assert: EmptyInterpolatedString
String.format("I'm hungry!") // assert: EmptyInterpolatedString
val str = "I'm hungry!"
str.format() // assert: EmptyInterpolatedString
"I'm hungry!".format() // assert: EmptyInterpolatedString
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
rule = IllegalFormatString
*/
package fix

object IllegalFormatString {
def test(): Unit = {
val name: String = "John"
val age: Integer = 30
val illegalFormatString1 = "%s is %d years old, %d"
String.format(illegalFormatString1, name, age) // assert: IllegalFormatString

illegalFormatString1.format(name, age) // assert: IllegalFormatString

"%s is %d years old, %d".format(name, age) // assert: IllegalFormatString

"%5.5q".format("sam") // assert: IllegalFormatString

"% s".format("sam") // assert: IllegalFormatString

"%qs".format("sam") // assert: IllegalFormatString

"%.-5s".format("sam") // assert: IllegalFormatString

"%.s".format("sam") // assert: IllegalFormatString

"%<s %s".format("sam", "sam") // assert: IllegalFormatString

"%.2f %s".format(14.5, "sammmmmmmmm") // scalafix: ok;
"%010d".format(0) // scalafix: ok;

"%s is %d years old, %d".format(name, age, 145) // scalafix: ok;


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
rule = IncorrectNumberOfArgsToFormat
*/
package fix

object IncorrectNumberOfArgsToFormat {
def test() = {
val name: String = "John"
val age: Integer = 30
val illegalFormatString1 = "%s is %d years old, %d"
illegalFormatString1.format(name, age, 134, 54, "Olivia") // assert: IncorrectNumberOfArgsToFormat
illegalFormatString1.format(name) // assert: IncorrectNumberOfArgsToFormat

"%s is %d years old, %d".format(name, age, 134, 54, "Olivia") // assert: IncorrectNumberOfArgsToFormat
"%s is %d years old, %d".format(name) // assert: IncorrectNumberOfArgsToFormat

String.format(illegalFormatString1, name) // assert: IncorrectNumberOfArgsToFormat

illegalFormatString1.format(name, age, 134) // scalafix: ok;
"%s is %d years old, %d".format(name, age, 134) // scalafix: ok;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
rule = IncorrectlyNamedExceptions
*/
package fix

// Test values taken from Scapegoat test
object IncorrectlyNamedExceptions {
class NotException // scalafix: ok;

class IsException extends Exception // scalafix: ok;

class IsNotNamedCorrectly extends Exception // assert: IncorrectlyNamedExceptions

class Is extends Exception // assert: IncorrectlyNamedExceptions

class IsChild extends Is // assert: IncorrectlyNamedExceptions

class IsChildException // scalafix: ok;

class IsRuntimeException extends RuntimeException // scalafix: ok;

class IsRuntime extends Exception // assert: IncorrectlyNamedExceptions

}

106 changes: 106 additions & 0 deletions be2-scala/linter/input/src/main/scala/fix/LonelySealedTrait.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
rule = LonelySealedTrait
*/
package fix

// Test values taken from Scapegoat test
object LonelySealedTrait {

sealed trait NoImpl // assert: LonelySealedTrait

sealed trait Impl1 // scalafix: ok;
object Implemented extends Impl1

sealed trait Impl2 // scalafix: ok;
case object Implemented2 extends Impl2

sealed trait Impl3 // scalafix: ok;
case object Implemented3 extends Serializable with Impl3

sealed trait Impl4 // scalafix: ok;
case class Implemented4() extends Impl4

sealed trait Impl5 // scalafix: ok;
class Implemented extends Impl5

sealed trait Impl6 // scalafix: ok;
case class Implemented6(name: String) extends Serializable with Impl6

sealed trait Impl7 // scalafix: ok;
class Implemented7(name: String) extends Serializable with Impl7

sealed trait Impl8 // scalafix: ok;
case class Implemented8(name: String) extends Impl8

sealed trait Impl9 // scalafix: ok;
class Implemented9(name: String) extends Impl9

sealed trait Impl10 // scalafix: ok;
sealed trait Impl11 // scalafix: ok;
case class Implemented10(name: String) extends Impl10
case class Implemented11(name: String) extends Impl11

trait AnalyzerFilter {
def name: String
}

trait AnalyzerFilterDefinition {
def filterType: String
}

sealed trait CharFilter extends AnalyzerFilter // scalafix: ok;

sealed trait CharFilterDefinition extends CharFilter with AnalyzerFilterDefinition // scalafix: ok;

case object HtmlStripCharFilter extends CharFilter {
val name = "html_strip"
}

case class MappingCharFilter(name: String, mappings: (String, String)*)
extends CharFilterDefinition {
val filterType = "mapping"
}

case class PatternReplaceCharFilter(name: String, pattern: String, replacement: String)
extends CharFilterDefinition {
val filterType = "pattern_replace"
}

sealed abstract class MultiMode(val elastic: String) // scalafix: ok;
case object MultiMode {
case object Min extends MultiMode("min")
case object Max extends MultiMode("max")
case object Sum extends MultiMode("sum")
case object Avg extends MultiMode("avg")
}

sealed trait A[S] // scalafix: ok;
case object B extends A[String]
case object C extends A[BigDecimal]

sealed abstract class IndexOptionsNoImplementation(val value: String) // assert: LonelySealedTrait

sealed abstract class IndexOptions(val value: String) // scalafix: ok;
object IndexOptions {
case object Docs extends IndexOptions("docs")
case object Freqs extends IndexOptions("freqs")
case object Positions extends IndexOptions("positions")
}

sealed trait D // scalafix: ok;
sealed trait E extends D
sealed trait F extends E
object F1 extends F

sealed class G // scalafix: ok;
sealed class H extends G
sealed class I extends H
object I1 extends I

sealed trait J // scalafix: ok;
sealed trait K extends J
sealed class L extends K
object L1 extends L


}
19 changes: 19 additions & 0 deletions be2-scala/linter/input/src/main/scala/fix/MapGetAndGetOrElse.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
rule = MapGetAndGetOrElse
*/
package fix

object MapGetAndGetOrElse {
def test() = {
val numMap1 = Map(1 -> "one", 2 -> "two")
numMap1.get(1).getOrElse("unknown") // assert: MapGetAndGetOrElse


val numMap2 = scala.collection.mutable.Map("one" -> 1, "two" -> 2)
numMap2.get("one").getOrElse(-1) // assert: MapGetAndGetOrElse

Map("John" -> "Smith", "Peter" -> "Rabbit").get("Sarah").getOrElse("-") // assert: MapGetAndGetOrElse

}

}
29 changes: 29 additions & 0 deletions be2-scala/linter/input/src/main/scala/fix/NanComparison.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
rule = NanComparison
*/
package fix

object NanComparison {

def test() = {
val d = 0.5d
d == Double.NaN // assert: NanComparison
Double.NaN == d // assert: NanComparison
d.equals(Double.NaN) // assert: NanComparison
Double.NaN.equals(d) // assert: NanComparison

val f = 0.5f
f == Double.NaN // assert: NanComparison
Double.NaN == f // assert: NanComparison

val g = Double.NaN
f == g // assert: NanComparison
g == f // assert: NanComparison

d == g // assert: NanComparison
g == d // assert: NanComparison
d.equals(g) // assert: NanComparison
g.equals(d) // assert: NanComparison
}

}
13 changes: 13 additions & 0 deletions be2-scala/linter/input/src/main/scala/fix/OptionGet.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
rule = OptionGet
*/
package fix

object OptionGet {
def test() = {
val o = Option("olivia")
o.get // assert: OptionGet

Option("layla").get // assert: OptionGet
}
}
13 changes: 13 additions & 0 deletions be2-scala/linter/input/src/main/scala/fix/OptionSize.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
rule = OptionSize
*/
package fix

object OptionSize {
def test() = {
val o = Option("olivia")
o.size // assert: OptionSize

Option("layla").size // assert: OptionSize
}
}
13 changes: 13 additions & 0 deletions be2-scala/linter/input/src/main/scala/fix/StripMarginOnRegex.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
rule = StripMarginOnRegex
*/
package fix

object StripMarginOnRegex {
def test() = {
val regex = "match|this".stripMargin.r // assert: StripMarginOnRegex
"match|that".stripMargin.r // assert: StripMarginOnRegex
"match_this".stripMargin.r // scalafix: ok;
"match|this".r // scalafix: ok;
}
}
15 changes: 15 additions & 0 deletions be2-scala/linter/input/src/main/scala/fix/TryGet.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
rule = TryGet
*/
package fix

import scala.util.Try

object TryGet {
def test() = {
val o = Try { println("mojave") }
o.get // assert: TryGet

Try { println("ghost") }.get // assert: TryGet
}
}
43 changes: 43 additions & 0 deletions be2-scala/linter/project/TargetAxis.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import sbt._
import sbt.internal.ProjectMatrix
import sbtprojectmatrix.ProjectMatrixPlugin.autoImport._

/** Use on ProjectMatrix rows to tag an affinity to a custom scalaVersion */
case class TargetAxis(scalaVersion: String) extends VirtualAxis.WeakAxis {

private val scalaBinaryVersion = CrossVersion.binaryScalaVersion(scalaVersion)

override val idSuffix = s"Target${scalaBinaryVersion.replace('.', '_')}"
override val directorySuffix = s"target$scalaBinaryVersion"
}

object TargetAxis {

private def targetScalaVersion(virtualAxes: Seq[VirtualAxis]): String =
virtualAxes.collectFirst { case a: TargetAxis => a.scalaVersion }.get

/** When invoked on a ProjectMatrix with a TargetAxis, lookup the project generated by `matrix` with a scalaVersion matching the one declared in that TargetAxis, and resolve `key`.
*/
def resolve[T](
matrix: ProjectMatrix,
key: TaskKey[T]
): Def.Initialize[Task[T]] =
Def.taskDyn {
val sv = targetScalaVersion(virtualAxes.value)
val project = matrix.finder().apply(sv)
Def.task((project / key).value)
}

/** When invoked on a ProjectMatrix with a TargetAxis, lookup the project generated by `matrix` with a scalaVersion matching the one declared in that TargetAxis, and resolve `key`.
*/
def resolve[T](
matrix: ProjectMatrix,
key: SettingKey[T]
): Def.Initialize[T] =
Def.settingDyn {
val sv = targetScalaVersion(virtualAxes.value)
val project = matrix.finder().apply(sv)
Def.setting((project / key).value)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,13 @@ fix.CatchNpe
fix.ComparingFloatingTypes
fix.EmptyInterpolatedString
fix.ImpossibleOptionSizeCondition
fix.IllegalFormatString
fix.IncorrectNumberOfArgsToFormat
fix.IncorrectlyNamedExceptions
fix.LonelySealedTrait
fix.MapGetAndGetOrElse
fix.NanComparison
fix.OptionGet
fix.OptionSize
fix.StripMarginOnRegex
fix.TryGet
Loading

0 comments on commit 62b1a2e

Please sign in to comment.