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")
Добавьте Linter в свой проект, обновив свой pom.xml в разделе «CompilerPlugin».
<configuration>
<compilerPlugins>
<compilerPlugin>
<groupId>org.psywerx.hairyfotr</groupId>
<artifactId>linter_2.11</artifactId>
<version>0.1.17</version>
</compilerPlugin>
</compilerPlugins>
</configuration>
Используйте свой обычный метод строительства и плагин предупреждения Дженкинса.
Другой возможный способ использования 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"
Примечание. Установите 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, маловероятное экологичность, uselog1p, uselog10, useexpm1, usehypot, usecbrt, users qrt, soipiciouspow, useexp, useabsnotsqrtsquare, userisnannot selfomporse, useisnannotnancomprison, используйте, bigdecimalbressformatrisom, bigdemalecimalprisomalpercimalpricasimalprecimalpricam ReflexiveAssignment, CloseSourceFile, JavaConverters, ContainsTypeMismatch, NumberInstanceOf, PatternMatchConstant, PreferIfToBooleanMatch, IdenticalCaseBodies, IdenticalCaseConditions, ReflexiveComparison, YodaConditions, UseConditionDirectly, UseIfExpression, UnnecessaryElseBranch, DuplicateIfBranches, Идентификация кончиков, MERGENSETIFS, VARIABLEASSIGNEDUNUSEVALUE, MALFORDSWAP, идентичный кондиционер, идентификации, IndexingWithNegativenumber, опция, undesirabletypeinference, ussingoptiontonull, wroudnulthoption, reseoptionStrings, избегание. USEOPTIONGETORELSE, USEEXISTSNOTFINDISDEFINED, useExistsnotfilterisempty, usefindnotfilterhead, usecontainsnotexist sequals, usequantifierfuncnotfold, usefuncnotreduce, usefuncnotfold, mergemaps, funcfirstthenmap, filterfirtthensort, usemraxort d USEMAPNOTFLATMAP, USEFILENTERNOTFLATMAP, ESELOPTIONMETHOD, TransformNotMap, DuplickeKeyInmap, неэффективное оформление, одноэверное воздействие, intdivisionAssignedtofloat, useflattennotfilteroption, useCountnotfilterlenge, useflattennotfilteroption, usecountnotfilterlenge, useflattennotfilter PassPartialFunctionDirectly, UnitImplicitorDing, REGEXWARNNE, InvarianTcondition, DecposingEmptyCollection, Invariantextrema, ненужногометодкол, продюсируйте, эмптиколликция, операционные пути, продуцирующие, модулобион, дивидеби, dividebyzero, ZeroDivideby InvalidParamToRandomNextInt, UnusedForLoopIteratorValue, StringMultiplicationByNonPositive, LikelyIndexOutOfBounds, UnnecessaryReturn, InvariantReturn, UnusedParameter, InvalidStringFormat, InvalidStringConversion, UnnecessaryStringNonEmpty, UnnecessaryStringIsEmpty, PossibleLossOfPrecision, Неоседания, типотип, пустотечный интерполятор, маловероятное времятостроирование, unthrownexception, подозрительные матча, прохождение. UseHeadOptionNotif, uselaStoptionNotif, usezipwithindexnotzipindices, usegetorelseNotPatMatch, useOrelsEnotPatmatch, usesOptionFlatMapnotPatmatch, useOptionMapnotPatmatch, useOptionLattenNotPatMatch, usePoptionFatePatePatePatePatePatePatePatePatePatePatePatePatmatch USEOPTIONISEMPTYNOTPATMATCH, USEOPTIORNOTNOTPATMATCH, USEOPTIONEXISTSNOTPATMATCH
Ссылки выше в настоящее время перейдут в тест на эту проверку.
Еще один файл для проверки - 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) вместо 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) )Списки правил из других инструментов статического анализа: