-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
66 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
rule = MethodReturningAny | ||
*/ | ||
package fix | ||
|
||
object MethodReturningAny { | ||
|
||
def inferredAny(value: Boolean) = { // assert: MethodReturningAny | ||
if (value) "This is a string" // returns a String | ||
else 42 // returns an Int | ||
} | ||
|
||
// This method returns Any in Scala 2 and should be flagged. It returns Int | String in Scala 3 and will also be flagged. | ||
// See rule for more precisions. | ||
|
||
def test: Any = 1 // assert: MethodReturningAny | ||
|
||
def foo: Int = 4 // scalafix: ok; | ||
def boo: String = "sam" // scalafix: ok; | ||
|
||
trait A { | ||
def foo: AnyRef = "foo" // assert: MethodReturningAny | ||
} | ||
class B extends A { | ||
override def foo: AnyRef = "overridden foo" // scalafix: ok; | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
rule = MethodReturningAny | ||
*/ | ||
package fix | ||
|
||
import scalafix.lint.LintSeverity | ||
import scalafix.v1._ | ||
|
||
import scala.meta._ | ||
|
||
class MethodReturningAny extends SemanticRule("MethodReturningAny") { | ||
|
||
private def diag(pos: Position) = Diagnostic( | ||
"", | ||
"Checks for functions that are defined to return Any.", | ||
pos, | ||
"Method returns Any. Consider using a more specialized type.", | ||
LintSeverity.Error | ||
) | ||
|
||
override def fix(implicit doc: SemanticDocument): Patch = { | ||
doc.tree.collect { | ||
// Note: this rule is limited since there is no type inference done, we cannot use synthetics either since they | ||
// do not seem to provide information about definitions and return types. This rule is thus limited to the type put by the developer. | ||
case t @ Defn.Def.After_4_6_0(mods, _, _, Some(Type.Name("Any" | "AnyRef")), _) if !mods.exists(m => m.toString() == "override") => Patch.lint(diag(t.pos)) | ||
case t @ Defn.Def.After_4_6_0(mods, _, _, None, _) if !mods.exists(m => m.toString() == "override") => | ||
t.symbol.info.collect(s => s.signature match { | ||
// Type was inferred to be Any or AnyRef | ||
case MethodSignature(_, _, TypeRef(_, tpe, _)) if SymbolMatcher.exact("scala/Any#", "scala/AnyRef#").matches(tpe) => Patch.lint(diag(t.pos)) | ||
case MethodSignature(_, _, UnionType(_)) => Patch.lint(diag(t.pos)) | ||
// Flag soft (i.e. compiler inferred) UnionTypes, as chances are the user would not want that. | ||
// If a UnionType is actually desired, one can simply add the type explicitly. The ParamClauseGroup would not be None in that case. | ||
case _ => Patch.empty | ||
}).getOrElse(Patch.empty) | ||
}.asPatch | ||
} | ||
} |