diff --git a/CHANGELOG.md b/CHANGELOG.md index d0d64b55..79f33fdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +Fixed issues in [`NoUnused.Exports`] where type aliases and custom types would incorrectly be reported. Thanks Eric from the Elm Slack for reporting! + ## [1.2.1] - 2024-04-01 - [`NoUnused.Exports`] now reports (and removes using `--fix`) elements even if the module is exposing everything (`module X exposing (..)`) if the element is unused both locally and across the project. Thanks [@tfausak](https://github.com/tfausak). diff --git a/src/NoUnused/Exports.elm b/src/NoUnused/Exports.elm index 6f707994..ff1ef117 100644 --- a/src/NoUnused/Exports.elm +++ b/src/NoUnused/Exports.elm @@ -1655,7 +1655,12 @@ expressionVisitor node moduleContext = [] declarations in - { moduleContext | used = List.foldl Set.insert moduleContext.used used } + List.foldl + (\( moduleName, name ) ctx -> + registerLocalValueWithRealModuleName moduleName name ctx + ) + moduleContext + used Expression.CaseExpression { cases } -> let @@ -1666,7 +1671,12 @@ expressionVisitor node moduleContext = (List.map Tuple.first cases) [] in - { moduleContext | used = List.foldl Set.insert moduleContext.used usedConstructors } + List.foldl + (\( moduleName, name ) ctx -> + registerLocalValueWithRealModuleName moduleName name ctx + ) + moduleContext + usedConstructors _ -> moduleContext @@ -1675,7 +1685,17 @@ expressionVisitor node moduleContext = registerLocalValue : Range -> String -> ModuleContext -> ModuleContext registerLocalValue range name moduleContext = case ModuleNameLookupTable.moduleNameAt moduleContext.lookupTable range of - Just [] -> + Just moduleName -> + registerLocalValueWithRealModuleName (String.join "." moduleName) name moduleContext + + Nothing -> + moduleContext + + +registerLocalValueWithRealModuleName : String -> String -> ModuleContext -> ModuleContext +registerLocalValueWithRealModuleName realModuleName name moduleContext = + case realModuleName of + "" -> case Dict.get name moduleContext.constructorNameToTypeName of Just typeName -> { moduleContext | exposed = Dict.remove typeName moduleContext.exposed } @@ -1693,11 +1713,8 @@ registerLocalValue range name moduleContext = else moduleContext - Just moduleName -> - registerAsUsed ( String.join "." moduleName, name ) moduleContext - - Nothing -> - moduleContext + moduleName -> + registerAsUsed ( moduleName, name ) moduleContext findUsedConstructors : ModuleNameLookupTable -> List (Node Pattern) -> List ( ModuleNameStr, String ) -> List ( ModuleNameStr, String ) diff --git a/tests/NoUnused/ExportsTest.elm b/tests/NoUnused/ExportsTest.elm index 5f45fefa..ac3e77d6 100644 --- a/tests/NoUnused/ExportsTest.elm +++ b/tests/NoUnused/ExportsTest.elm @@ -1877,6 +1877,78 @@ main = NotReported.used , """ port module NotReported exposing (..) port used : () +""" + ] + |> Review.Test.runOnModulesWithProjectData application rule + |> Review.Test.expectNoErrors + , test "should not remove a type alias used in a local let binding type annotation" <| + \() -> + [ """ +module Main exposing (main) +import Tertiary +main = Tertiary.func 1 2 +""" + , """ +module Tertiary exposing (..) + +type alias Tertiary = {} + +func : Int -> Int -> Int +func a b = + let + perhapsTertiary : Int -> Maybe Tertiary + perhapsTertiary a = + if a > 5 then + Just {} + else + Nothing + in + case perhapsTertiary 4 of + Just _ -> + a + b + + Nothing -> + a - 4 +""" + ] + |> Review.Test.runOnModulesWithProjectData application rule + |> Review.Test.expectNoErrors + , test "should not remove a type used in a local let destructuring" <| + \() -> + [ """ +module Main exposing (main) +import Tertiary +main = Tertiary.func 1 +""" + , """ +module Tertiary exposing (..) + +type Wrapper = WrapperConstructor Int + +func foo = + let + (WrapperConstructor int) = foo + in + int +""" + ] + |> Review.Test.runOnModulesWithProjectData application rule + |> Review.Test.expectNoErrors + , test "should not custom type that is being pattern matched on locally" <| + \() -> + [ """ +module Main exposing (main) +import Tertiary +main = Tertiary.func foo +""" + , """ +module Tertiary exposing (..) + +type Used = X + +func foo = + case foo of + X -> 1 """ ] |> Review.Test.runOnModulesWithProjectData application rule