import os
import sys
import argparse
def is_skippable_line(line):
stripped = line.strip()
return (not stripped or
stripped.startswith('//') or
stripped.startswith('#[') or
stripped.startswith('#!['))
def is_module_declaration(line):
stripped = line.strip()
return ((stripped.startswith('pub mod ') or stripped.startswith('mod '))
and '{' in stripped)
def is_allowed_module_import(line, just_saw_module_decl):
return just_saw_module_decl and line.strip() == 'use super::*;'
def ends_multiline_import(line):
stripped = line.strip()
return stripped.endswith(';') or stripped == '}' or stripped.endswith('};')
def process_import_line(stripped, state):
if is_allowed_module_import(f"{stripped}", state['just_saw_module_decl']):
state['just_saw_module_decl'] = False
return None
if not stripped.endswith(';'):
state['in_multiline_import'] = True
issue = None
if (not state['in_imports'] and
state['first_non_import_line'] > 0 and
not state['just_saw_module_decl']):
issue = stripped
state['just_saw_module_decl'] = False
return issue
def process_non_import_line(state):
if state['in_imports']:
state['in_imports'] = False
return True state['just_saw_module_decl'] = False
return False
def process_line(line, line_num, state):
if is_skippable_line(line):
return None
if state['in_multiline_import']:
if ends_multiline_import(line):
state['in_multiline_import'] = False
return None
if is_module_declaration(line):
state['just_saw_module_decl'] = True
return None
stripped = line.strip()
if stripped.startswith('use '):
issue = process_import_line(stripped, state)
return (line_num, issue) if issue else None
if process_non_import_line(state):
state['first_non_import_line'] = line_num
return None
def check_inline_imports(file_path):
with open(file_path, 'r') as f:
lines = f.readlines()
issues = []
state = {
'in_imports': True,
'in_multiline_import': False,
'first_non_import_line': 0,
'just_saw_module_decl': False
}
for i, line in enumerate(lines, 1):
issue = process_line(line, i, state)
if issue:
issues.append(issue)
return issues
def check_imports(crate_path):
violations = []
src_path = os.path.join(crate_path, 'src')
if not os.path.exists(src_path):
print(f"Error: {src_path} does not exist", file=sys.stderr)
return None
for root, dirs, files in os.walk(src_path):
if 'tests' in root.split(os.sep):
continue
for file in files:
if not file.endswith('.rs'):
continue
path = os.path.join(root, file)
rel_path = os.path.relpath(path, crate_path)
issues = check_inline_imports(path)
if issues:
violations.append((rel_path, issues))
return violations
def main():
parser = argparse.ArgumentParser(
description='Verify imports are at top of Rust files'
)
parser.add_argument(
'crate_path',
help='Path to the crate to check (e.g., multi-llm)'
)
args = parser.parse_args()
violations = check_imports(args.crate_path)
if violations is None:
return 1
if violations:
print(f"❌ Found {len(violations)} file(s) with imports after code:\n")
for path, issues in violations[:10]:
print(f" {path}:")
for line_num, import_stmt in issues[:3]:
print(f" Line {line_num}: {import_stmt[:60]}...")
if len(issues) > 3:
print(f" ... and {len(issues) - 3} more imports")
if len(violations) > 10:
print(f"\n ... and {len(violations) - 10} more files")
return 1
else:
print("✓ All imports are at top of files")
return 0
if __name__ == '__main__':
sys.exit(main())