feat: comprehensive Type Hierarchy LSP support#2602
Draft
kbrilla wants to merge 3 commits intomicrosoft:mainfrom
Draft
feat: comprehensive Type Hierarchy LSP support#2602kbrilla wants to merge 3 commits intomicrosoft:mainfrom
kbrilla wants to merge 3 commits intomicrosoft:mainfrom
Conversation
Implements the Type Hierarchy feature (LSP 3.17) for typescript-go. Features: - textDocument/prepareTypeHierarchy: Finds the type declaration at cursor - typeHierarchy/supertypes: Shows parent classes, implemented interfaces, extended interfaces, type alias dependencies - typeHierarchy/subtypes: Shows subclasses, implementing classes, interface extensions (cross-project aware) Supports: - Class declarations and expressions - Interface declarations - Type aliases (including intersection/union types, mapped types) - Type parameters with constraints - Mixin patterns (const X = Mixin(Base)) The implementation follows the patterns established by the Call Hierarchy feature and integrates with the existing cross-project orchestration for finding subtypes across the workspace. Port of TypeScript PR #63052 to typescript-go.
…sults limit - Add createTypeHierarchyItemWithName to support optional display name parameter - Add getDisplayNameFromTypeNode helper to extract type text with arguments - Update getSupertypes to use display names from type reference nodes (e.g., 'Repository<T>' instead of just 'Repository') - Add DefaultTypeHierarchyMaxResults constant (1000, matches TypeScript) - Update getSubtypes with early termination when max results reached - Update baseline for typeHierarchyGenerics test All 22 type hierarchy tests pass.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Type Hierarchy Feature: Comprehensive Enhancement
Summary
This PR implements a comprehensive Type Hierarchy feature for the TypeScript language service, providing IDE support for navigating class, interface, and type alias hierarchies. The feature supports the LSP Type Hierarchy protocol and enables rich navigation across supertypes and subtypes.
This PR is ported from microsoft/TypeScript#63052
Fixes
microsoft/TypeScript#45877
Features
Core Functionality
Supported Declaration Types
const Mixed = Mixin(Base)patterns)Advanced Type Patterns
The implementation handles complex TypeScript patterns:
extendsclausesimplementsclausesA & B)A | B)Note on Mapped Types: Utility types like
Required<T>,Pick<T, K>,Partial<T>are type-level transformations, not inheritance relationships. They don't appear as subtypes because structural subtype checks are expensive and can produce noisy results. The semantics vary - some create subtypes (Required), some create supertypes (Partial).Kind Modifiers
Types are annotated with descriptive
kindModifiersto help distinguish different type relationships:mixinconst Mixed = Mixin(Base)aliastype Foo = Barconditional,extendsT extends U ? X : Yconditional,inferT extends (...) => infer R ? R : neverintersectionA & BunionA | Bmapped{ [K in keyof T]: ... }tuple[A, B]template`Hello ${string}`indexedT["key"]keyofkeyof Treadonlyreadonly T[]Configurable Result Limits
The maximum number of results per level is configurable via
UserPreferences:This allows clients to adjust the limit based on their needs and prevents performance issues in very large codebases.
Implementation Details
Files Changed
src/services/typeHierarchy.ts(new, ~1000 lines)resolveTypeHierarchyDeclaration()- Entry point for type hierarchy requestscreateTypeHierarchyItem()- Creates hierarchy items with proper metadatagetSupertypes()- Collects base types, implemented interfaces, and type parameter constraintsgetSubtypes()- Finds derived types using hybrid approach with configurable limitsgetTypeHierarchyKindModifiers()- Returns modifiers based on type patternfindMixinVariablesUsingSymbol()- Reverse mixin lookupcollectTypeParameterConstraints()- Collects type parameter constraints as supertypessrc/compiler/types.ts(modified)typeHierarchyMaxResultstoUserPreferencesfor configurable result limitssrc/services/types.ts(modified)LanguageServiceinterface with preferences parametersrc/services/services.ts(modified)src/server/session.ts(modified)src/harness/fourslashImpl.ts(modified)kindModifiersdisplay in type hierarchy baselinesTest Files (27 new fourslash tests)
Key Algorithms
Supertype Collection
getEffectiveBaseTypeNode()for class inheritanceextends/implementsSubtype Collection (Hybrid Approach)
{ implementations: true }for efficient heritage clause lookupSymbol Resolution
skipAlias()getMergedSymbol()Mixin Support
The implementation recognizes and supports TypeScript mixin patterns:
Type Parameter Constraints
Type hierarchy shows type parameter constraints as supertypes:
Testing
Test Coverage
Running Tests
Semantic Correctness
Union vs Intersection Types
The implementation correctly models type relationships:
A & B): A subtype of both A and B (has ALL properties)A | B): A supertype of A and B (not a subtype!)Conditional Types
Conditional types like
ExtractDog<T> = T extends Dog ? T : neverare shown as "possible subtypes" when the condition could be satisfied. Theconditional,extendsorconditional,infermodifiers help distinguish these from structural subtypes.Mapped Types
Mapped types like
Required<T>,Partial<T>,Pick<T, K>are NOT shown as subtypes because:Required<T>creates subtypes,Partial<T>creates supertypesPerformance Considerations
Known Limitations
satisfiesis an expression-level operator, not a type-level relationshipFuture Enhancements
AI Disclosure
This PR was developed with assistance from GitHub Copilot (Claude Opus 4.5). The AI helped with:
All code has been reviewed by the contributor @kbrilla and tested against the full TypeScript test suite (99,267 tests passing).