mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-12-24 02:02:29 +03:00
Backport work from review-unused
This commit is contained in:
parent
7d2a08d335
commit
f1e3e725a8
@ -277,20 +277,29 @@ exposedElements nodes =
|
|||||||
(\node ->
|
(\node ->
|
||||||
case Node.value node of
|
case Node.value node of
|
||||||
Exposing.FunctionExpose name ->
|
Exposing.FunctionExpose name ->
|
||||||
Just <| ( name, { range = Node.range node, exposedElement = Function } )
|
Just ( name, { range = untilEndOfVariable name (Node.range node), exposedElement = Function } )
|
||||||
|
|
||||||
Exposing.TypeOrAliasExpose name ->
|
Exposing.TypeOrAliasExpose name ->
|
||||||
Just <| ( name, { range = Node.range node, exposedElement = TypeOrTypeAlias } )
|
Just ( name, { range = untilEndOfVariable name (Node.range node), exposedElement = TypeOrTypeAlias } )
|
||||||
|
|
||||||
Exposing.TypeExpose { name } ->
|
Exposing.TypeExpose { name } ->
|
||||||
Just <| ( name, { range = Node.range node, exposedElement = ExposedType } )
|
Just ( name, { range = untilEndOfVariable name (Node.range node), exposedElement = ExposedType } )
|
||||||
|
|
||||||
Exposing.InfixExpose name ->
|
Exposing.InfixExpose _ ->
|
||||||
Nothing
|
Nothing
|
||||||
)
|
)
|
||||||
|> Dict.fromList
|
|> Dict.fromList
|
||||||
|
|
||||||
|
|
||||||
|
untilEndOfVariable : String -> Range -> Range
|
||||||
|
untilEndOfVariable name range =
|
||||||
|
if range.start.row == range.end.row then
|
||||||
|
range
|
||||||
|
|
||||||
|
else
|
||||||
|
{ range | end = { row = range.start.row, column = range.start.column + String.length name } }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- DECLARATION LIST VISITOR
|
-- DECLARATION LIST VISITOR
|
||||||
|
|
||||||
|
@ -592,6 +592,34 @@ type alias B = A.OtherType
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
, test "should report the correct range when exports are on multiple lines" <|
|
||||||
|
\() ->
|
||||||
|
[ """module A
|
||||||
|
exposing ( Card
|
||||||
|
, Link
|
||||||
|
, init
|
||||||
|
, toElement
|
||||||
|
)
|
||||||
|
type Card = Card
|
||||||
|
type Link = Link
|
||||||
|
init = 1
|
||||||
|
""", """
|
||||||
|
module Exposed exposing (..)
|
||||||
|
import A
|
||||||
|
a = A.Card A.init A.toElement
|
||||||
|
""" ]
|
||||||
|
|> Review.Test.runOnModulesWithProjectData package_ rule
|
||||||
|
|> Review.Test.expectErrorsForModules
|
||||||
|
[ ( "A"
|
||||||
|
, [ Review.Test.error
|
||||||
|
{ message = "Exposed type or type alias `Link` is never used outside this module."
|
||||||
|
, details = details
|
||||||
|
, under = "Link"
|
||||||
|
}
|
||||||
|
|> Review.Test.atExactly { start = { row = 3, column = 7 }, end = { row = 3, column = 11 } }
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,15 +10,15 @@ module NoUnused.Variables exposing (rule)
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
import Dict exposing (Dict)
|
import Dict exposing (Dict)
|
||||||
import Elm.Syntax.Declaration exposing (Declaration(..))
|
import Elm.Syntax.Declaration as Declaration exposing (Declaration)
|
||||||
import Elm.Syntax.Exposing exposing (Exposing(..), TopLevelExpose(..))
|
import Elm.Syntax.Exposing as Exposing exposing (Exposing)
|
||||||
import Elm.Syntax.Expression exposing (Expression(..), Function, FunctionImplementation, LetDeclaration(..))
|
import Elm.Syntax.Expression as Expression exposing (Expression, Function, FunctionImplementation)
|
||||||
import Elm.Syntax.Import exposing (Import)
|
import Elm.Syntax.Import exposing (Import)
|
||||||
import Elm.Syntax.Module as Module exposing (Module(..))
|
import Elm.Syntax.Module as Module exposing (Module)
|
||||||
import Elm.Syntax.Node as Node exposing (Node(..))
|
import Elm.Syntax.Node as Node exposing (Node(..))
|
||||||
import Elm.Syntax.Pattern as Pattern exposing (Pattern)
|
import Elm.Syntax.Pattern as Pattern exposing (Pattern)
|
||||||
import Elm.Syntax.Range exposing (Range)
|
import Elm.Syntax.Range exposing (Range)
|
||||||
import Elm.Syntax.TypeAnnotation exposing (TypeAnnotation(..))
|
import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
||||||
import NoUnused.NonemptyList as NonemptyList exposing (Nonempty)
|
import NoUnused.NonemptyList as NonemptyList exposing (Nonempty)
|
||||||
import Review.Fix as Fix exposing (Fix)
|
import Review.Fix as Fix exposing (Fix)
|
||||||
import Review.Rule as Rule exposing (Direction, Error, Rule)
|
import Review.Rule as Rule exposing (Direction, Error, Rule)
|
||||||
@ -27,10 +27,6 @@ import Set exposing (Set)
|
|||||||
|
|
||||||
{-| Report variables or types that are declared or imported but never used.
|
{-| Report variables or types that are declared or imported but never used.
|
||||||
|
|
||||||
**NOTE**: Since `elm-review` only works in the scope of a single file, this rule
|
|
||||||
will not report variables that are exposed but not used anywhere in the project.
|
|
||||||
If you wish those to be reported, check out [`elm-xref`](https://github.com/zwilias/elm-xref).
|
|
||||||
|
|
||||||
config =
|
config =
|
||||||
[ NoUnused.Variables.rule
|
[ NoUnused.Variables.rule
|
||||||
]
|
]
|
||||||
@ -232,25 +228,25 @@ fix declaredModules { variableType, rangeToRemove } =
|
|||||||
moduleDefinitionVisitor : Node Module -> Context -> ( List nothing, Context )
|
moduleDefinitionVisitor : Node Module -> Context -> ( List nothing, Context )
|
||||||
moduleDefinitionVisitor (Node _ moduleNode) context =
|
moduleDefinitionVisitor (Node _ moduleNode) context =
|
||||||
case Module.exposingList moduleNode of
|
case Module.exposingList moduleNode of
|
||||||
All _ ->
|
Exposing.All _ ->
|
||||||
( [], { context | exposesEverything = True } )
|
( [], { context | exposesEverything = True } )
|
||||||
|
|
||||||
Explicit list ->
|
Exposing.Explicit list ->
|
||||||
let
|
let
|
||||||
names =
|
names =
|
||||||
List.filterMap
|
List.filterMap
|
||||||
(\(Node _ node) ->
|
(\(Node _ node) ->
|
||||||
case node of
|
case node of
|
||||||
FunctionExpose name ->
|
Exposing.FunctionExpose name ->
|
||||||
Just name
|
Just name
|
||||||
|
|
||||||
TypeOrAliasExpose name ->
|
Exposing.TypeOrAliasExpose name ->
|
||||||
Just name
|
Just name
|
||||||
|
|
||||||
TypeExpose { name } ->
|
Exposing.TypeExpose { name } ->
|
||||||
Just name
|
Just name
|
||||||
|
|
||||||
InfixExpose name ->
|
Exposing.InfixExpose name ->
|
||||||
-- Just name
|
-- Just name
|
||||||
Nothing
|
Nothing
|
||||||
)
|
)
|
||||||
@ -260,13 +256,33 @@ moduleDefinitionVisitor (Node _ moduleNode) context =
|
|||||||
|
|
||||||
|
|
||||||
importVisitor : Node Import -> Context -> ( List (Error {}), Context )
|
importVisitor : Node Import -> Context -> ( List (Error {}), Context )
|
||||||
importVisitor ((Node _ { exposingList, moduleAlias, moduleName }) as node) context =
|
importVisitor ((Node _ import_) as node) context =
|
||||||
case exposingList of
|
let
|
||||||
|
errors : List (Error {})
|
||||||
|
errors =
|
||||||
|
case import_.moduleAlias of
|
||||||
|
Just moduleAlias ->
|
||||||
|
if Node.value moduleAlias == Node.value import_.moduleName then
|
||||||
|
[ Rule.errorWithFix
|
||||||
|
{ message = "Module `Html` is aliased as `Html`"
|
||||||
|
, details = [ "The alias is the same as the module name, and brings no useful value" ]
|
||||||
|
}
|
||||||
|
(Node.range moduleAlias)
|
||||||
|
[ Fix.removeRange <| moduleAliasRange node (Node.range moduleAlias) ]
|
||||||
|
]
|
||||||
|
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
[]
|
||||||
|
in
|
||||||
|
case import_.exposingList of
|
||||||
Nothing ->
|
Nothing ->
|
||||||
( [], registerModuleNameOrAlias node context )
|
( errors, registerModuleNameOrAlias node context )
|
||||||
|
|
||||||
Just declaredImports ->
|
Just declaredImports ->
|
||||||
( []
|
( errors
|
||||||
, List.foldl
|
, List.foldl
|
||||||
(\( name, variableInfo ) context_ -> register variableInfo name context_)
|
(\( name, variableInfo ) context_ -> register variableInfo name context_)
|
||||||
(registerModuleAlias node context)
|
(registerModuleAlias node context)
|
||||||
@ -324,19 +340,19 @@ moduleAliasRange (Node _ { moduleName }) range =
|
|||||||
expressionVisitor : Node Expression -> Direction -> Context -> ( List (Error {}), Context )
|
expressionVisitor : Node Expression -> Direction -> Context -> ( List (Error {}), Context )
|
||||||
expressionVisitor (Node range value) direction context =
|
expressionVisitor (Node range value) direction context =
|
||||||
case ( direction, value ) of
|
case ( direction, value ) of
|
||||||
( Rule.OnEnter, FunctionOrValue [] name ) ->
|
( Rule.OnEnter, Expression.FunctionOrValue [] name ) ->
|
||||||
( [], markAsUsed name context )
|
( [], markAsUsed name context )
|
||||||
|
|
||||||
( Rule.OnEnter, FunctionOrValue moduleName name ) ->
|
( Rule.OnEnter, Expression.FunctionOrValue moduleName name ) ->
|
||||||
( [], markModuleAsUsed (getModuleName moduleName) context )
|
( [], markModuleAsUsed (getModuleName moduleName) context )
|
||||||
|
|
||||||
( Rule.OnEnter, OperatorApplication name _ _ _ ) ->
|
( Rule.OnEnter, Expression.OperatorApplication name _ _ _ ) ->
|
||||||
( [], markAsUsed name context )
|
( [], markAsUsed name context )
|
||||||
|
|
||||||
( Rule.OnEnter, PrefixOperator name ) ->
|
( Rule.OnEnter, Expression.PrefixOperator name ) ->
|
||||||
( [], markAsUsed name context )
|
( [], markAsUsed name context )
|
||||||
|
|
||||||
( Rule.OnEnter, LetExpression { declarations, expression } ) ->
|
( Rule.OnEnter, Expression.LetExpression { declarations, expression } ) ->
|
||||||
let
|
let
|
||||||
letBlockContext : LetBlockContext
|
letBlockContext : LetBlockContext
|
||||||
letBlockContext =
|
letBlockContext =
|
||||||
@ -351,7 +367,7 @@ expressionVisitor (Node range value) direction context =
|
|||||||
List.foldl
|
List.foldl
|
||||||
(\declaration context_ ->
|
(\declaration context_ ->
|
||||||
case Node.value declaration of
|
case Node.value declaration of
|
||||||
LetFunction function ->
|
Expression.LetFunction function ->
|
||||||
let
|
let
|
||||||
namesUsedInArgumentPatterns : { types : List String, modules : List String }
|
namesUsedInArgumentPatterns : { types : List String, modules : List String }
|
||||||
namesUsedInArgumentPatterns =
|
namesUsedInArgumentPatterns =
|
||||||
@ -365,7 +381,7 @@ expressionVisitor (Node range value) direction context =
|
|||||||
|> registerFunction letBlockContext function
|
|> registerFunction letBlockContext function
|
||||||
|> markUsedTypesAndModules namesUsedInArgumentPatterns
|
|> markUsedTypesAndModules namesUsedInArgumentPatterns
|
||||||
|
|
||||||
LetDestructuring pattern _ ->
|
Expression.LetDestructuring pattern _ ->
|
||||||
context_
|
context_
|
||||||
)
|
)
|
||||||
{ context | scopes = NonemptyList.cons emptyScope context.scopes }
|
{ context | scopes = NonemptyList.cons emptyScope context.scopes }
|
||||||
@ -373,7 +389,7 @@ expressionVisitor (Node range value) direction context =
|
|||||||
in
|
in
|
||||||
( [], newContext )
|
( [], newContext )
|
||||||
|
|
||||||
( Rule.OnEnter, LambdaExpression { args } ) ->
|
( Rule.OnEnter, Expression.LambdaExpression { args } ) ->
|
||||||
let
|
let
|
||||||
namesUsedInArgumentPatterns : { types : List String, modules : List String }
|
namesUsedInArgumentPatterns : { types : List String, modules : List String }
|
||||||
namesUsedInArgumentPatterns =
|
namesUsedInArgumentPatterns =
|
||||||
@ -383,10 +399,10 @@ expressionVisitor (Node range value) direction context =
|
|||||||
in
|
in
|
||||||
( [], markUsedTypesAndModules namesUsedInArgumentPatterns context )
|
( [], markUsedTypesAndModules namesUsedInArgumentPatterns context )
|
||||||
|
|
||||||
( Rule.OnExit, RecordUpdateExpression expr _ ) ->
|
( Rule.OnExit, Expression.RecordUpdateExpression expr _ ) ->
|
||||||
( [], markAsUsed (Node.value expr) context )
|
( [], markAsUsed (Node.value expr) context )
|
||||||
|
|
||||||
( Rule.OnExit, CaseExpression { cases } ) ->
|
( Rule.OnExit, Expression.CaseExpression { cases } ) ->
|
||||||
let
|
let
|
||||||
usedVariables : { types : List String, modules : List String }
|
usedVariables : { types : List String, modules : List String }
|
||||||
usedVariables =
|
usedVariables =
|
||||||
@ -401,7 +417,7 @@ expressionVisitor (Node range value) direction context =
|
|||||||
, markUsedTypesAndModules usedVariables context
|
, markUsedTypesAndModules usedVariables context
|
||||||
)
|
)
|
||||||
|
|
||||||
( Rule.OnExit, LetExpression _ ) ->
|
( Rule.OnExit, Expression.LetExpression _ ) ->
|
||||||
let
|
let
|
||||||
( errors, remainingUsed ) =
|
( errors, remainingUsed ) =
|
||||||
makeReport (NonemptyList.head context.scopes)
|
makeReport (NonemptyList.head context.scopes)
|
||||||
@ -545,7 +561,7 @@ getUsedModulesFromPattern patternNode =
|
|||||||
declarationVisitor : Node Declaration -> Direction -> Context -> ( List nothing, Context )
|
declarationVisitor : Node Declaration -> Direction -> Context -> ( List nothing, Context )
|
||||||
declarationVisitor node direction context =
|
declarationVisitor node direction context =
|
||||||
case ( direction, Node.value node ) of
|
case ( direction, Node.value node ) of
|
||||||
( Rule.OnEnter, FunctionDeclaration function ) ->
|
( Rule.OnEnter, Declaration.FunctionDeclaration function ) ->
|
||||||
let
|
let
|
||||||
functionImplementation : FunctionImplementation
|
functionImplementation : FunctionImplementation
|
||||||
functionImplementation =
|
functionImplementation =
|
||||||
@ -579,7 +595,7 @@ declarationVisitor node direction context =
|
|||||||
in
|
in
|
||||||
( [], newContext )
|
( [], newContext )
|
||||||
|
|
||||||
( Rule.OnEnter, CustomTypeDeclaration { name, documentation, constructors } ) ->
|
( Rule.OnEnter, Declaration.CustomTypeDeclaration { name, documentation, constructors } ) ->
|
||||||
let
|
let
|
||||||
variablesFromConstructorArguments : { types : List String, modules : List String }
|
variablesFromConstructorArguments : { types : List String, modules : List String }
|
||||||
variablesFromConstructorArguments =
|
variablesFromConstructorArguments =
|
||||||
@ -610,7 +626,7 @@ declarationVisitor node direction context =
|
|||||||
|> markUsedTypesAndModules variablesFromConstructorArguments
|
|> markUsedTypesAndModules variablesFromConstructorArguments
|
||||||
)
|
)
|
||||||
|
|
||||||
( Rule.OnEnter, AliasDeclaration { name, typeAnnotation, documentation } ) ->
|
( Rule.OnEnter, Declaration.AliasDeclaration { name, typeAnnotation, documentation } ) ->
|
||||||
let
|
let
|
||||||
namesUsedInTypeAnnotation : { types : List String, modules : List String }
|
namesUsedInTypeAnnotation : { types : List String, modules : List String }
|
||||||
namesUsedInTypeAnnotation =
|
namesUsedInTypeAnnotation =
|
||||||
@ -627,7 +643,7 @@ declarationVisitor node direction context =
|
|||||||
|> markUsedTypesAndModules namesUsedInTypeAnnotation
|
|> markUsedTypesAndModules namesUsedInTypeAnnotation
|
||||||
)
|
)
|
||||||
|
|
||||||
( Rule.OnEnter, PortDeclaration { name, typeAnnotation } ) ->
|
( Rule.OnEnter, Declaration.PortDeclaration { name, typeAnnotation } ) ->
|
||||||
let
|
let
|
||||||
namesUsedInTypeAnnotation : { types : List String, modules : List String }
|
namesUsedInTypeAnnotation : { types : List String, modules : List String }
|
||||||
namesUsedInTypeAnnotation =
|
namesUsedInTypeAnnotation =
|
||||||
@ -644,10 +660,10 @@ declarationVisitor node direction context =
|
|||||||
(Node.value name)
|
(Node.value name)
|
||||||
)
|
)
|
||||||
|
|
||||||
( Rule.OnEnter, InfixDeclaration _ ) ->
|
( Rule.OnEnter, Declaration.InfixDeclaration _ ) ->
|
||||||
( [], context )
|
( [], context )
|
||||||
|
|
||||||
( Rule.OnEnter, Destructuring _ _ ) ->
|
( Rule.OnEnter, Declaration.Destructuring _ _ ) ->
|
||||||
( [], context )
|
( [], context )
|
||||||
|
|
||||||
( Rule.OnExit, _ ) ->
|
( Rule.OnExit, _ ) ->
|
||||||
@ -764,10 +780,10 @@ registerFunction letBlockContext function context =
|
|||||||
collectFromExposing : Node Exposing -> List ( String, VariableInfo )
|
collectFromExposing : Node Exposing -> List ( String, VariableInfo )
|
||||||
collectFromExposing exposingNode =
|
collectFromExposing exposingNode =
|
||||||
case Node.value exposingNode of
|
case Node.value exposingNode of
|
||||||
All _ ->
|
Exposing.All _ ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
Explicit list ->
|
Exposing.Explicit list ->
|
||||||
let
|
let
|
||||||
listWithPreviousRange : List (Maybe Range)
|
listWithPreviousRange : List (Maybe Range)
|
||||||
listWithPreviousRange =
|
listWithPreviousRange =
|
||||||
@ -807,27 +823,60 @@ collectFromExposing exposingNode =
|
|||||||
{ range | start = previousRange.end }
|
{ range | start = previousRange.end }
|
||||||
in
|
in
|
||||||
case value of
|
case value of
|
||||||
FunctionExpose name ->
|
Exposing.FunctionExpose name ->
|
||||||
Just ( name, { variableType = ImportedItem ImportedVariable, under = range, rangeToRemove = rangeToRemove } )
|
Just
|
||||||
|
( name
|
||||||
|
, { variableType = ImportedItem ImportedVariable
|
||||||
|
, under = untilEndOfVariable name range
|
||||||
|
, rangeToRemove = rangeToRemove
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
InfixExpose name ->
|
Exposing.InfixExpose name ->
|
||||||
Just ( name, { variableType = ImportedItem ImportedOperator, under = range, rangeToRemove = rangeToRemove } )
|
Just
|
||||||
|
( name
|
||||||
|
, { variableType = ImportedItem ImportedOperator
|
||||||
|
, under = untilEndOfVariable name range
|
||||||
|
, rangeToRemove = rangeToRemove
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
TypeOrAliasExpose name ->
|
Exposing.TypeOrAliasExpose name ->
|
||||||
Just ( name, { variableType = ImportedItem ImportedType, under = range, rangeToRemove = rangeToRemove } )
|
Just
|
||||||
|
( name
|
||||||
|
, { variableType = ImportedItem ImportedType
|
||||||
|
, under = untilEndOfVariable name range
|
||||||
|
, rangeToRemove = rangeToRemove
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
TypeExpose { name, open } ->
|
Exposing.TypeExpose { name, open } ->
|
||||||
case open of
|
case open of
|
||||||
Just openRange ->
|
Just openRange ->
|
||||||
-- TODO Change this behavior once we know the contents of the open range, using dependencies or the interfaces of the other modules
|
-- TODO Change this behavior once we know the contents of the open range, using dependencies or the interfaces of the other modules
|
||||||
Nothing
|
Nothing
|
||||||
|
|
||||||
Nothing ->
|
Nothing ->
|
||||||
Just ( name, { variableType = ImportedItem ImportedType, under = range, rangeToRemove = rangeToRemove } )
|
Just
|
||||||
|
( name
|
||||||
|
, { variableType = ImportedItem ImportedType
|
||||||
|
, under = range
|
||||||
|
, rangeToRemove = rangeToRemove
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|> List.filterMap identity
|
|> List.filterMap identity
|
||||||
|
|
||||||
|
|
||||||
|
untilEndOfVariable : String -> Range -> Range
|
||||||
|
untilEndOfVariable name range =
|
||||||
|
if range.start.row == range.end.row then
|
||||||
|
range
|
||||||
|
|
||||||
|
else
|
||||||
|
{ range | end = { row = range.start.row, column = range.start.column + String.length name } }
|
||||||
|
|
||||||
|
|
||||||
collectNamesFromTypeAnnotation : Node TypeAnnotation -> { types : List String, modules : List String }
|
collectNamesFromTypeAnnotation : Node TypeAnnotation -> { types : List String, modules : List String }
|
||||||
collectNamesFromTypeAnnotation node =
|
collectNamesFromTypeAnnotation node =
|
||||||
{ types = collectTypesFromTypeAnnotation node
|
{ types = collectTypesFromTypeAnnotation node
|
||||||
@ -838,10 +887,10 @@ collectNamesFromTypeAnnotation node =
|
|||||||
collectTypesFromTypeAnnotation : Node TypeAnnotation -> List String
|
collectTypesFromTypeAnnotation : Node TypeAnnotation -> List String
|
||||||
collectTypesFromTypeAnnotation node =
|
collectTypesFromTypeAnnotation node =
|
||||||
case Node.value node of
|
case Node.value node of
|
||||||
FunctionTypeAnnotation a b ->
|
TypeAnnotation.FunctionTypeAnnotation a b ->
|
||||||
collectTypesFromTypeAnnotation a ++ collectTypesFromTypeAnnotation b
|
collectTypesFromTypeAnnotation a ++ collectTypesFromTypeAnnotation b
|
||||||
|
|
||||||
Typed nameNode params ->
|
TypeAnnotation.Typed nameNode params ->
|
||||||
let
|
let
|
||||||
name : List String
|
name : List String
|
||||||
name =
|
name =
|
||||||
@ -854,34 +903,34 @@ collectTypesFromTypeAnnotation node =
|
|||||||
in
|
in
|
||||||
name ++ List.concatMap collectTypesFromTypeAnnotation params
|
name ++ List.concatMap collectTypesFromTypeAnnotation params
|
||||||
|
|
||||||
Record list ->
|
TypeAnnotation.Record list ->
|
||||||
list
|
list
|
||||||
|> List.map (Node.value >> Tuple.second)
|
|> List.map (Node.value >> Tuple.second)
|
||||||
|> List.concatMap collectTypesFromTypeAnnotation
|
|> List.concatMap collectTypesFromTypeAnnotation
|
||||||
|
|
||||||
GenericRecord name list ->
|
TypeAnnotation.GenericRecord name list ->
|
||||||
list
|
list
|
||||||
|> Node.value
|
|> Node.value
|
||||||
|> List.map (Node.value >> Tuple.second)
|
|> List.map (Node.value >> Tuple.second)
|
||||||
|> List.concatMap collectTypesFromTypeAnnotation
|
|> List.concatMap collectTypesFromTypeAnnotation
|
||||||
|
|
||||||
Tupled list ->
|
TypeAnnotation.Tupled list ->
|
||||||
List.concatMap collectTypesFromTypeAnnotation list
|
List.concatMap collectTypesFromTypeAnnotation list
|
||||||
|
|
||||||
GenericType _ ->
|
TypeAnnotation.GenericType _ ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
Unit ->
|
TypeAnnotation.Unit ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
|
|
||||||
collectModuleNamesFromTypeAnnotation : Node TypeAnnotation -> List String
|
collectModuleNamesFromTypeAnnotation : Node TypeAnnotation -> List String
|
||||||
collectModuleNamesFromTypeAnnotation node =
|
collectModuleNamesFromTypeAnnotation node =
|
||||||
case Node.value node of
|
case Node.value node of
|
||||||
FunctionTypeAnnotation a b ->
|
TypeAnnotation.FunctionTypeAnnotation a b ->
|
||||||
collectModuleNamesFromTypeAnnotation a ++ collectModuleNamesFromTypeAnnotation b
|
collectModuleNamesFromTypeAnnotation a ++ collectModuleNamesFromTypeAnnotation b
|
||||||
|
|
||||||
Typed nameNode params ->
|
TypeAnnotation.Typed nameNode params ->
|
||||||
let
|
let
|
||||||
name : List String
|
name : List String
|
||||||
name =
|
name =
|
||||||
@ -894,24 +943,24 @@ collectModuleNamesFromTypeAnnotation node =
|
|||||||
in
|
in
|
||||||
name ++ List.concatMap collectModuleNamesFromTypeAnnotation params
|
name ++ List.concatMap collectModuleNamesFromTypeAnnotation params
|
||||||
|
|
||||||
Record list ->
|
TypeAnnotation.Record list ->
|
||||||
list
|
list
|
||||||
|> List.map (Node.value >> Tuple.second)
|
|> List.map (Node.value >> Tuple.second)
|
||||||
|> List.concatMap collectModuleNamesFromTypeAnnotation
|
|> List.concatMap collectModuleNamesFromTypeAnnotation
|
||||||
|
|
||||||
GenericRecord name list ->
|
TypeAnnotation.GenericRecord name list ->
|
||||||
list
|
list
|
||||||
|> Node.value
|
|> Node.value
|
||||||
|> List.map (Node.value >> Tuple.second)
|
|> List.map (Node.value >> Tuple.second)
|
||||||
|> List.concatMap collectModuleNamesFromTypeAnnotation
|
|> List.concatMap collectModuleNamesFromTypeAnnotation
|
||||||
|
|
||||||
Tupled list ->
|
TypeAnnotation.Tupled list ->
|
||||||
List.concatMap collectModuleNamesFromTypeAnnotation list
|
List.concatMap collectModuleNamesFromTypeAnnotation list
|
||||||
|
|
||||||
GenericType _ ->
|
TypeAnnotation.GenericType _ ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
Unit ->
|
TypeAnnotation.Unit ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
|
|
||||||
|
@ -555,7 +555,7 @@ import Foo
|
|||||||
[ Review.Test.error
|
[ Review.Test.error
|
||||||
{ message = "Imported type `C` is not used"
|
{ message = "Imported type `C` is not used"
|
||||||
, details = details
|
, details = details
|
||||||
, under = "C\n ,"
|
, under = "C"
|
||||||
}
|
}
|
||||||
|> Review.Test.whenFixed """module SomeModule exposing (d)
|
|> Review.Test.whenFixed """module SomeModule exposing (d)
|
||||||
import Foo
|
import Foo
|
||||||
@ -591,6 +591,41 @@ import Foo
|
|||||||
, a
|
, a
|
||||||
)"""
|
)"""
|
||||||
]
|
]
|
||||||
|
, test "should report unused imported functions (multiple imports on several lines, function first)" <|
|
||||||
|
\() ->
|
||||||
|
"""module SomeModule exposing (d)
|
||||||
|
import Foo
|
||||||
|
exposing
|
||||||
|
( a
|
||||||
|
, b
|
||||||
|
)
|
||||||
|
d = 1"""
|
||||||
|
|> Review.Test.run rule
|
||||||
|
|> Review.Test.expectErrors
|
||||||
|
[ Review.Test.error
|
||||||
|
{ message = "Imported variable `a` is not used"
|
||||||
|
, details = details
|
||||||
|
, under = "a"
|
||||||
|
}
|
||||||
|
|> Review.Test.whenFixed
|
||||||
|
"""module SomeModule exposing (d)
|
||||||
|
import Foo
|
||||||
|
exposing
|
||||||
|
( b
|
||||||
|
)
|
||||||
|
d = 1"""
|
||||||
|
, Review.Test.error
|
||||||
|
{ message = "Imported variable `b` is not used"
|
||||||
|
, details = details
|
||||||
|
, under = "b"
|
||||||
|
}
|
||||||
|
|> Review.Test.whenFixed """module SomeModule exposing (d)
|
||||||
|
import Foo
|
||||||
|
exposing
|
||||||
|
( a
|
||||||
|
)
|
||||||
|
d = 1"""
|
||||||
|
]
|
||||||
, test "should report unused operator import" <|
|
, test "should report unused operator import" <|
|
||||||
\() ->
|
\() ->
|
||||||
"""module SomeModule exposing (a)
|
"""module SomeModule exposing (a)
|
||||||
@ -738,6 +773,23 @@ import Html.Styled exposing (Html)
|
|||||||
a : Html
|
a : Html
|
||||||
a = ()"""
|
a = ()"""
|
||||||
]
|
]
|
||||||
|
, test "should report import alias if the name is the same thing as the module name" <|
|
||||||
|
\() ->
|
||||||
|
"""module SomeModule exposing (a)
|
||||||
|
import Html as Html
|
||||||
|
a = Html.div"""
|
||||||
|
|> Review.Test.run rule
|
||||||
|
|> Review.Test.expectErrors
|
||||||
|
[ Review.Test.error
|
||||||
|
{ message = "Module `Html` is aliased as `Html`"
|
||||||
|
, details = [ "The alias is the same as the module name, and brings no useful value" ]
|
||||||
|
, under = "Html"
|
||||||
|
}
|
||||||
|
|> Review.Test.atExactly { start = { row = 2, column = 16 }, end = { row = 2, column = 20 } }
|
||||||
|
|> Review.Test.whenFixed """module SomeModule exposing (a)
|
||||||
|
import Html
|
||||||
|
a = Html.div"""
|
||||||
|
]
|
||||||
, test "should not report import that exposes a used exposed type" <|
|
, test "should not report import that exposes a used exposed type" <|
|
||||||
\() ->
|
\() ->
|
||||||
"""module SomeModule exposing (a)
|
"""module SomeModule exposing (a)
|
||||||
|
Loading…
Reference in New Issue
Block a user