-
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.
Add
NoUnnecessaryForComprehension
rule.
- Loading branch information
Showing
4 changed files
with
118 additions
and
0 deletions.
There are no files selected for viewing
43 changes: 43 additions & 0 deletions
43
scalafix/input/src/main/scala-3/fix/NoUnnecessaryForComprehension.scala
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,43 @@ | ||
/* | ||
rule = NoUnnecessaryForComprehension | ||
NoUnnecessaryForComprehension.color = false | ||
*/ | ||
package fix | ||
|
||
object NoUnnecessaryForComprehension { | ||
val x = for {/* assert: NoUnnecessaryForComprehension | ||
^ | ||
A for comprehension with only one statement can be simplified | ||
Cases where the yield returns the result of the statement can just be the statement itself: | ||
Before: | ||
for { | ||
x <- someStatementHere | ||
} yield x | ||
After: | ||
someStatementHere | ||
Cases where the yield performs an additional computation can be rewritten with map: | ||
Before: | ||
for { | ||
x <- someStatementHere | ||
} yield doSomethingElse(x) | ||
After: | ||
someStatementHere.map(doSomethingElse) */ | ||
i <- Option(1) | ||
} yield i | ||
|
||
val y = for { | ||
i <- Option(1) | ||
j <- Option(2) | ||
} yield i + j | ||
} |
12 changes: 12 additions & 0 deletions
12
scalafix/output/src/main/scala-3/fix/NoUnnecessaryForComprehension.scala
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,12 @@ | ||
package fix | ||
|
||
object NoUnnecessaryForComprehension { | ||
val x = for { | ||
i <- Option(1) | ||
} yield i | ||
|
||
val y = for { | ||
i <- Option(1) | ||
j <- Option(2) | ||
} yield i + j | ||
} |
1 change: 1 addition & 0 deletions
1
scalafix/rules/src/main/resources/META-INF/services/scalafix.v1.Rule
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
fix.NoUnnecessaryCase | ||
fix.NoUnnecessaryForComprehension | ||
fix.StrictSubclassAccess | ||
fix.NoWithForExtends |
62 changes: 62 additions & 0 deletions
62
scalafix/rules/src/main/scala/fix/NoUnnecessaryForComprehension.scala
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,62 @@ | ||
package fix | ||
|
||
import metaconfig.{ConfDecoder, Configured} | ||
import metaconfig.generic.{deriveDecoder, deriveSurface, Surface} | ||
import scalafix.v1._ | ||
import scala.io.AnsiColor | ||
import scala.meta._ | ||
|
||
case class NoUnnecessaryForComprehensionConfig(color: Boolean) | ||
object NoUnnecessaryForComprehensionConfig { | ||
val default = NoUnnecessaryForComprehensionConfig(true) | ||
|
||
implicit val surface: Surface[NoUnnecessaryForComprehensionConfig] = deriveSurface | ||
implicit val decoder: ConfDecoder[NoUnnecessaryForComprehensionConfig] = deriveDecoder(default) | ||
} | ||
|
||
case class UnnecessaryForComprehensionLint(position: Position, color: Boolean) extends Diagnostic { | ||
private def withColor(c: String): String => String = s => if (color) c ++ s ++ AnsiColor.RESET else s | ||
private val magenta = withColor(AnsiColor.MAGENTA) | ||
private val red = withColor(AnsiColor.RED) | ||
|
||
override def message = s"""| | ||
|A ${magenta("for")} comprehension with only one statement can be simplified | ||
| | ||
|Cases where the ${magenta("yield")} returns the result of the statement can just be the statement itself: | ||
| | ||
|Before: | ||
| | ||
| ${magenta("for")} { | ||
| ${red("x")} <- someStatementHere | ||
| } ${magenta("yield")} x | ||
| | ||
|After: | ||
| | ||
| someStatementHere | ||
| | ||
|Cases where the ${magenta("yield")} performs an additional computation can be rewritten with ${magenta("map")}: | ||
| | ||
|Before: | ||
| | ||
| ${magenta("for")} { | ||
| ${red("x")} <- someStatementHere | ||
| } ${magenta("yield")} doSomethingElse(x) | ||
| | ||
|After: | ||
| | ||
| someStatementHere.map(doSomethingElse) | ||
|""".stripMargin | ||
} | ||
|
||
class NoUnnecessaryForComprehension(config: NoUnnecessaryForComprehensionConfig) | ||
extends SyntacticRule("NoUnnecessaryForComprehension") { | ||
def this() = this(NoUnnecessaryForComprehensionConfig.default) | ||
|
||
override def withConfiguration(config: Configuration): Configured[Rule] = | ||
config.conf.getOrElse("NoUnnecessaryForComprehension")(this.config).map(new NoUnnecessaryForComprehension(_)) | ||
|
||
override def fix(implicit doc: SyntacticDocument): Patch = | ||
doc.tree.collect { | ||
case t @ Term.ForYield(List(_), _) => Patch.lint(UnnecessaryForComprehensionLint(t.pos, config.color)) | ||
}.asPatch | ||
} |