Linter는 스칼라 정적 분석 컴파일러 플러그인으로 다양한 가능한 버그, 비 효율성 및 스타일 문제에 대한 컴파일 타임 검사를 추가합니다.
Linter의 개발을 지원하도록 도와주세요.
이 라인을 build.sbt 에 추가하여 프로젝트에 Linter를 추가하십시오.
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 스위치를 사용하십시오.
scalacOptions += "-P:linter:printWarningNames:false"
참고 : 버전 0.1.17 이후 기본적으로 TRUE로 설정하십시오
플러스 분리 된 확인 이름 목록을 사용하여 수표를 비활성화 할 수 있습니다.
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, Unlilequality, Uselog1p, Uselog10, Uselog10, UseExpm1, UseHypot, Usecbrt, useqrt, suspiciouspow, useabsnotsqrtsquare, usenannotselfcomparison, useisnannotnancomparison, aingsignum, bigdecimallorformat, bigdecimallorformat, bigdecimallorformat RefleIveAssignment, CloseSourceFile, JavaconVerters, InstypeMistimatch, NumberInstanceof, PatternMatchConstant, PreferiftObooleanMatch, 동일한 케이스 보드, 동일한 CASECONDITIONS, REDICIVECOMPARISIS, YODANDITIONS, USECONDITION DIRECTLY, WITELIFERCONCONT, UNNECESLANCONCENT, UNNECESCENCENTIFON, UNNECERCENTIFINIFINIFINIFINIFING, UNNECERCENTION. mergenestedifs, variableAssignedUnousedValue, 층간 스웨이, 동일한 식별, 동일한 기간, 옵션 옵션, 옵션, 옵션, 과도한 교차점, antadyOptiontonUll, wrapNullWithOption, reviptionstringsize, intuePtionEption, usingToptionOnOption, usingToneTorToptionOnOption, usingToneTortoneToptionOnOption, 사용 useexistsNotFindIsDiSDefined, useExistSnotFilterIsempty, useeContainsNotexistSequals, usequantifierFuncNotfold, usePuncNotReduce, usefuncNotfold, mergemaps, funcfirstthenmap, filterfirstthensort, usemnotort, usemnotsort, usemnotsort, usemnotsort, mergemaps, mergemaps. usefilternotflatmap, feaptionmethod, transformNotMap, duplyKeyInMap, inferficientSublistSize, evaluatedStatementSinBlockReturningFunction, intDivisionAssignEdTofLoat, useflattennotFilterOption, useCountnotFileTlergent, useeCountFilectISticscomPare, passPartialFunistScompare Unitimplicitorderding, RegexWarning, Invariantcondition, DecomposingEmptyCollection, Invariantextrema, 불필요한 메트로 드 콜, 제작, OperationalWaysProduceSzero, Modulobyone, DivideByOne, DivideByzero, Zerodivideby, invaldilnottominusone, invalidamtorandomnextint, dividebyone, dividebyone, dividebyone, dividebyone. 사용되지 않은 forloopiteratorvalue, stringmultiplicationbalue, 가능성이 높고, 불필요한, 불필요한, 불법 복제, 불가사의, 유효하지 않은, 유효하지 않은, 유효하지 않은, 불필요한, 불필요한 지시, 불필요한, 불안정한, 불안정, 불안정, 시대성, 초대형, 초대형, 초대형, 초대형, 초대형, 불안정. VELMSTRINGTRINGINTERPOLATOR, UNLILETOSTRING, UNTROWNEXCEPTION, 의심스러운 모칭, PassingNullIntooftion, ifdowhile, FloatingPointNumericRange, useInitNotReversEtailReverse, UsetakerIGHTNOTREVERSETAKEREVERES, USELASTNOTREVERSEHEAD, USELASTNOTREVERSEHEARVERES, USELASTNOTREVERISE, 사용 HEADHEARVERY, USELASTNOTPAPPLY, USELASTNOTNOTNOTNOTNOTPAPPLY, 사용 USELASTOPTIONNOTIF, USEZIPWITHINDEXNOTZIPINDICES, USEGETORELSENOTPATMATCH, USEORELSENOTPATMATCH, USEOPTIONFTIONFTIONFTIONMAPNOTPATMATCH, USEOPTIONMAPNOTPATMATCH, useOptionFlatttenNotPatMatch, UseOptionForeCHEACHNOTPATMATCH, useOptionORCHEACHNOTPATMATCH, 사용 useoptionisemptynotpatmatch, useoptionforallnotpatmatch, useoptionexistsnotpatmatch
위의 링크는 현재 해당 수표를 테스트합니다.
체크 아웃 할 또 다른 파일은 경고입니다
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( " ? " , " . " )
^log1p(a) log(1 + 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) )다른 정적 분석 도구의 규칙 목록 :