Linter عبارة عن مكون إضافي لمرجم تحليلات Scala Static يقوم بإضافة اختبارات وقت الترجمة لمختلف الأخطاء الممكنة ، وعدم الكفاءة ، ومشاكل النمط.
الرجاء المساعدة في دعم تطوير Linter.
أضف Linter إلى مشروعك عن طريق إلحاق هذا السطر بـ build.sbt :
addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1.17")
إذا كنت ترغب دائمًا في الحصول على أحدث التغييرات ، تتوفر لقطات أيضًا:
resolvers += Resolver.sonatypeRepo("snapshots")
addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1-SNAPSHOT")
أضف Linter إلى مشروعك عن طريق تحديث pom.xml الخاص بك مع قسم "برنامج التحويل البرمجي".
<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 ،
سكالا 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"
ملاحظة: قم بتعيين 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ملاحظة: يرجى النظر في الإبلاغ عن إيجابيات كاذبة حتى يمكن إزالتها في الإصدارات المستقبلية.
غير مدته ، غير محتملة ، uselog1p ، uselog10 ، useexpm1 ، usehypot ، usecbrt ، useqrt ، المشبوهة ، useexp ، useabsnotsqrtsquare ، useisnannotselscomparison ، useisnannotnancomparison ، useignum ، bigdecimalsimaltorsmalsporsmalsporsporsmalsporsporsporsmalsporsporsm. relevlexiveassignment ، closeSourceFile ، javaconverters ، invateStypemismatch ، numberInstanceof ، patternmatchconstant ، preferifictobooleanmatch ، vericalcasebodies ، falwericalcaseconds ، inflincyelparison ، yodaconditions ، useCondirective ، useAftBranced ، unsnecessaryel. متطابق inclodecondition ، mergenestedifs ، variaBleAsignedUnusedValue ، مشوه ، اطلاع متطابق ، متطابق ، indexingwithnegativenber ، خيار optOptOption ، useptioncolutions ، use -uptoreltists ، useOptionlicultions ، useOptionluctions ، useOptionluctions ، useOptionlictions ، useOptionliction. useOptiongetOrelse ، useexistsnotfindisDefined ، useexistsnotfilterisempty ، usefindnotfilterhead ، usecontainsnotexistist ، usequantifierfuncnotfold ، useminotreduce ، usefuncnotfol UsemapNotflatmap ، usefilternotflatmap ، تجنب اطلاع ، transformnotmap ، ditplicatekeyinmap ، غير فعال اطلاق ، passpartialfunctiondirectly ، unitimplicitorering ، regexwarning ، instariantcondition ، shyposposeemptycollection ، invariantextrema ، un neecessarymethodcall ، producesemptycollection ، usintlysproducsero ، modulobyone ، divideby ، dividezero ، useNtominuss ، useuntilnottomins ، useuntilnottominus ، useuntilnottomin. invalidparamtorandomNextint ، غير مستخدمة forloopiteratorvalue ، stringmultiplicationbynonpositive ، محتمل extindexoutofbounds ، unninecessaryreturn ، distaristreturn ، غير مستخدمة ، invalidstringformat Typetotype ، reghstringInterpolator ، غير محتمل ، غير متكافئ ، مشبوهة ، ممرات ، ifdowhile ، floatingpointnumericrang useheadoptionnotif ، uselastoptionnotif ، usezipwithIndexNotzipIndices ، usegetorelsenotpatmatch ، useorelsenotpatmatch ، useoptionflatmapnotpatmatch ، useOptionMapNotpatmatch ، usoOptionnotpatmatch ، useOptiStingMatch. UseOptionImptyNotPatmatch ، 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) )قوائم القواعد من أدوات التحليل الثابت الأخرى: