Skip to content

feat: emit SymbolInformation.kind and declare UTF-16 position encoding - #124

Open
PhysShell wants to merge 1 commit into
sourcegraph:mainfrom
PhysShell:feat/scip-symbol-kind-position-encoding
Open

PhysShell wants to merge 1 commit into
sourcegraph:mainfrom
PhysShell:feat/scip-symbol-kind-position-encoding

Conversation

@PhysShell

Copy link
Copy Markdown

Summary

scip-dotnet currently emits SymbolInformation.kind = 0 (UnspecifiedKind) for every symbol and leaves
Document.position_encoding unset, because the vendored scip.proto predates both fields. Consumers therefore have to
guess what a symbol is from the shape of its symbol string, and have to guess the unit of character offsets.

This PR:

  • refreshes the vendored schema and C# binding to scip-code/scip@08b592d — scip.proto and the official
    bindings/dotnet/src/Scip.cs, copied unmodified — and bumps Google.Protobuf to 3.34.2 to match the generator;
  • sets SymbolInformation.Kind for definitions from the Roslyn symbol (table below); every other symbol keeps
    UnspecifiedKind;
  • declares Document.position_encoding = UTF16CodeUnitOffsetFromLineStart for C# and Visual Basic documents. Ranges
    come from Roslyn LinePosition.Character, which counts UTF-16 code units; the ranges themselves are unchanged.

Handwritten production change: +27 / −2 lines (ScipDocumentIndexer.cs, ScipProjectIndexer.cs, ScipDotnet.csproj).

Roslyn symbol SCIP kind
INamedTypeSymbol TypeKind Class / Interface / Struct / Enum / Delegate / Module Class / Interface / Struct / Enum / Delegate / Module
IMethodSymbol Constructor, StaticConstructor Constructor
IMethodSymbol Ordinary Method, or StaticMethod when IsStatic (extension methods and VB module members included)
IPropertySymbol (not an indexer) Property, or StaticProperty when IsStatic
IFieldSymbol EnumMember in an enum, Constant when IsConst, else Field / StaticField
IEventSymbol Event, or StaticEvent when IsStatic

The static variants follow the schema, which documents StaticMethod, StaticField, StaticProperty and StaticEvent
as intended for C#. Records map to Class / Struct through their TypeKind.

What does not change

Symbol strings, occurrences, ranges, roles, relationships and documentation. I checked this by indexing
snapshots/input/syntax, snapshots/input/syntax-slnx and the new fixture with main and with this branch on
net8.0, net9.0 and net10.0, decoding both indexes with the pinned schema, clearing only position_encoding and kind,
and comparing the rest with proto.Equal: identical in every case. The existing textual snapshots are byte-identical
(the snapshot renderer does not print kind or position_encoding, so kinds are covered by a dedicated test).

scip lint built from the same scip-code/scip commit reports no new diagnostics for this branch compared to main on
the same inputs.

Tests

  • New snapshot input snapshots/input/symbol-kinds (a C# project and a VB project) with generated outputs for
    net8.0 / net9.0 / net10.0.
  • New SymbolKindTests asserting the kind of each construct above and the UTF-16 position encoding of both documents.
    To reuse the indexing helper, SnapshotTests.IndexDirectory and SnapshotTests.RootDirectory changed from
    private to internal. Printing kind in the snapshot renderer would be an alternative, but it would rewrite every
    existing snapshot, so I left the renderer alone; happy to switch if you prefer.
  • The commands from test.yml (dotnet format --verify-no-changes ×3 and dotnet test for net10.0 / net9.0 / net8.0)
    pass locally on Linux. I have not run them on Windows or macOS.

Notes

  • The refreshed binding marks Occurrence.Range and Suffix.Package as obsolete, so the build now reports three
    CS0612 warnings per target framework. The CI does not treat warnings as errors. Migrating to the typed range fields is
    a separate change and is not part of this PR.
  • An equivalent implementation using the official Scip 0.10.0 NuGet package was also tested: same schema
    fingerprint, same generated index, builds on net8/net9/net10. I kept the existing vendored-binding model in this PR to
    avoid changing dependency policy; happy to switch if maintainers prefer the package.
  • position_encoding declares the unit of the character offsets only. With #line directives, ranges still come
    from GetMappedLineSpan() and keep their current behavior.
  • Not addressed here: generic types that differ only in arity (Box<T> and Box<T1, T2>) currently share one symbol,
    which scip lint reports as a repeated SymbolInformation; and enclosing_range is not emitted. Both are separate
    changes.

🤖 Generated with Claude Code

Refresh the vendored SCIP schema and C# binding to scip-code/scip@08b592d
(the official bindings/dotnet/src/Scip.cs, unmodified) and bump
Google.Protobuf to 3.34.2 to match its generator.

- Set SymbolInformation.Kind for definitions from the Roslyn symbol:
  class, interface, struct, enum, delegate, VB module, constructor,
  method / static method, property / static property, enum member,
  constant, field / static field, event / static event. Every other
  symbol keeps UnspecifiedKind.
- Declare Document.position_encoding as UTF16CodeUnitOffsetFromLineStart
  for C# and Visual Basic documents: ranges come from Roslyn
  LinePosition.Character, which counts UTF-16 code units. Ranges
  themselves are unchanged.
- Add a symbol-kinds snapshot input and SymbolKindTests.

Symbols, occurrences, ranges, relationships and documentation are
unchanged; existing snapshots are byte-identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant