Skip to content

Add lsp stub services - #125

Open
ssmifi wants to merge 3 commits into
mainfrom
ssm/lsp-stub-services
Open

Add lsp stub services#125
ssmifi wants to merge 3 commits into
mainfrom
ssm/lsp-stub-services

Conversation

@ssmifi

@ssmifi ssmifi commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Closes #28

Mostly ports from langium with go-idiomatic mechanisms for customization.

I refactored the original proposal. With the exceptions of Declaration, Implementation and Type Defintion, which provide meaningful defaults, all lsp stubs only provide the plain interface.
Semantic tokens is another exception, which I kept for comparison, but I guess it will be overwritten by the more sophisticated version in #136.

Added examples for Call Hierarchy, Code lens, Semantic tokens (which will be replaced), and Inlay Hints to the statemachine example to show adopters a working example.

# Feature Pattern Notes
1 Declaration Interface-only Default removed - duplicated Definition without adding value
2 Implementation Interface-only Default + ImplementationFilter removed - the "type implements" heuristic requires language-specific type-system knowledge no generic filter can provide
3 Type Definition Interface-only Default removed - its cross-reference heuristic never actually filtered by field
4 Semantic Tokens Removed from this PR entirely; deferred to #136
5 Inlay Hint Interface-only Unchanged. Open question: should it get ResolvingInlayHintProvider too?
6 Signature Help Interface-only, + separate trigger service Split into SignatureHelpProvider and SignatureHelpTriggers
7 Call Hierarchy Interface-only Fixed NodeAtCursor - now uses NameFinder. Fixed in both the godoc example and the statemachine example
8 Type Hierarchy Interface-only Same NodeAtCursor
9 Code Actions Interface-only, + optional resolve extension Added ResolvingCodeActionProvider for codeAction/resolve support
10 Code Lens Interface-only, + optional resolve extension Added ResolvingCodeLensProvider for codeLens/resolve support.
11 Document Links Interface-only Unchanged. Open question: should it get ResolvingDocumentLinkProvider too?
12 Commands Interface-only Unchanged

@ssmifi
ssmifi force-pushed the ssm/lsp-stub-services branch 2 times, most recently from 1b9c746 to 154c364 Compare July 24, 2026 09:34

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: 68da275 Previous: d803417 Ratio
BenchmarkWorkspaceCycle (typefox.dev/fastbelt/examples/statemachine) - MB/s 12.98 MB/s 5.21 MB/s 2.49

This comment was automatically generated by workflow using github-action-benchmark.

@ssmifi
ssmifi force-pushed the ssm/lsp-stub-services branch from 154c364 to a9cbd1c Compare July 24, 2026 09:53
@ssmifi
ssmifi force-pushed the ssm/lsp-stub-services branch from a9cbd1c to 8be8f2b Compare July 24, 2026 10:25
@ssmifi
ssmifi force-pushed the ssm/lsp-stub-services branch from a747f34 to 68da275 Compare August 7, 2026 13:31
@ssmifi
ssmifi marked this pull request as ready for review August 7, 2026 13:32
@ssmifi
ssmifi requested a review from msujew August 7, 2026 13:32

@msujew msujew left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, that's very useful!

Comment thread server/declaration_provider.go Outdated
Comment thread server/implementation_provider.go Outdated
Comment on lines +47 to +54
// DefaultImplementationProvider is the default implementation of [ImplementationProvider].
//
// The default implementation finds all references to the target symbol and uses an
// [ImplementationFilter] to determine which references represent actual implementations.
type DefaultImplementationProvider struct {
sc *service.Container
filter ImplementationFilter
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Discussion: I'm unsure how much benefit such a default/abstract implementation has, since it requires a very specific language design for this to work as expected.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I agree. Let's fall back to interface only.

Comment on lines +110 to +115
// grammarInlayHintProvider provides custom inlay hints for grammar language nodes.
// Provider-only pattern: adopter implements the full provider interface,
// using the shared server.NodesInRange helper for range-filtered iteration.
type grammarInlayHintProvider struct {
sc *service.Container
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question: Is this a real implementation or just for testing purposes?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It is a working implementation currently only used in testing. The "provider-only" comment was misleading though. I changed that already.

Comment thread server/signature_help_provider.go
Comment on lines +74 to +80
// grammarSignatureHelpProvider provides custom signature help for grammar
// language nodes. Provider-only pattern: adopter implements the full
// provider interface, using the shared server.NodeAtCursor helper for
// cursor-to-node resolution.
type grammarSignatureHelpProvider struct {
sc *service.Container
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question: Real or only for testing?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Same as before, working implementation currently only used for testing.

Comment thread server/type_definition_provider.go Outdated
Comment thread server/type_hierarchy_provider.go Outdated
// if doc == nil {
// return nil, nil
// }
// node := server.NodeAtCursor(doc, params.Position)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggestion: I believe this example is misleading. If you call server.NodeAtCursor, you run into two issues:

  1. If the token at the cursor is a reference, you would expect that it shows the type hierarchy for the referenced type. However, NodeAtCursor will return the AST node that contains the reference.
  2. If your cursor is over a random keyword of that type, like t<cursor>ype SomeType, it shows the type hierarchy for that type. Normally, it should only show it, if the user hovers over the name of the type (or a reference to the name).

Comment on lines +31 to +33
type CodeLensProvider interface {
HandleCodeLensRequest(ctx context.Context, params *lsp.CodeLensParams) ([]lsp.CodeLens, error)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggestion: Can we also add a ResolvingCodeLensProvider that supports the codeLens/resolve request?

Comment on lines +29 to +31
type CodeActionProvider interface {
HandleCodeActionRequest(ctx context.Context, params *lsp.CodeActionParams) ([]lsp.CodeAction, error)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggestion: Here as well for the codeAction/resolve request.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Should we add this also for InlayHint and DocumentLinks?

Comment thread server/semantic_tokens_contributor.go Outdated
@ssmifi

ssmifi commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for the review @msujew. Included all suggestions.
Still under consideration:

  • Should we also add the resolve support pattern to the InlayHintProvider and DocumentLinkProvider?
  • Whether to keep the real-but-test-only fixture providers (grammarInlayHintProvider, grammarCodeLensProvider, grammarSignatureHelpProvider, grammarTypeDefinitionProvider) as documentation, or trim them?

@ssmifi
ssmifi requested a review from msujew August 27, 2026 21:23
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.

Stub services for various LSP features

2 participants