From 548a7d372477de0188035b67623b3e38e0bdafb7 Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Fri, 26 Apr 2024 01:24:55 +0200 Subject: [PATCH] handle unary `::` (#39) * add failing test case * fix test case * format * format * also fix #36 * add failing test * handle for loop arguments and nested local scope * add some more nested scope tests * handle unary `::` --- src/get_names_used.jl | 17 +++++++++++++---- test/runtests.jl | 6 ++++++ test/test_mods.jl | 18 +++++++++++++----- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/get_names_used.jl b/src/get_names_used.jl index 1e8494b..9b2f788 100644 --- a/src/get_names_used.jl +++ b/src/get_names_used.jl @@ -60,7 +60,7 @@ function is_anonymous_function_definition_arg(leaf) return child_index(get_parent(leaf, 3)) == 2 elseif parents_match(leaf, (K"::",)) # we must be on the LHS, otherwise we're a type - child_index(leaf) == 1 || return false + is_hastype_LHS(leaf) || return false # Ok, let's just step up one level and see again return is_anonymous_function_definition_arg(parent(leaf)) elseif parents_match(leaf, (K"=",)) @@ -92,10 +92,10 @@ function is_struct_field_name(leaf) kind(leaf) == K"Identifier" || return false if parents_match(leaf, (K"::", K"block", K"struct")) # we want to be on the LHS of the `::` - return child_index(leaf) == 1 + return is_hastype_LHS(leaf) elseif parents_match(leaf, (K"::", K"=", K"block", K"struct")) # if we are in a `Base.@kwdef`, we may be on the LHS of an `=` - return child_index(leaf) == 1 && child_index(parent(leaf)) == 1 + return is_hastype_LHS(leaf) && child_index(parent(leaf)) == 1 else return false end @@ -149,7 +149,7 @@ function is_non_anonymous_function_definition_arg(leaf) return is_non_anonymous_function_definition_arg(parent(leaf)) elseif parents_match(leaf, (K"::",)) # we must be on the LHS, otherwise we're a type - child_index(leaf) == 1 || return false + is_hastype_LHS(leaf) || return false # Ok, let's just step up one level and see again return is_non_anonymous_function_definition_arg(parent(leaf)) else @@ -157,6 +157,15 @@ function is_non_anonymous_function_definition_arg(leaf) end end +# matches `x` in `x::Y`, but not `Y`, nor `foo(::Y)` +function is_hastype_LHS(leaf) + parents_match(leaf, (K"::",)) || return false + unary = has_flags(get_parent(leaf), JuliaSyntax.PREFIX_OP_FLAG) + unary && return false + # OK if not unary, then check we're in position 1 for LHS + return child_index(leaf) == 1 +end + # Here we use the magic of AbstractTrees' `TreeCursor` so we can start at # a leaf and follow the parents up to see what scopes our leaf is in. # TODO- cleanup with parsing utilities (?) diff --git a/test/runtests.jl b/test/runtests.jl index affcae4..e7c1817 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -109,6 +109,12 @@ end ["using LinearAlgebra: LinearAlgebra"] end +@testset "types without values in function signatures" begin + # https://github.com/ericphanson/ExplicitImports.jl/issues/33 + @test using_statement.(explicit_imports_nonrecursive(TestMod8, "test_mods.jl")) == + ["using LinearAlgebra: LinearAlgebra", "using LinearAlgebra: QR"] +end + @testset "scripts" begin str = sprint(print_explicit_imports_script, "script.jl") @test contains(str, "Script `script.jl`") diff --git a/test/test_mods.jl b/test/test_mods.jl index 4d75c35..59db70f 100644 --- a/test/test_mods.jl +++ b/test/test_mods.jl @@ -80,15 +80,23 @@ using LinearAlgebra # these are all local references to `I`, but you have to go up a scope to know that function foo(I) let - I+1 + I + 1 end - let k=I - k+I + let k = I + k + I end function bar(x) - I+1 + return I + 1 end - bar(I) + return bar(I) end end # TestMod7 + +module TestMod8 +using LinearAlgebra + +# https://github.com/ericphanson/ExplicitImports.jl/issues/33 +foo(::QR) = () + +end # TestMod8