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) )來自其他靜態分析工具的規則列表: