Explicit Imports Fixing
The explicit imports fixer uses ExplicitImports.jl to automatically detect and fix import issues in Julia packages. It iteratively runs checks and applies fixes until all explicit import best practices are satisfied.
ExplicitImports.jl is included as a direct dependency of OrgMaintenanceScripts, so no additional setup is required.
Features
- Automatic Detection: Uses ExplicitImports.jl to find implicit imports and unused explicit imports
- Iterative Fixing: Repeatedly applies fixes and re-checks until all issues are resolved
- Safe Modifications: Verifies the package still loads after each round of fixes
- Pull Request Creation: Automatically creates PRs with detailed explanations of changes
- Organization-wide Processing: Can process entire GitHub organizations
Usage
Fix a Single Package
using OrgMaintenanceScripts
# Fix explicit imports in a local package
success, iterations, report = fix_explicit_imports("/path/to/MyPackage.jl")
if success
println("✓ All explicit import checks pass after $iterations iterations!")
else
println("Some issues remain after $iterations iterations")
println(report)
end
Fix a Repository
# Clone, fix, and create a PR for a repository
success = fix_repo_explicit_imports("MyOrg/MyPackage.jl";
create_pr = true,
max_iterations = 10
)
Fix an Entire Organization
# Process all Julia packages in an organization
results = fix_org_explicit_imports("MyOrg";
create_prs = true,
skip_repos = ["DeprecatedPackage.jl"],
only_repos = nothing # Process all repos
)
# Summary of results
for (repo, success) in results
println("$repo: ", success ? "✓ Fixed" : "✗ Failed/No changes")
end
How It Works
The fixer follows this iterative process:
- Run ExplicitImports.jl checks on the package
- Parse the output to identify specific issues:
- Missing explicit imports (e.g., using
println
withoutusing Base: println
) - Unused explicit imports (e.g.,
using Base: push!
whenpush!
is never used)
- Missing explicit imports (e.g., using
- Apply fixes to the source files:
- Add missing imports at appropriate locations
- Remove unused imports while preserving other imports
- Verify the package still loads correctly
- Repeat until all checks pass or maximum iterations reached
Example Fixes
Missing Import
Before:
module MyModule
function greet(name)
println("Hello, $name!") # println used implicitly
end
end
After:
module MyModule
using Base: println
function greet(name)
println("Hello, $name!")
end
end
Unused Import
Before:
module MyModule
using Base: println, push!, filter # push! is never used
function process(items)
filtered = filter(x -> x > 0, items)
println("Processed $(length(filtered)) items")
end
end
After:
module MyModule
using Base: println, filter
function process(items)
filtered = filter(x -> x > 0, items)
println("Processed $(length(filtered)) items")
end
end
Options
fix_explicit_imports
package_path
: Path to the package directorymax_iterations
: Maximum number of fix/check cycles (default: 10)verbose
: Show detailed output during processing (default: true)
fix_repo_explicit_imports
repo_name
: GitHub repository name (e.g., "MyOrg/Package.jl")work_dir
: Temporary directory for cloning (default: mktempdir())max_iterations
: Maximum number of fix/check cycles (default: 10)create_pr
: Whether to create a pull request (default: true)verbose
: Show detailed output (default: true)
fix_org_explicit_imports
org_name
: GitHub organization namework_dir
: Temporary directory for processing (default: mktempdir())max_iterations
: Maximum iterations per package (default: 10)create_prs
: Whether to create pull requests (default: true)skip_repos
: Array of repository names to skiponly_repos
: Process only these repositories (default: all)verbose
: Show detailed output (default: true)
Benefits
Using explicit imports provides several benefits:
- Clarity: Makes dependencies explicit and clear
- Performance: Can improve load times by avoiding unnecessary imports
- Maintainability: Easier to track what external functions are used
- Stability: Reduces risk of name conflicts when packages export new names
- Static Analysis: Better compatibility with tools that analyze code
Limitations
- Requires ExplicitImports.jl to be installable in the package environment
- May not catch all edge cases that require manual review
- Some packages may have legitimate reasons for implicit imports
- Complex macro usage might not be handled perfectly
Best Practices
- Review Changes: Always review the automated changes before merging
- Run Tests: Ensure your test suite passes after fixes
- Incremental Adoption: For large packages, consider fixing one module at a time
- Document Exceptions: If you need implicit imports, document why
Troubleshooting
If the fixer encounters issues:
- Check Package Loads: Ensure your package loads without the fixes
- Update Dependencies: Make sure all dependencies are up to date
- Manual Review: Some complex cases may need manual intervention
- Report Issues: File issues for packages that can't be automatically fixed