Skip to content

Commit

Permalink
use skip mechanism to skip imports/access of names from Compat that…
Browse files Browse the repository at this point in the history
… are owned by Base (#71)
  • Loading branch information
ericphanson authored Jul 2, 2024
1 parent 44b9bee commit eda7501
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 15 deletions.
5 changes: 3 additions & 2 deletions src/ExplicitImports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module ExplicitImports
using JuliaSyntax, AbstractTrees
using AbstractTrees: parent
using TOML: parsefile
using Compat: @compat
using Compat: Compat, @compat

export print_explicit_imports, explicit_imports, check_no_implicit_imports,
explicit_imports_nonrecursive
Expand Down Expand Up @@ -132,7 +132,8 @@ function choose_exporter(name, exporters)
return first(sorted)
end

function using_statements(io::IO, rows; linewidth=80, show_locations=false, separate_lines=false)
function using_statements(io::IO, rows; linewidth=80, show_locations=false,
separate_lines=false)
chosen = (choose_exporter(row.name, row.exporters) for row in rows)
prev_mod = nothing
cur_line_width = 0
Expand Down
16 changes: 12 additions & 4 deletions src/checks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,9 @@ end
"""
check_all_qualified_accesses_via_owners(mod::Module, file=pathof(mod); ignore::Tuple=(),
require_submodule_access=false,
skip::$(TUPLE_MODULE_PAIRS)=(Base => Core,),
skip::$(TUPLE_MODULE_PAIRS)=(Base => Core,
Compat => Base,
Compat => Core),
allow_internal_accesses=true)
Checks that neither `mod` nor any of its submodules has accesses to names via modules other than their owner as determined by `Base.which` (unless the name is public or exported in that module),
Expand Down Expand Up @@ -303,7 +305,9 @@ See also: [`improper_qualified_accesses`](@ref) for programmatic access and the
"""
function check_all_qualified_accesses_via_owners(mod::Module, file=pathof(mod);
ignore::Tuple=(),
skip::TUPLE_MODULE_PAIRS=(Base => Core,),
skip::TUPLE_MODULE_PAIRS=(Base => Core,
Compat => Base,
Compat => Core),
require_submodule_access=false,
allow_internal_accesses=true)
check_file(file)
Expand Down Expand Up @@ -471,7 +475,9 @@ end
"""
check_all_explicit_imports_via_owners(mod::Module, file=pathof(mod); ignore::Tuple=(),
require_submodule_import=false,
skip::$(TUPLE_MODULE_PAIRS)=(Base => Core,)),
skip::$(TUPLE_MODULE_PAIRS)=(Base => Core,
Compat => Base,
Compat => Core)),
allow_internal_imports=true)
Checks that neither `mod` nor any of its submodules has imports to names via modules other than their owner as determined by `Base.which` (unless the name is public or exported in that module),
Expand Down Expand Up @@ -516,7 +522,9 @@ See also: [`improper_explicit_imports`](@ref) for programmatic access to such im
"""
function check_all_explicit_imports_via_owners(mod::Module, file=pathof(mod);
ignore::Tuple=(),
skip::TUPLE_MODULE_PAIRS=(Base => Core,),
skip::TUPLE_MODULE_PAIRS=(Base => Core,
Compat => Base,
Compat => Core),
allow_internal_imports=true,
require_submodule_import=false)
check_file(file)
Expand Down
18 changes: 13 additions & 5 deletions src/improper_explicit_imports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ function analyze_explicitly_imported_names(mod::Module, file=pathof(mod);
file_analysis=get_names_used(file))
check_file(file)
@compat (; per_usage_info, unnecessary_explicit_import, tainted) = filter_to_module(file_analysis,
mod)
mod)
stale_imports = Set((; nt.name, nt.module_path) for nt in unnecessary_explicit_import)

_explicit_imports = filter(per_usage_info) do row
Expand Down Expand Up @@ -148,15 +148,19 @@ function process_explicitly_imported_row(row, mod)
end

