Linter是Scala静态分析编译器插件,可为各种可能的错误,效率低下和样式问题添加编译时间检查。
请帮助支持Linter的开发。
通过将此行附加到您的build.sbt :
addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1.17")
如果您始终想进行最新的更改,也可以使用快照:
resolvers += Resolver.sonatypeRepo("snapshots")
addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1-SNAPSHOT")
通过使用“ CompilerPlugin”部分更新pom.xml ,将Linter添加到您的项目中。
<configuration>
<compilerPlugins>
<compilerPlugin>
<groupId>org.psywerx.hairyfotr</groupId>
<artifactId>linter_2.11</artifactId>
<version>0.1.17</version>
</compilerPlugin>
</compilerPlugins>
</configuration>
使用通常的建筑方法和Jenkins警告插件。
使用Linter的另一种可能方法是手动下载并使用这些快照罐:
Scala 2.12,Scala 2.11,Scala 2.10,
Scala 2.9.3(过时)
terminal:
scalac -Xplugin:<path-to-linter-jar>.jar ...
sbt: (in build.sbt)
scalacOptions += "-Xplugin:<path-to-linter-jar>.jar"
maven: (in pom.xml inside scala-maven-plugin configuration)
<configuration>
<args>
<arg>-Xplugin:<path-to-linter-jar>.jar</arg>
</args>
</configuration>
注意:如果您有其他构建工具或IDE的说明,请提出拉请请求。
在输出中禁用显示检查名称的要使用printWarningNames Switch:
scalacOptions += "-P:linter:printWarningNames:false"
注意:默认情况下设置为True,因为版本为0.1.17
可以使用分隔的支票名称列表禁用检查:
scalacOptions += "-P:linter:disable:UseHypot+CloseSourceFile+OptionOfOption"
或只能使用以下方式启用特定的检查:
scalacOptions += "-P:linter:enable-only:UseHypot+CloseSourceFile+OptionOfOption"
如果您认为某些警告是误报,则可以通过代码注释忽略它们:
scala > val x = math.pow( 5 , 1 / 3d ) + 1 / 0 // linter:ignore UseCbrt,DivideByZero // ignores UseCbrt and DivideByZero
< console > : 8 : warning : Integer division detected in an expression assigned to a floating point variable.
math.pow( 5 , 1 / 3d ) + 1 / 0 // linter:ignore UseCbrt,DivideByZero // ignores UseCbrt and DivideByZero
^
scala > val x = math.pow( 5 , 1 / 3d ) + 1 / 0 // linter:ignore // ignores all warnings注意:请考虑报告假阳性,以便可以在以后的版本中删除它们。
UnextendedSealedTrait, UnlikelyEquality, UseLog1p, UseLog10, UseExpm1, UseHypot, UseCbrt, UseSqrt, SuspiciousPow, UseExp, UseAbsNotSqrtSquare, UseIsNanNotSelfComparison, UseIsNanNotNanComparison, UseSignum, BigDecimalNumberFormat, BigDecimalPrecisionLoss, ReflexiveAssignment, CloseSourceFile, JavaConverters, ContainsTypeMismatch, NumberInstanceOf, PatternMatchConstant, PreferIfToBooleanMatch, IdenticalCaseBodies, IdenticalCaseConditions, ReflexiveComparison, YodaConditions, UseConditionDirectly, UseIfExpression, UnnecessaryElseBranch, DuplicateIfBranches,相同的条件,MergenestEdifs,variaBleasSignEdunusedValue,畸形,相同的条件,相同的条件,相同的拟合,索引indexingNneGativenTiviNumber,optionofoption,deSirableBableTypeInfere UseGetOrElseOnOption, UseOptionOrNull, UseOptionGetOrElse, UseExistsNotFindIsDefined, UseExistsNotFilterIsEmpty, UseFindNotFilterHead, UseContainsNotExistsEquals, UseQuantifierFuncNotFold, UseFuncNotReduce, UseFuncNotFold, MergeMaps, FuncFirstThenMap, FilterFirstThenSort, UseMinOrMaxNotSort, UseMapNotFlatMap, UseFilterNotFlatMap, AvoidOptionMethod, TransformNotMap, DuplicateKeyInMap, InefficientUseOfListSize, OnceEvaluatedStatementsInBlockReturningFunction, IntDivisionAssignedToFloat, UseFlattenNotFilterOption, UseCountNotFilterLength, UseExistsNotCountCompare, PassPartialFunctionDirectly, UnitImplicitOrdering, RegexWarning, InvariantCondition, DecomposingEmptyCollection, InvariantExtrema, UnnecessaryMethodCall, ProducesEmptyCollection, OperationAlwaysProducesZero, ModuloByOne, DivideByOne, DivideByZero, ZeroDivideBy, UseUntilNotToMinusOne, InvalidParamToRandomNextInt, UnusedForLoopIteratorValue, StringMultiplicationByNonPositive, LikelyIndexOutOfBounds, UnnecessaryReturn, InvariantReturn, UnusedParameter, InvalidStringFormat, InvalidStringConversion, UnnecessaryStringNonEmpty, UnnecessaryStringIsEmpty, PossibleLossOfPrecision, UnsafeAbs, TypeToType, EmptyStringInterpolator, UnlikelyToString, UnthrownException, SuspiciousMatches, PassingNullIntoOption, IfDoWhile, FloatingPointNumericRange, UseInitNotReverseTailReverse, UseTakeRightNotReverseTakeReverse, UseLastNotReverseHead, UseFuncNotReverse, UseHeadNotApply, UseLastNotApply, UseHeadOptionNotIf, UseLastOptionNotIf, UseZipWithIndexNotZipIndices, UseGetOrElseNotPatMatch, UseOrElseNotPatMatch, UseOptionFlatMapNotPatMatch, UseOptionMapNotPatMatch, UseOptionFlattenNotPatMatch, UseOptionForeachNotPatMatch,UseOptionisDefinednotPatMatch,useoptionisemptynotpatMatch,useoptionforallnotpatMatch,useoptionexistsnotpatMatch
上面的链接当前转到该检查的测试。
要查看的另一个文件是警告。Scala
scala > if (a == 10 || b == 10 ) 0 else if (a == 20 && b == 10 ) 1 else 2
< console > : 10 : warning : This condition has appeared earlier in the if - else chain and will never hold here.
if (a == 10 || b == 10 ) 0 else if (a == 20 && b == 10 ) 1 else 2
^ scala > if (b > 4 ) ( 2 ,a) else ( 2 ,a)
< console > : 9 : warning : If statement branches have the same structure.
if (b > 4 ) ( 2 ,a) else ( 2 ,a)
^ scala > if (a == b) true else false
< console > : 9 : warning : Remove the if expression and use the condition directly.
if (a == b) true else false
^scala > (x,y) match { case (a, 5 ) if a > 5 => 0 case (c, 5 ) if c > 5 => 1 }
< console > : 10 : warning : Identical case condition detected above. This case will never match .
(x,y) match { case (a, 5 ) if a > 5 => 0 case (c, 5 ) if c > 5 => 1 }
^ scala > a match { case 3 => " hello " case 4 => " hello " case 5 => " hello " case _ => " how low " }
< console > : 9 : warning : Bodies of 3 neighbouring cases are identical and could be merged.
a match { case 3 => " hello " case 4 => " hello " case 5 => " hello " case _ => " how low " }
^ scala > bool match { case true => 0 case false => 1 }
< console > : 9 : warning : Pattern matching on Boolean is probably better written as an if statement.
a match { case true => 0 case false => 1 }
^scala > for (i <- 10 to 20 ) { if (i > 20 ) " " }
< console > : 8 : warning : This condition will never hold.
for (i <- 10 to 20 ) { if (i > 20 ) " " }
^ scala > for (i <- 1 to 10 ) { 1 / (i - 1 ) }
< console > : 8 : warning : You will likely divide by zero here.
for (i <- 1 to 10 ) { 1 / (i - 1 ) }
^ scala > { val a = List ( 1 , 2 , 3 ); for (i <- 1 to 10 ) { println(a(i)) } }
< console > : 8 : warning : You will likely use a too large index.
{ val a = List ( 1 , 2 , 3 ); for (i <- 1 to 10 ) { println(a(i)) } }
^scala > for (i <- 10 to 20 ) { if (i.toString.length == 3 ) " " }
< console > : 8 : warning : This condition will never hold.
for (i <- 10 to 20 ) { if (i.toString.length == 3 ) " " }
^ scala > { val a = " hello " + util. Random .nextString( 10 ) + " world " + util. Random .nextString( 10 ) + " ! " ; if (a contains " world " ) " " ; if (a startsWith " hell " ) " " }
< console > : 8 : warning : This contains will always returns the same value : true
{ val a = " hello " + util. Random .nextString( 10 ) + " world " + util. Random .nextString( 10 ) + " ! " ; if (a contains " world " ) " " ; if (a startsWith " hell " ) " " }
^
< console > : 8 : warning : This startsWith always returns the same value : true
{ val a = " hello " + util. Random .nextString( 10 ) + " world " + util. Random .nextString( 10 ) + " ! " ; if (a contains " world " ) " " ; if (a startsWith " hell " ) " " }
^ scala > str.replaceAll( " ? " , " . " )
< console > : 9 : warning : Regex pattern syntax error : Dangling meta character '?'
str.replaceAll( " ? " , " . " )
^log(1 + a)代替log1p(a) scala > math.log( 1d + a)
< console > : 9 : warning : Use math.log1p(x), instead of math.log( 1 + x) for added accuracy when x is near 0 .
math.log( 1 + a)
^ scala > BigDecimal ( 0.555555555555555555555555555 )
< console > : 8 : warning : Possible loss of precision. Literal cannot be represented exactly by Double . ( 0.555555555555555555555555555 != 0.5555555555555556 )
BigDecimal ( 0.555555555555555555555555555 )
^scala > val a = Some ( List ( 1 , 2 , 3 )); if (a.size > 3 ) " "
< console > : 9 : warning : Did you mean to take the size of the collection inside the Option ?
if (a.size > 3 ) " "
^ scala > if (strOption.isDefined) strOption.get else " "
< console > : 9 : warning : Use strOption.getOrElse(...) instead of if (strOption.isDefined) strOption.get else ...
if (strOption.isDefined) strOption.get else " "
^scala > List ( 1 , 2 , 3 , 4 ).find(x => x % 2 == 0 ).isDefined
< console > : 8 : warning : Use col.exists(...) instead of col.find(...).isDefined.
List ( 1 , 2 , 3 , 4 ).find(x => x % 2 == 0 ).isDefined
^ scala > List ( 1 , 2 , 3 , 4 ).flatMap(x => if (x % 2 == 0 ) List (x) else Nil )
< console > : 8 : warning : Use col.filter(x => condition) instead of col.flatMap(x => if (condition) ... else ...).
List ( 1 , 2 , 3 , 4 ).flatMap(x => if (x % 2 == 0 ) List (x) else Nil )
^scala > def func ( b : Int , c : String , d : String ) = { println(b); b + c }
< console > : 7 : warning : Parameter d is not used in method func
def func ( b : Int , c : String , d : String ) = { println(b); b + c }
^ contains scala > List ( 1 , 2 , 3 ).contains( " 4 " )
< console > : 29 : warning : List [ Int ].contains( String ) will probably return false , since the collection and target element are of unrelated types.
List ( 1 , 2 , 3 ).contains( " 4 " )
^ == scala > Nil == None
< console > : 29 : warning : Comparing with == on instances of unrelated types (scala.collection.immutable. Nil . type , None . type ) will probably return false .
Nil == None
^ 随意添加自己的想法或实施这些想法。欢迎拉请求!
var a = 4; { val a = 5 } )func("arg1", force = true) )来自其他静态分析工具的规则列表: