Skip to content

Commit

Permalink
Added BoundedByFinalType
Browse files Browse the repository at this point in the history
  • Loading branch information
t1b00 committed Sep 12, 2024
1 parent ebbb200 commit 169db3f
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 1 deletion.
25 changes: 25 additions & 0 deletions input/src/main/scala/fix/BoundedByFinalType.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
rule = BoundedByFinalType
*/
package fix

object BoundedByFinalType {
class Test[A <: String] // assert: BoundedByFinalType
def foo[B <: Integer](): Unit = {} // assert: BoundedByFinalType

val test: PartialFunction[Array[String], Int] = { // scalafix: ok;
case _ => -1
}
val a = List[String]("sam") // scalafix: ok;

class Test2[A <: Exception] // scalafix: ok;
class Test3[A <: Any] // scalafix: ok;
class Test4 // scalafix: ok;

def foo2[B <: Exception](): Unit = {} // scalafix: ok;
def foo3[B <: Any](): Unit = {} // scalafix: ok;
def foo4(): Unit = {} // scalafix: ok;

type Texty = String // scalafix: ok;
type ListBuffer[A] = scala.collection.mutable.ListBuffer[A] // scalafix: ok;
}
3 changes: 2 additions & 1 deletion rules/src/main/resources/META-INF/services/scalafix.v1.Rule
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,5 @@ fix.AsInstanceOf
fix.AvoidToMinusOne
fix.BigDecimalDoubleConstructor
fix.BigDecimalScaleWithoutRoundingMode
fix.BooleanParameter
fix.BooleanParameter
fix.BoundedByFinalType
32 changes: 32 additions & 0 deletions rules/src/main/scala/fix/BoundedByFinalType.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
rule = BoundedByFinalType
*/
package fix

import scalafix.lint.LintSeverity
import scalafix.v1._

import scala.meta._

class BoundedByFinalType extends SemanticRule("BoundedByFinalType") {

private def diag(pos: Position) = Diagnostic(
"",
"Checks for types with upper bounds of a final type.",
pos,
"Pointless type bound. Type parameter can only be a single value.",
LintSeverity.Warning
)

override def fix(implicit doc: SemanticDocument): Patch = {
doc.tree.collect {
// Corresponds to [A <: ...] in class Test[A <: String] or def foo[B <: Integer] = {}
case Type.ParamClause(List(params)) =>
params.collect {
// String is seen as Predef.String, not java/lang/String. String is final but not Predef.String, even though they are essentially the same.
case p @ Type.Param.After_4_6_0(_, _, _, Type.Bounds(_, hi), _, _) if hi.exists(h => h.symbol.info.exists(i => i.isFinal) || h.toString == "String") => Patch.lint(diag(p.pos))
}
}.flatten.asPatch
}

}

0 comments on commit 169db3f

Please sign in to comment.