-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding inspection for immediate rethrows (#652)
* Adding inspection for immediate rethrows * Inspections now available when throwables/exceptions are immediately rethrown in a catch block implementation. * Adding inspection * Updating README.md
- Loading branch information
Showing
4 changed files
with
110 additions
and
1 deletion.
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
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
45 changes: 45 additions & 0 deletions
45
...cala/com/sksamuel/scapegoat/inspections/exception/CatchExceptionImmediatelyRethrown.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,45 @@ | ||
package com.sksamuel.scapegoat.inspections.exception | ||
|
||
import com.sksamuel.scapegoat._ | ||
|
||
class CatchExceptionImmediatelyRethrown | ||
extends Inspection( | ||
text = "Caught Exception Immediately Rethrown", | ||
defaultLevel = Levels.Warning, | ||
description = "Checks for try-catch blocks that immediately rethrow caught exceptions.", | ||
explanation = "Immediately re-throwing a caught exception is equivalent to not catching it at all." | ||
) { | ||
|
||
def inspector(context: InspectionContext): Inspector = | ||
new Inspector(context) { | ||
|
||
override def postTyperTraverser: context.Traverser = | ||
new context.Traverser { | ||
import context.global._ | ||
|
||
private def exceptionHandlers(cases: List[CaseDef]): List[(String, Tree)] = { | ||
cases.collect { | ||
// matches t : Exception | ||
case CaseDef(Bind(name, Typed(_, tpt)), _, body) if tpt.tpe =:= typeOf[Exception] => | ||
(name.toString(), body) | ||
// matches t : Throwable | ||
case CaseDef(Bind(name, Typed(_, tpt)), _, body) if tpt.tpe =:= typeOf[Throwable] => | ||
(name.toString(), body) | ||
} | ||
} | ||
|
||
override def inspect(tree: Tree): Unit = { | ||
tree match { | ||
case Try(_, catches, _) => | ||
val exceptionBodies = exceptionHandlers(catches) | ||
exceptionBodies.collect { | ||
case (exceptionName, Throw(Ident(name))) if name.toString() == exceptionName => | ||
context.warn(tree.pos, self) | ||
} | ||
case _ => | ||
continue(tree) | ||
} | ||
} | ||
} | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
.../com/sksamuel/scapegoat/inspections/exception/CatchExceptionImmediatelyRethrownTest.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 com.sksamuel.scapegoat.inspections.exception | ||
|
||
import com.sksamuel.scapegoat.InspectionTest | ||
|
||
class CatchExceptionImmediatelyRethrownTest extends InspectionTest { | ||
|
||
override val inspections = Seq(new CatchExceptionImmediatelyRethrown) | ||
|
||
"catch exception immediately throw" - { | ||
"should report warning" in { | ||
|
||
val testCode = """object Test { | ||
try { | ||
val x = 1 | ||
} catch { | ||
case foo : Exception => | ||
throw foo | ||
} | ||
} """.stripMargin | ||
|
||
compileCodeSnippet(testCode) | ||
compiler.scapegoat.feedback.warnings.size shouldBe 1 | ||
} | ||
} | ||
|
||
"catch throwable immediately throw" - { | ||
"should report warning" in { | ||
|
||
val testCode = """object Test { | ||
try { | ||
val x = 1 | ||
} catch { | ||
case foo : Throwable => | ||
throw foo | ||
} | ||
} """.stripMargin | ||
|
||
compileCodeSnippet(testCode) | ||
compiler.scapegoat.feedback.warnings.size shouldBe 1 | ||
} | ||
|
||
} | ||
|
||
"catch throwable and exception immediately throw" - { | ||
"should report all warnings" in { | ||
|
||
val testCode = """object Test { | ||
try { | ||
val x = 1 | ||
} catch { | ||
case foo : Throwable => | ||
throw foo | ||
case bar : Exception => | ||
throw bar | ||
} | ||
} """.stripMargin | ||
|
||
compileCodeSnippet(testCode) | ||
compiler.scapegoat.feedback.warnings.size shouldBe 2 | ||
} | ||
} | ||
} |