Files
JuliaFEM.jl/scripts/check_namespace_collisions.jl
T

148 lines
4.6 KiB
Julia
Raw Normal View History

#!/usr/bin/env julia
"""
Analyze namespace collisions before consolidation
Finds function definitions that might conflict when merging packages
"""
using Printf
function find_function_definitions(dir::String)
"""Find all function definitions in .jl files"""
functions = Dict{String,Vector{String}}()
for (root, dirs, files) in walkdir(dir)
for file in files
if !endswith(file, ".jl")
continue
end
filepath = joinpath(root, file)
relpath_str = relpath(filepath, dir)
try
content = read(filepath, String)
lines = split(content, '\n')
for (lineno, line) in enumerate(lines)
# Match function definitions
m = match(r"^\s*function\s+([a-zA-Z_][a-zA-Z0-9_!]*)", line)
if m !== nothing
fname = m.captures[1]
location = "$relpath_str:$lineno"
if !haskey(functions, fname)
functions[fname] = String[]
end
push!(functions[fname], location)
end
# Match short-form function definitions
m = match(r"^\s*([a-zA-Z_][a-zA-Z0-9_!]*)\([^)]*\)\s*=", line)
if m !== nothing && !occursin("function", line)
fname = m.captures[1]
location = "$relpath_str:$lineno"
if !haskey(functions, fname)
functions[fname] = String[]
end
push!(functions[fname], location)
end
end
catch e
@warn "Error reading $filepath: $e"
end
end
end
return functions
end
function main()
println("="^80)
println("NAMESPACE COLLISION ANALYSIS - JuliaFEM Consolidation")
println("="^80)
println()
# Analyze vendor packages
vendor_dir = "/home/juajukka/dev/JuliaFEM.jl/vendor"
src_dir = "/home/juajukka/dev/JuliaFEM.jl/src"
println("Analyzing vendor packages...")
vendor_functions = find_function_definitions(vendor_dir)
println("Analyzing main src/...")
src_functions = find_function_definitions(src_dir)
# Find collisions (functions defined in multiple places)
println()
println("="^80)
println("POTENTIAL COLLISIONS (functions defined multiple times)")
println("="^80)
println()
collision_count = 0
high_risk = String[]
# Check vendor collisions
for (fname, locations) in sort(collect(vendor_functions), by=x -> length(x[2]), rev=true)
if length(locations) > 1
collision_count += 1
# Check if it's a common override pattern (likely safe)
is_override = any(occursin(r"FEMBase\.|get_|assemble", fname) for loc in locations)
risk = is_override ? "🟢 LOW" : "🔴 HIGH"
if !is_override
push!(high_risk, fname)
end
println("$risk: $fname ($(length(locations)) definitions)")
for loc in locations[1:min(5, length(locations))]
println(" $loc")
end
if length(locations) > 5
println(" ... and $(length(locations) - 5) more")
end
println()
end
end
println("="^80)
println("SUMMARY")
println("="^80)
println()
@printf "Total unique functions in vendor: %d\n" length(vendor_functions)
@printf "Total unique functions in src: %d\n" length(src_functions)
@printf "Functions defined multiple times: %d\n" collision_count
@printf "High-risk collisions: %d\n" length(high_risk)
println()
if length(high_risk) > 0
println("High-risk collisions to review:")
for fname in high_risk[1:min(10, length(high_risk))]
println(" - $fname")
end
if length(high_risk) > 10
println(" ... and $(length(high_risk) - 10) more")
end
else
println("✅ No high-risk collisions detected!")
println(" Most collisions are likely dispatch specializations (safe)")
end
println()
println("="^80)
println("RECOMMENDATION")
println("="^80)
println("""
Most function "collisions" in FEM packages are actually safe:
- Different Problem{T} types dispatch correctly
- get_* and assemble_* are intentional overrides
Review high-risk collisions manually before consolidation.
""")
end
main()