"""
improper_explicit_imports_nonrecursive(mod::Module, file=pathof(mod); strict=true, skip=(Base => Core,),
improper_explicit_imports_nonrecursive(mod::Module, file=pathof(mod); strict=true, skip=(Base => Core,
Compat => Base,
Compat => Core),
allow_internal_imports=true)
A non-recursive version of [`improper_explicit_imports`](@ref), meaning it only analyzes the module `mod` itself, not any of its submodules; see that function for details, including important caveats about stability (outputs may grow in future non-breaking releases of ExplicitImports!).
If `strict=true`, then returns `nothing` if `mod` could not be fully analyzed.
"""
function improper_explicit_imports_nonrecursive(mod::Module, file=pathof(mod);
skip=(Base => Core,),
skip=(Base => Core,
Compat => Base,
Compat => Core),
strict=true,
allow_internal_imports=true,
# private undocumented kwarg for hoisting this analysis
Expand Down Expand Up @@ -191,7 +195,9 @@ function improper_explicit_imports_nonrecursive(mod::Module, file=pathof(mod);
end

"""
improper_explicit_imports(mod::Module, file=pathof(mod); strict=true, skip=(Base => Core,),
improper_explicit_imports(mod::Module, file=pathof(mod); strict=true, skip=(Base => Core,
Compat => Base,
Compat => Core),
allow_internal_imports=true)
Attempts do detect various kinds of "improper" explicit imports taking place in `mod` and any submodules of `mod`.
Expand Down Expand Up @@ -234,7 +240,9 @@ However, the result will be a Tables.jl-compatible row-oriented table (for each
See also [`print_explicit_imports`](@ref) to easily compute and print these results, [`improper_explicit_imports_nonrecursive`](@ref) for a non-recursive version which ignores submodules, as well as [`check_no_stale_explicit_imports`](@ref), [`check_all_explicit_imports_via_owners`](@ref), and [`check_all_explicit_imports_are_public`](@ref) for specific regression-testing helpers.
"""
function improper_explicit_imports(mod::Module, file=pathof(mod); strict=true,
skip=(Base => Core,),
skip=(Base => Core,
Compat => Base,
Compat => Core),
allow_internal_imports=true)
check_file(file)
submodules = find_submodules(mod, file)
Expand Down
17 changes: 13 additions & 4 deletions src/improper_qualified_accesses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ function trygetproperty(x::Module, y)
end

"""
improper_qualified_accesses_nonrecursive(mod::Module, file=pathof(mod); skip=(Base => Core,),
improper_qualified_accesses_nonrecursive(mod::Module, file=pathof(mod); skip=(Base => Core,
Compat => Base,
Compat => Core),
allow_internal_accesses=true)
Expand Down Expand Up @@ -115,7 +117,9 @@ julia> (; row.name, row.accessing_from, row.whichmodule)
```
"""
function improper_qualified_accesses_nonrecursive(mod::Module, file=pathof(mod);
skip=(Base => Core,),
skip=(Base => Core,
Compat => Base,
Compat => Core),
allow_internal_accesses=true,
# deprecated, does nothing
require_submodule_access=nothing,
Expand Down Expand Up @@ -147,7 +151,9 @@ function improper_qualified_accesses_nonrecursive(mod::Module, file=pathof(mod);
end

"""
improper_qualified_accesses(mod::Module, file=pathof(mod); skip=(Base => Core,),
improper_qualified_accesses(mod::Module, file=pathof(mod); skip=(Base => Core,
Compat => Base,
Compat => Core),
allow_internal_accesses=true)
Attempts do detect various kinds of "improper" qualified accesses taking place in `mod` and any submodules of `mod`.
Expand Down Expand Up @@ -208,7 +214,10 @@ julia> (; row.name, row.accessing_from, row.whichmodule)
(name = :sum, accessing_from = LinearAlgebra, whichmodule = Base)
```
"""
function improper_qualified_accesses(mod::Module, file=pathof(mod); skip=(Base => Core,),
function improper_qualified_accesses(mod::Module, file=pathof(mod);
skip=(Base => Core,
Compat => Base,
Compat => Core),
allow_internal_accesses=true,
# deprecated
require_submodule_access=nothing)
Expand Down
14 changes: 14 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ end
@test owner_mod_for_printing(Core, :println, Core.println) == Core
end

if VERSION >= v"1.7-"
@testset "Compat skipping" begin
@test check_all_explicit_imports_via_owners(TestMod14, "test_mods.jl") === nothing
@test check_all_qualified_accesses_via_owners(TestMod14, "test_mods.jl") === nothing

@test isempty(improper_explicit_imports_nonrecursive(TestMod14, "test_mods.jl"))
@test isempty(improper_explicit_imports(TestMod14, "test_mods.jl")[1][2])

@test isempty(improper_qualified_accesses_nonrecursive(TestMod14, "test_mods.jl"))

@test isempty(improper_qualified_accesses(TestMod14, "test_mods.jl")[1][2])
end
end

@testset "imports" begin
cursor = TreeCursor(SyntaxNodeWrapper("imports.jl"))
leaves = collect(Leaves(cursor))
Expand Down
9 changes: 9 additions & 0 deletions test/test_mods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,12 @@ using LinearAlgebra: norm
f(norm=norm) = 1

end # TestMod13

if VERSION >= v"1.7-"
@eval module TestMod14

using Compat: Compat, Returns
Compat.Returns

end # TestMod14
end

0 comments on commit eda7501

Please sign in to comment.