LINTER adalah plugin kompiler analisis statis scala yang menambahkan pemeriksaan waktu kompilasi untuk berbagai kemungkinan bug, inefisiensi, dan masalah gaya.
Tolong bantu mendukung pengembangan linter.
Tambahkan linter ke proyek Anda dengan menambahkan baris ini ke build.sbt Anda:
addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1.17")
Jika Anda selalu ingin memiliki perubahan terbaru, snapshot juga tersedia:
resolvers += Resolver.sonatypeRepo("snapshots")
addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1-SNAPSHOT")
Tambahkan linter ke proyek Anda dengan memperbarui pom.xml Anda dengan bagian "compilerplugin".
<configuration>
<compilerPlugins>
<compilerPlugin>
<groupId>org.psywerx.hairyfotr</groupId>
<artifactId>linter_2.11</artifactId>
<version>0.1.17</version>
</compilerPlugin>
</compilerPlugins>
</configuration>
Gunakan metode bangunan biasa dan plugin Jenkins Warnings.
Cara lain yang mungkin untuk menggunakan linter adalah dengan mengunduh secara manual dan menggunakan stoples snapshot ini:
Scala 2.12, Scala 2.11, Scala 2.10,
Scala 2.9.3 (usang)
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>
Catatan: Jika Anda memiliki instruksi untuk alat bangunan atau IDE lain, silakan buat permintaan tarik.
Untuk menonaktifkan menampilkan nama cek di output, gunakan sakelar printwarningnames:
scalacOptions += "-P:linter:printWarningNames:false"
Catatan: Setel ke true secara default sejak versi 0.1.17
Cek dapat dinonaktifkan menggunakan daftar nama cek yang dipisahkan ditambah:
scalacOptions += "-P:linter:disable:UseHypot+CloseSourceFile+OptionOfOption"
Atau hanya pemeriksaan spesifik yang dapat diaktifkan menggunakan:
scalacOptions += "-P:linter:enable-only:UseHypot+CloseSourceFile+OptionOfOption"
Jika Anda yakin beberapa peringatan adalah positif palsu, Anda dapat mengabaikannya dengan komentar kode:
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 warningsCatatan: Harap pertimbangkan untuk melaporkan positif palsu sehingga dapat dihapus di versi mendatang.
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, IdenticalIfElseCondition, MergeNestedIfs, VariableAssignedUnusedValue, MalformedSwap, IdenticalIfCondition, IdenticalStatements, IndexingWithNegativeNumber, OptionOfOption, UndesirableTypeInference, AssigningOptionToNull, WrapNullWithOption, AvoidOptionStringSize, AvoidOptionCollectionSize, UseGetOrElseOnOption, UseOptionOrNull, UseOptionGetOrElse, UseExistsNotFindIsDefined, UseExistsNotFilterIsEmpty, UseFindNotFilterHead, UseContainsNotExistsEquals, UseQuantifierFuncNotFold, UseFuncNotReduce, UseFuncNotFold, MergeMaps, FuncFirstThenMap, FilterFirstThenSort, Useminormaxnotsort, usemapnotflatmap, usefilternoTflatMap, hindariOptionMethod, transformnotmap, duplicateKeyInmap, inefisieneFlistSize, outevalatedstatenmentnotennotnoRfunction, IntdivisionSignedtofloat, UsefLattennotnotnoRFunction, IntdivisionSignedtofloat, UseflattennotnotnotnoFunction, IntdivisionSignedtofloat, UsefLattennotnotnotulrunction, IntdivisionSignedtofloat, UsefLattennoNotnoTnoNtnoCteri UseExistsnotcountCompare, PasspartialFunctionDirectly, UnitImplicitordering, Regexwarning, InvariantCondition, DecompositionCollection, InvariantExtrema, UncnecessaryMethodCall, DivideByOdone, OperationalWays Produceszero, ModulobyO - Useuntilnottominusone, InvalidParamtorandomnextint, tidak digunakan untuk keyakinan, stringMultiplicationByNonPositive, kemungkinan tidak akan ada di luar, tidak ada yang tidak terkalir, tidak digunakan lagi, tidak ada gunanya, invalidasi, konversi yang tidak masuk akal, tidak ada gunanya, invalidstring -confersion, valid -tidak divalidasi, invalidstring, validstring -inidstring, PossibleLossOfPrecision, UnsafeAbs, TypeToType, EmptyStringInterpolator, UnlikelyToString, UnthrownException, SuspiciousMatches, PassingNullIntoOption, IfDoWhile, FloatingPointNumericRange, UseInitNotReverseTailReverse, UseTakeRightNotReverseTakeReverse, UseLastNotReverseHead, Usefuncnotreverse, UseEadnotApply, UselastNotApply, UseEadOptionNotif, UselastOptionNotif, UseZipWithIndexnotzipindices, UsegetorelsEnotpatmatch, UseorelsEnotpatmatch, UseOptionFlatMapMangkat, UseorelsEnotpatmatch, UseOptionFlatMapMangkat, UseOmPATATCATCH, USOOPPATATCATCH, USOOPPATATCATCH, USOOPPATATCATCH, USOOPPATATCATCATCATCATCATCATCATCATKMATCATKMATCATCATKMATCATCATKMATCATKMATCATKMATCATKMATCATKMATCATCAT UseOptionFlatnotPatMatch, UseOptionForeachNotPatMatch, UseOptionisDefinedNotPatMatch, UseOptionIsemptynotpatmatch, UseOptionForAllNotPatmatch, UseOptionexistNotPatMatch
Tautan di atas saat ini pergi ke tes untuk cek itu.
File lain yang harus diperiksa adalah Warning.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) alih -alih 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
^ Jangan ragu untuk menambahkan ide Anda sendiri, atau mengimplementasikannya. Tarik Permintaan Selamat Datang!
var a = 4; { val a = 5 } )func("arg1", force = true) )Daftar aturan dari alat analisis statis lainnya: