scapegoat-scala / scapegoat Goto Github PK
View Code? Open in Web Editor NEWScala compiler plugin for static code analysis
License: Apache License 2.0
Scala compiler plugin for static code analysis
License: Apache License 2.0
Related to #19
scalaCompilerJar,
scalaReflectJar,
scalaLibraryJar).flatten
Is reporting as a use (ensime, ProjectConfig.scala:751)
Set[T]() creates a new instance. Consider Set.empty which does not allocate a new object. scala.this.Predef.Set.apply[Option[org.ensime.util.CanonFile]]``
Use of var com.sksamuel.scapegoat.inspections.VarUse
var used: private[this] var state: Int = 0
Empty case classes should be case objects, since they would compare equals anyways.
I tried scapegoat
on our large Scala codebase.
Here is what I found:
We use this in a few places, e.g.
In one place we dive into the Akka internals in order to do some reporting that Akka doesn't offer:
def examineAllActors(system: ActorSystem): ActorStats = {
...
walk(system.asInstanceOf[ActorSystemImpl].lookupRoot)
}
The warning here is just "asInstanceOf used near ... Consider using collect.", which doesn't quite make sense.
Perhaps there just needs to be an option to suppress warnings?
The following actor Receive method triggers this warning:
def receive: Receive = LoggingReceive {
case requestStart: ChunkedRequestStart =>
// start by establishing a new HTTP connection
val host = requestStart.request.uri.authority.host.address
val port = requestStart.request.uri.authority.port
ioActor ! Http.Connect(host, port)
owner = sender()
context.become(connecting(requestStart))
}
This seems to happen on many of our receive
blocks.
We use this in a few places, and it is flagged as an error by scapegoat
.
The warning doesn't offer any justification for a blanket ban on this feature, nor any suggestions on alternatives.
Much of our use of "option.get" is in stateful actors.
Again, no justifications are given for a blanket ban on these features, nor any suggestions on alternatives.
What's wrong with Java conversions?
Again, no justification is given for a blanket ban on this feature, nor any suggestions on alternatives.
This is generally a good one. We have some false positives where the param is required to implement an interface, but not used by all implementors.
We have some macro use, and every param is flagged as "unused", even though they are all used.
Code like this:
<xml>{myVariable}</xml>
Generates "var used: var $tmpscope: scala.xml.NamespaceBinding = $scope"
We have an abstract method:
def xml(sessionId: Option[String]): Elem
which generates "Unused method parameter (val sessionId: Option[String] = _) at xml"
The report is pretty and easy to read, but it's static. There is no way to sort or filter. The Findbugs report viewer is more fully featured in this respect.
Is there any way to explicit override a warning, e.g. with a code comment?
Generally this looks good. I think it might be more effective to make Findbugs scala-friendly though. I'll reply to your other email.
via comment / annotation / external file ?
Warning Repeated case body com.sksamuel.scapegoat.inspections.matching.RepeatedCaseBody
x0$1 match { case '\n' => ' ' case '\r' => ' ' case (c @ _) => c }
The rule is good, but needs a description (ie. that two cases have the same result code).
Running this against some auto-genned code from scalaxb I got this stack trace (sorry for the lenght). Compiling without the "experimental" compiler options (ie genbcode / closure elim / const-opt & delamdafy) still caused the exception. I also completely removed HairyFotr's linter (even though it's disabled in this sub-project) which also caused no change.
[debug] Calling Scala compiler with arguments (CompilerInterface):
[debug] -encoding
[debug] utf8
[debug] -language:implicitConversions
[debug] -target:jvm-1.7
[debug] -Ybackend:GenBCode
[debug] -Yclosure-elim
[debug] -Yconst-opt
[debug] -Ydelambdafy:method
[debug] -language:_
[debug] -Xplugin-disable:linter
[debug] -Xplugin:/.../linter_2.11-0.1-SNAPSHOT.jar
[debug] -Xplugin:/.../scalac-scapegoat-plugin_2.11-0.90.5.jar
[debug] -P:scapegoat:dataDir:/.../target/scala-2.11/scapegoat-report
[debug] -P:scapegoat:disabledInspections:
java.util.NoSuchElementException: head of empty list
at scala.collection.immutable.Nil$.head(List.scala:420)
at scala.collection.immutable.Nil$.head(List.scala:417)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:16)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.api.Trees$Traverser.traverseGuard(Trees.scala:2477)
at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1231)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1323)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.api.Trees$Traverser.traverseTrees(Trees.scala:2484)
at scala.reflect.api.Trees$Traverser.traverseCases(Trees.scala:2487)
at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1258)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1323)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.internal.Trees$$anonfun$itraverse$1.apply$mcV$sp(Trees.scala:1322)
at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2507)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1322)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.api.Trees$Traverser.traverseTrees(Trees.scala:2484)
at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1277)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1323)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1276)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1323)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.internal.Trees$$anonfun$traverseMemberDef$1$1.apply$mcV$sp(Trees.scala:1202)
at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2507)
at scala.reflect.internal.Trees$class.traverseMemberDef$1(Trees.scala:1196)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1321)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.api.Trees$Traverser.traverseTrees(Trees.scala:2484)
at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1227)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1323)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.internal.Trees$$anonfun$traverseMemberDef$1$1.apply$mcV$sp(Trees.scala:1208)
at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2507)
at scala.reflect.internal.Trees$class.traverseMemberDef$1(Trees.scala:1196)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1321)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.api.Trees$Traverser$$anonfun$traverseStats$1$$anonfun$apply$1.apply$mcV$sp(Trees.scala:2498)
at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2507)
at scala.reflect.api.Trees$Traverser.traverseStats(Trees.scala:2497)
at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1225)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1323)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.internal.Trees$$anonfun$traverseMemberDef$1$1.apply$mcV$sp(Trees.scala:1201)
at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2507)
at scala.reflect.internal.Trees$class.traverseMemberDef$1(Trees.scala:1196)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1320)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at scala.reflect.api.Trees$Traverser$$anonfun$traverseStats$1$$anonfun$apply$1.apply$mcV$sp(Trees.scala:2498)
at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2507)
at scala.reflect.api.Trees$Traverser.traverseStats(Trees.scala:2497)
at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1319)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.com$sksamuel$scapegoat$InspectionContext$Traverser$$super$traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.continue(Inspection.scala:48)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.continue(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.inspect(UnsafeContains.scala:19)
at com.sksamuel.scapegoat.InspectionContext$Traverser$class.traverse(Inspection.scala:58)
at com.sksamuel.scapegoat.inspections.collections.UnsafeContains$$anon$2$$anon$1.traverse(UnsafeContains.scala:9)
at com.sksamuel.scapegoat.ScapegoatComponent$Transformer$$anonfun$transform$1.apply(plugin.scala:84)
at com.sksamuel.scapegoat.ScapegoatComponent$Transformer$$anonfun$transform$1.apply(plugin.scala:82)
at scala.collection.immutable.List.foreach(List.scala:381)
at com.sksamuel.scapegoat.ScapegoatComponent$Transformer.transform(plugin.scala:82)
at com.sksamuel.scapegoat.ScapegoatComponent$Transformer.transform(plugin.scala:78)
at scala.tools.nsc.ast.Trees$Transformer.transformUnit(Trees.scala:147)
at scala.tools.nsc.transform.Transform$Phase.apply(Transform.scala:30)
at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:410)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:377)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:377)
at scala.collection.Iterator$class.foreach(Iterator.scala:743)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1177)
at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:377)
at com.sksamuel.scapegoat.ScapegoatComponent$$anon$1.run(plugin.scala:62)
at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1557)
at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1542)
at scala.tools.nsc.Global$Run.compileSources(Global.scala:1537)
at scala.tools.nsc.Global$Run.compile(Global.scala:1644)
at xsbt.CachedCompiler0.run(CompilerInterface.scala:123)
at xsbt.CachedCompiler0.run(CompilerInterface.scala:99)
at xsbt.CompilerInterface.run(CompilerInterface.scala:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:102)
at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:48)
at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:41)
at sbt.compiler.AggressiveCompile$$anonfun$3$$anonfun$compileScala$1$1.apply$mcV$sp(AggressiveCompile.scala:99)
at sbt.compiler.AggressiveCompile$$anonfun$3$$anonfun$compileScala$1$1.apply(AggressiveCompile.scala:99)
at sbt.compiler.AggressiveCompile$$anonfun$3$$anonfun$compileScala$1$1.apply(AggressiveCompile.scala:99)
at sbt.compiler.AggressiveCompile.sbt$compiler$AggressiveCompile$$timed(AggressiveCompile.scala:166)
at sbt.compiler.AggressiveCompile$$anonfun$3.compileScala$1(AggressiveCompile.scala:98)
at sbt.compiler.AggressiveCompile$$anonfun$3.apply(AggressiveCompile.scala:143)
at sbt.compiler.AggressiveCompile$$anonfun$3.apply(AggressiveCompile.scala:87)
at sbt.inc.IncrementalCompile$$anonfun$doCompile$1.apply(Compile.scala:39)
at sbt.inc.IncrementalCompile$$anonfun$doCompile$1.apply(Compile.scala:37)
at sbt.inc.IncrementalCommon.cycle(Incremental.scala:99)
at sbt.inc.Incremental$$anonfun$1.apply(Incremental.scala:38)
at sbt.inc.Incremental$$anonfun$1.apply(Incremental.scala:37)
at sbt.inc.Incremental$.manageClassfiles(Incremental.scala:65)
at sbt.inc.Incremental$.compile(Incremental.scala:37)
at sbt.inc.IncrementalCompile$.apply(Compile.scala:27)
at sbt.compiler.AggressiveCompile.compile2(AggressiveCompile.scala:157)
at sbt.compiler.AggressiveCompile.compile1(AggressiveCompile.scala:71)
at sbt.compiler.AggressiveCompile.apply(AggressiveCompile.scala:46)
at sbt.Compiler$.apply(Compiler.scala:75)
at sbt.Compiler$.apply(Compiler.scala:66)
at sbt.Defaults$.sbt$Defaults$$compileTaskImpl(Defaults.scala:770)
at sbt.Defaults$$anonfun$compileTask$1.apply(Defaults.scala:762)
at sbt.Defaults$$anonfun$compileTask$1.apply(Defaults.scala:762)
at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:42)
at sbt.std.Transform$$anon$4.work(System.scala:64)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
at sbt.Execute.work(Execute.scala:244)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:160)
at sbt.CompletionService$$anon$2.call(CompletionService.scala:30)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
For standalone projects (i.e. not libraries), unused public methods are a nuisance that can be hard to track down.
Possibly scapegoat
could detect these and warn?
The difficulty with this inspection is that it is completely inapplicable to many projects (i.e. those intended as libraries).
val nonNil = items.filter {
case (s, NilAtom) => false
case (s, SExpList(items)) if items.isEmpty => false
case _ => true
}
Is reporting the first two cases as duplicate
result match {
case Success(value, next) => value
case Failure(errMsg, next) =>
println(errMsg)
NilAtom
case Error(errMsg, next) =>
println(errMsg)
NilAtom
}
As far as I understand these matches cannot be combined (i.e you cant do Failure(s,n) | Error(s,n)
as you lose the ability to access s.
Info Class name not recommended com.sksamuel.scapegoat.inspections.naming.ClassNames
Class names should begin with uppercase letter (bad = $anon)
reported on an anonymous class:
classReader.accept(new ClassVisitor(Opcodes.ASM5) {
override def visitSource(source: String, debug: String) {
....
I thought I was doing well getting the warnings down,then up updated to 0.90.11 ;) )
I've got a lot (>100) AvoidOperatorOverload warnings all over the code, in really odd places such as:
case class CallCompletionReq(id: Int)
case class TypeAtPointReq(file: File, range: OffsetRange)
reports the first line once and the second line twice.
Reports "Use of asInstanceOf", "Class name not recommended" and "Avoid operator overload"
There are many times when you need to check if something is null (either with a direct comparison or through a match statement), especially when dealing with Java. This should not throw a warning.
Absolute links for right side navigation (class links) are broken.
I generate coverage on virtual machine and when viewing reports on host machine left side package links are pointing to href="com/package.html"
class links on right side are pointing to href="/mnt/scala/project/project-common/target/scala-2.10/scoverage-report/com/ApplicationConfig.scala.html"
It would be nice to have a changelog in the readme - to keep track of all the cool features being added.
Seq(file)
(ensime, FileUtil.scala:56)
or
Seq(AbstractFile.getFile(f))
(ensime, FileUtil.scala:110)
reports
Info Prefer Seq.empty com.sksamuel.scapegoat.inspections.collections.PreferSeqEmpty Seq[T]() creates a new instance. Consider Set.empty which does not allocate a new object. scala.collection.Seq.apply[java.io.File]
I guess its thinking that Seq.apply(x)
is Seq.apply()
Reported by @RichardBradley
Code like this:
<xml>{myVariable}</xml>
Generates "var used: var $tmpscope: scala.xml.NamespaceBinding = $scope"
If a class/def has multiple type parameters, one being "empty" and one containing a bound then this check incorrectly flags it. An example:
trait TestTrait
class Test1[A, B <: TestTrait]() {} // Throws warning
class Test2[B <: TestTrait]() {} // Works fine
As suggested by @RichardBradley add an annotation to ignore sections of code.
Last one for tonight, and a weird one:
Set[T]() creates a new instance. Consider Set.empty which does not allocate a new object. scala.this.Predef.Set.apply[String]
On ensime Server.scala:25 ->
private val blacklist = Set("sun.", "java.", "scala.Console", "scala.Predef")
In some cases, particularly no-arg case classes, it is possible to create match
blocks that look for type literals when an unapply matcher was intended.
Perhaps scapegoat
could detect this and warn?
e.g.
case class Deletion()
class DeletorActor extends Actor {
override def receive = {
case Deletion =>
println("this is never hit, as it looks for people sending us classOf[Deletion]")
}
}
Reported by @RichardBradley
We have an abstract method:
def xml(sessionId: Option[String]): Elem
which generates "Unused method parameter (val sessionId: Option[String] = _) at xml"
The message output on MaxParameters is broken.
Info Max parameters com.sksamuel.scapegoat.inspections.MaxParameters
Method $name has ${vparams.size} parameters. Consider refactoring to a containing instance.
I believe you have forgotten an 's' .
Generally you are doing something wrong if you have them, so why not?
This has been there in there since at least the previous version.
Warning Zero numerator com.sksamuel.scapegoat.inspections.math.ZeroNumerator
Dividing zero by any number will always return zero
reports on:
state.getBoost * (1F / state.getLength)
Whilst I accept that state.getBoost could in theory be 0 I'm not quite sure that what the rule is aiming for.
The below triggers a RepeatedCaseBody w
sym match {
case NoSymbol => None
case sym: Symbol => Some(sym)
case _ => None
}
I don't think there is a way to reorganise this to avoid the duplication. As NoSymbol is a instance of Symbol.
This warns that the var is never used, but it could be inside the if
def test(b: Boolean): Int = {
var count = 0
if (b) count += 1
// if (b) count = count + 1 // This also fails
count
}
Parameterless methods returns unit reported in async macro
Var usage is convenient in Akka Actors. But scapegoat reports warnings for them.
TClient.this.executecom.fasterxml.jackson.databind.JsonNode(reflect.this.ManifestFactory.classTypecom.fasterxml.jackson.databind.JsonNode).map[Seq[com.x.transaction.x.FinancialService]](((x0$4: scalaz.ValidationNel[com.x.transaction.x.TuxedoResponse,com.fasterxml.jackson.databind.JsonNode]) => x0$4 match { case (a: com.fasterxml.jackson.databind.JsonNode)scalaz.Success[scalaz.NonEmptyList[com.x.transact
case class Undo(id: Int, summary: String, changes: List[FileEdit])
(ensime, Project.scala:49)
Reports
Info Empty case class com.sksamuel.scapegoat.inspections.EmptyCaseClassInspection
Empty case class can be rewritten as a case object
This should only refer to the pattern
case class Foo()
It looks like Scala-core have recently come up with the same idea as scapegoat
and are busy implementing their own scalac plugin that also duplicates Findbugs: https://github.com/scala/scala-abide
It might be worth hacking on that instead, as it's likely to capture scapegoat
's mindshare / user base, since it is backed by the core scala team.
(No-one else seems interested in adapting Findbugs for Scala; everyone seems to want to reinvent the wheel. Maybe I'll moan about that on the Scala mailing list.)
private val knownPackages = new mutable.HashSet[String]()
knownPackages += packName
Reports itself as a Expression as Statement warning - which (whilst true, as the expression returns 'this' for chaining), is not really an error.
What is "BrokenOddness" checking for?
The warning could do with clarifying.
Are you saying that i % 2 == 1
should always be replaced with i & 0x1 == 1
? If so, I think you should a) clarify the warning to suggest that alternate form and b) cite some evidence, as opinion appears to be divided on the matter.
... also the rule doesn't check for tests like i % 2 == 0
Reported by @RichardBradley
The following actor Receive method triggers AsInstanceOf warnings
def receive: Receive = LoggingReceive {
case requestStart: ChunkedRequestStart =>
// start by establishing a new HTTP connection
val host = requestStart.request.uri.authority.host.address
val port = requestStart.request.uri.authority.port
ioActor ! Http.Connect(host, port)
owner = sender()
context.become(connecting(requestStart))
}
Use of asInstanceOf com.sksamuel.scapegoat.inspections.unsafe.AsInstanceOf
asInstanceOf used near tr.get.asInstanceOf[com.x.x.x.FinancialService]. Consider using pattern matching.
Curently it contains a count of errors and warnings - would be good if info count was included too.
Prefer Seq.empty com.sksamuel.scapegoat.inspections.collections.PreferSeqEmpty
SeqT creates a new instance. Consider Set.empty which does not allocate a new object. collection.this.Seq.apply[com.x.x.x.RqParam]
e.g. with Play, finds "Use of asInstanceOf" in target/scala-2.11/src_managed/main/routes_routing.scala
(maybe a bug for the related sbt plugin?)
LonelySealedTrait appears to be triggering more often than it should. E.g. in the below SExp is being marked:
(ensime SExp.scala)
sealed trait SExp extends WireFormat ...
...
case class SExpList(items: List[SExp]) extends SExp with Iterable[SExp] {
... // more implementations...
Suggested new inspection: warn for strings that look like they ought to be interpolated but aren't, e.g.
try {
require(false, "inner exception details here")
} catch {
case NonFatal(e) =>
throw new IOException("Error attempting foo: $e")
}
i.e. if a non-interpolated string contains "$foo" when there is a variable named "foo" in scope, warn that you need to add "s" to make the string interpolated.
Here is something I do quite a bit.
I'll have
a match {
case Some(b) =>
case None =>
}
And then I'll add a guard to the some because something has changed
a match {
case Some(b) if b .... =>
case None =>
}
And now I don't have a full match, and if my unit tests aren't sufficient I can get a match error later on. Does anyone else do this?
Enumeration isn't particular elegant, and most people just use case objects. I need to find an article that explains why enumeration should be avoided as the justification in the inspection.
AvoidOperatorOverload warning being generated (100s)
Info Avoid operator overload com.sksamuel.scapegoat.inspections.style.AvoidOperatorOverload
Scala style guide advocates against using operators as method names, except in special circumstances. See http://docs.scala-lang.org/style/naming-conventions.html#symbolic-method-names
Is being reported in very weird places (see comments):
case class TypeSearchResult(
name: String, // this line
localName: String, // this line
declaredAs: scala.Symbol, // this line
pos: Option[(String, Int)]) extends SymbolSearchResult // this line
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.