Skip to content

Conversation

uberzzr
Copy link
Collaborator

@uberzzr uberzzr commented Sep 30, 2025

Description

This PR adds a reverse implementors index to the partial SCIP loader that maps each abstract/interface symbol to its implementing symbols, built during index load by reading IsImplementation relationships. Also implemented the registry-level implementation handler to be used in "gotoImplementation" later. This handler resolves the symbol uses the reverse index to fetch implementors, resolves each implementor to its definition location, and returns those as LSP locations. If the reverse index has no entry (e.g., incomplete data), it falls back to scanning the symbol’s relationships to find implementors before resolving their locations.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Test improvement

Component(s) Affected

  • Language Server (ULSP)
  • SCIP Generation (Python utilities)
  • VS Code/Cursor Extension
  • Java Aggregator
  • Build System (Bazel)
  • Documentation
  • Tests

Testing

  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes (bazel test //...)
  • I have tested this manually with a real project

Manual Testing Details

Describe how you tested these changes:

  • IDE used for testing:
  • Project(s) tested against:
  • Specific features/scenarios verified:

Checklist

  • My code follows the existing code style and conventions
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have updated BUILD.bazel files if I added new source files
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

Screenshots/Logs (if applicable)

Include any relevant screenshots, logs, or output that demonstrates the changes.

Related Issues

Fixes #(issue number)
Closes #(issue number)
Related to #(issue number)

Additional Notes

Any additional information that reviewers should know about this PR.

@CLAassistant
Copy link

CLAassistant commented Sep 30, 2025

CLA assistant check
All committers have signed the CLA.

@uberzzr uberzzr changed the title Zerunz/gotoimpl Add reverse implementors index to the partial SCIP loader Sep 30, 2025
GetSymbolInformation(symbol string) (*model.SymbolInformation, string, error)
GetSymbolInformationFromDescriptors(descriptors []model.Descriptor, version string) (*model.SymbolInformation, string, error)
References(symbol string) (map[string][]*model.Occurrence, error)
GetImplementationSymbols(symbol string) ([]string, error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Match the other methods by naming this Implementations

Suggested change
GetImplementationSymbols(symbol string) ([]string, error)
Implementations(symbol string) ([]string, error)

Comment on lines 371 to 400
// Fallback: traverse relationships on the abstract symbol if the reverse index is empty or there is error
symbolInformation, _, err := p.Index.GetSymbolInformation(sourceOccurrence.Symbol)
if err != nil {
p.logger.Errorf("failed to get symbol information for %s: %s", sourceOccurrence.Symbol, err)
return nil, err
}
if symbolInformation == nil {
return []protocol.Location{}, nil
}

for _, relationship := range symbolInformation.Relationships {
if relationship.IsImplementation {
implementingSymbol, err := model.ParseScipSymbol(relationship.Symbol)
if err != nil {
p.logger.Errorf("failed to parse implementing symbol %s: %s", relationship.Symbol, err)
continue
}
implOcc, err := p.GetSymbolDefinitionOccurrence(
mapper.ScipDescriptorsToModelDescriptors(implementingSymbol.Descriptors),
implementingSymbol.Package.Version,
)
if err != nil {
p.logger.Errorf("failed to get definition for implementing symbol %s: %s", relationship.Symbol, err)
continue
}
if implOcc != nil && implOcc.Occurrence != nil {
locations = append(locations, *mapper.ScipOccurrenceToLocation(implOcc.Location, implOcc.Occurrence))
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go to implementation is generally interface -> implementing struct(s)/class(es). This block of code would follow the struct -> parent type(s) which is closer to a typeDefinition; that being said, we have fields for type definition in the relationship as well, so now we'd be splitting hairs about expected behavior.

I think we may want to put this behind a setting (default false/disabled) to let us play with this in different language scip indices, since it's generally not the accurate intended behavior.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, removed the fallback logic. We can put this behind a feature flag in subsequent PRs if we need it.

Comment on lines +63 to +64
implementorsMu sync.RWMutex
ImplementorsBySymbol map[string]map[string]struct{}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this put as a map on the main index type because there isn't an easy way to attach it to a treeNode during the indexing process? We probably want to change this when we come up with the multiple step index load process.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the prefeix tree merging happens after scanning, and the nodes are versioned and pruned, cross-tree mutability may complicate concurrency and correctness

uberzzr and others added 4 commits October 8, 2025 11:45
## Description
The original goimports fix suggests `Run 'bazel run
//tools:goimports_fix' to fix formatting` however there is no such
target 'goimports_fix' in package 'tools'. To enable goimports fix mode
we need to run `bazel run //tools:goimports -- fix`


## Type of Change

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] Documentation update
- [ ] Refactoring (no functional changes)
- [ ] Performance improvement
- [ ] Test improvement

## Component(s) Affected

- [ ] Language Server (ULSP)
- [ ] SCIP Generation (Python utilities)
- [ ] VS Code/Cursor Extension
- [ ] Java Aggregator
- [ ] Build System (Bazel)
- [ ] Documentation
- [X] Tests

## Testing

- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes (`bazel
test //...`)
- [X] I have tested this manually with a real project

### Manual Testing Details

Describe how you tested these changes:
- IDE used for testing:
- Project(s) tested against:
- Specific features/scenarios verified:

## Checklist

- [ ] My code follows the existing code style and conventions
- [X] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] I have updated BUILD.bazel files if I added new source files
- [X] My changes generate no new warnings
- [ ] Any dependent changes have been merged and published

## Screenshots/Logs (if applicable)

Include any relevant screenshots, logs, or output that demonstrates the
changes.

## Related Issues

Fixes #(issue number)
Closes #(issue number)
Related to #(issue number)

## Additional Notes

Any additional information that reviewers should know about this PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants