Linter es un complemento de compilador de análisis estático Scala que agrega verificaciones de tiempo de compilación para varios posibles errores, ineficiencias y problemas de estilo.
Ayude a apoyar el desarrollo de Linter.
Agregue el enlace a su proyecto agregando esta línea a su build.sbt :
addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1.17")
Si siempre desea tener los últimos cambios, las instantáneas también están disponibles:
resolvers += Resolver.sonatypeRepo("snapshots")
addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1-SNAPSHOT")
Agregue el enlace a su proyecto actualizando su pom.xml con una sección "CompilerPlugin".
<configuration>
<compilerPlugins>
<compilerPlugin>
<groupId>org.psywerx.hairyfotr</groupId>
<artifactId>linter_2.11</artifactId>
<version>0.1.17</version>
</compilerPlugin>
</compilerPlugins>
</configuration>
Use su método de construcción habitual y el complemento de advertencias de Jenkins.
Otra posible forma de usar el linter es descargar manualmente y usar estos frascos de instantáneas:
Scala 2.12, Scala 2.11, Scala 2.10,
Scala 2.9.3 (anticuada)
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>
Nota: Si tiene instrucciones para otra herramienta de compilación o IDE, haga una solicitud de extracción.
Para deshabilitar la visualización de los nombres de verificación en la salida Use el interruptor PRITWARNINGNAMES:
scalacOptions += "-P:linter:printWarningNames:false"
Nota: Establecer en verdadero de forma predeterminada desde la versión 0.1.17
Los cheques se pueden deshabilitar utilizando una lista separada de nombres de cheques:
scalacOptions += "-P:linter:disable:UseHypot+CloseSourceFile+OptionOfOption"
O solo se pueden habilitar cheques específicos usando:
scalacOptions += "-P:linter:enable-only:UseHypot+CloseSourceFile+OptionOfOption"
Si cree que algunas advertencias son falsas positivas, puede ignorarlas con un comentario de código:
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 warningsNota: Considere informar falsos positivos para que puedan eliminarse en futuras versiones.
UnextendedSeLEdTrait, impractelyEquality, uselog1p, uselog10, useExpm1, usehypot, usecbrt, usosqrt, sospechePow, useExP, useAbSnotsqrtSquare, usaSnannotSelfcomparison, usaSnotnotnotnotnInsparison, ussignum, bigDecimalnumberformat, BigDecisionLosssLoss,, de UseisNotnotnotnancomis, Ussignum, BigDecimalnumberformat, BigDecisionLossssLOSS, ReflexiveAssignment, CloseSourceFile, JavaConverters, ContainsTypeMismatch, NumberInstanceOf, PatternMatchConstant, PreferIfToBooleanMatch, IdenticalCaseBodies, IdenticalCaseConditions, ReflexiveComparison, YodaConditions, UseConditionDirectly, UseIfExpression, UnnecessaryElseBranch, DuplicateIfBranches, IdenticalifelSecondition, Mergenestedifs, VariABLeAsSignedUnusedValue, MalFormedSwap, Identicalifcondition, IdenticalStatements, indexingWithNegativeNumber, opción OpcionOftoPtion, UndesirableTypeInference, AsigningOptionTonull, WrapnullWitHoption, EvitToPionionstringionstrionstrion UseOptionGetorelse, useExistSnotFindisDefined, useExistSnotFilterisEmpty, UseFindNotFilterhead, useContainsNotExistSequals, UsequantifierFuncnotfold, UseFuncnotreduce, Usefuncnotfold, Mercegemaps, FUncFirstthenmap, FilterFirstThensort, USMINOMINEMINET, MIRGEMAPS, FUNCFIRSTTHENMAP, FILTRESFIRSTTHENSORT, USOMINOMINEMINET, 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, no usado de ForLoopiteratorValue, StringMultIplationBynonPositive, Probablemente INDEXOUTOFBOUNDS, innecesaryReturn, InvarianTreTurn, no utilizada, InvalidStringFormat, InvalidStringConversion, innecesyStringnonEmty, UnnecessarsystringiseMeptyy, positivo Unsfeabs, typetotype, showytringInterpolator, impunlikelyToString, unthrownException, sospecheMatches, pasenullInTooption, ifdowhile, flotatingPointNumericRange, useInitNotREVERSETSETRAVERSE, usetakerTheTReVersetakeververse, uselastnotreversehead, Usefuncnotreverse, useHeadNotEnseverse. UselastNotAply, UseHeadEptionNotif, UselAstOptionNotif, UseZipWithIndexNotZIPIndices, UsegetorelSenotPatMatch, UseOrelSenotpatMatch, UseOptionFlatMapNotPatMatch, UseOptionMapNotPatpatMatch, UseOptionNetNotPatMatch, UseOptionReachNotPatMatch, UseOptionIsDefinedNotPatMatch, UseOptionIsEmptynotPatMatch, UseOptionForAllNotPatMatch, UseOptionExistNotPatMatch
Los enlaces anteriores actualmente van a la prueba para esa verificación.
Otro archivo para verificar es advertir.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) en lugar de 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
^ Siéntase libre de agregar sus propias ideas o implementarlas. ¡Solicitud de solicitud de bienvenida!
var a = 4; { val a = 5 } )func("arg1", force = true) )Listas de reglas de otras herramientas de análisis estático: