Problem
When performing focused refactoring operations like renaming, users sometimes need to find usages only of the original symbol name and not follow imported aliases where the symbol is used under a different name. Currently, find-usages always follows all references including aliased imports.
Use Case: Focused Renaming
Consider this scenario:
File A (original definition):
// utils/helpers.ts
export function processData(input: string): string {
return input.trim().toLowerCase();
}
File B (imports with same name - SHOULD be included):
// services/data-service.ts
import { processData } from '../utils/helpers';
class DataService {
clean(input: string) {
return processData(input); // Same name - should be tracked
}
}
File C (imports with alias - SHOULD be excluded with new option):
// services/user-service.ts
import { processData as sanitizeInput } from '../utils/helpers';
class UserService {
validateUser(name: string) {
const cleanName = sanitizeInput(name); // Aliased - exclude with new option
return cleanName.length > 0;
}
}
Current Behavior:
refakts find-usages '[utils/helpers.ts 2:17-2:28]'
# Returns ALL:
# - [utils/helpers.ts 2:17-2:28] processData (original)
# - [services/data-service.ts 6:12-6:23] processData (same name import)
# - [services/user-service.ts 6:21-6:33] sanitizeInput (aliased import)
Desired Behavior with New Option:
refakts find-usages '[utils/helpers.ts 2:17-2:28]' --stop-at-aliases
# Returns:
# - [utils/helpers.ts 2:17-2:28] processData (original)
# - [services/data-service.ts 6:12-6:23] processData (same name - included)
# - Does NOT include sanitizeInput usage (aliased import - excluded)
Proposed Solution
Add a new option to find-usages that stops tracking when symbols are imported with different names:
Option Name
--stop-at-aliases (recommended)
--exclude-aliases
--same-name-only
--no-renamed-imports
Behavior Specification
Include these usages:
- ✅ Original symbol definition
- ✅ Direct usages in same file
- ✅ Imports with same name:
import { processData } from '...'
- ✅ Namespace imports:
import * as utils from '...' then utils.processData
Exclude these usages (with --stop-at-aliases):
- ❌ Aliased imports:
import { processData as sanitize } from '...'
- ❌ Default imports with different names:
import sanitize from '...' (if original was named export)
- ❌ Re-exports with different names:
export { processData as sanitize }
Implementation Approach
Modify the CrossFileReferenceFinder to track symbol name consistency:
// Enhanced CrossFileReferenceFinder
class CrossFileReferenceFinder {
constructor(
private project: Project,
private options: {
stopAtAliases?: boolean; // New option
} = {}
) {}
findAllReferences(node: Node): UsageLocation[] {
const originalName = this.getSymbolName(node);
const references = this.findDirectReferences(node);
if (\!this.options.stopAtAliases) {
// Current behavior - follow all imports including aliases
references.push(...this.findAllImportedReferences(node));
} else {
// New behavior - only follow imports that preserve the name
references.push(...this.findSameNameImportedReferences(node, originalName));
}
return references;
}
private findSameNameImportedReferences(node: Node, originalName: string): UsageLocation[] {
// Only include imports where symbol is used with same name
// Skip: import { foo as bar }, export { foo as bar }
// Include: import { foo }, import * as utils -> utils.foo
}
}
Command Interface
# Find all usages including aliases (current default behavior)
refakts find-usages '[file.ts 5:10-5:20]'
# Find usages only with same name, exclude aliases
refakts find-usages '[file.ts 5:10-5:20]' --stop-at-aliases
# Alternative shorter syntax
refakts find-usages '[file.ts 5:10-5:20]' --same-name-only
Benefits
Focused Refactoring
- Name-based tracking: Only see usages under the original symbol name
- Exclude intentional aliases: Don't get overwhelmed by deliberately renamed imports
- Safer renaming: Focus on direct name usages without worrying about alias conflicts
Workflow Integration
- Rename preparation: See exactly what shares the same name that would be affected
- Impact analysis: Understand direct vs. aliased dependencies
- Incremental refactoring: Rename original symbol without affecting intentional aliases
Implementation Details
1. Command Option
// find-usages-options.json
{
"stopAtAliases": {
"alias": "same-name-only",
"description": "Don't follow usages through aliased imports (import { foo as bar })",
"type": "boolean",
"default": false
}
}
2. Service Integration
// Enhanced FindUsagesCommand
private async performFindUsages(location: LocationRange, options: FindUsagesOptions): Promise<UsageLocation[]> {
const targetNode = location.getNode();
const astService = ASTService.createForFile(location.file);
return new CrossFileReferenceFinder(astService.getProject(), {
stopAtAliases: options.stopAtAliases
}).findAllReferences(targetNode);
}
3. Output Distinction
When --stop-at-aliases is used, the output could indicate the scope limitation:
refakts find-usages '[file.ts 5:10-5:20]' --stop-at-aliases
# Output:
# Found 3 usages (same name only):
# [file.ts 5:10-5:20] processData
# [other.ts 12:5-12:16] processData
# [utils.ts 18:8-18:19] processData
# (Excluded 2 aliased usages)
Acceptance Criteria
Related Issues
This enhancement would work well with:
Priority
Medium - Valuable for focused refactoring workflows, especially useful for rename operations, but doesn't block existing functionality.
🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com
Problem
When performing focused refactoring operations like renaming, users sometimes need to find usages only of the original symbol name and not follow imported aliases where the symbol is used under a different name. Currently, find-usages always follows all references including aliased imports.
Use Case: Focused Renaming
Consider this scenario:
File A (original definition):
File B (imports with same name - SHOULD be included):
File C (imports with alias - SHOULD be excluded with new option):
Current Behavior:
Desired Behavior with New Option:
Proposed Solution
Add a new option to find-usages that stops tracking when symbols are imported with different names:
Option Name
--stop-at-aliases(recommended)--exclude-aliases--same-name-only--no-renamed-importsBehavior Specification
Include these usages:
import { processData } from '...'import * as utils from '...'thenutils.processDataExclude these usages (with
--stop-at-aliases):import { processData as sanitize } from '...'import sanitize from '...'(if original was named export)export { processData as sanitize }Implementation Approach
Modify the
CrossFileReferenceFinderto track symbol name consistency:Command Interface
Benefits
Focused Refactoring
Workflow Integration
Implementation Details
1. Command Option
2. Service Integration
3. Output Distinction
When
--stop-at-aliasesis used, the output could indicate the scope limitation:Acceptance Criteria
--stop-at-aliasesoption to find-usages commandCrossFileReferenceFinderto support alias filteringimport { foo }import * as utils→utils.fooimport { foo as bar }export { foo as bar }Related Issues
This enhancement would work well with:
Priority
Medium - Valuable for focused refactoring workflows, especially useful for rename operations, but doesn't block existing functionality.
🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com