Skip to content

Add a scijava-code-lsp ScriptDialect - #8

Draft
gselzer wants to merge 21 commits into
mainfrom
lsp-completion
Draft

gselzer wants to merge 21 commits into
mainfrom
lsp-completion

Conversation

@gselzer

@gselzer gselzer commented Oct 21, 2026

Copy link
Copy Markdown
Member

This PR adds a org.scijava.code.lsp.ScriptDialect that describes how to convert a SciJava Groovy script to plain groovy code.

See scijava/scijava#294 for discussion

gselzer and others added 21 commits October 6, 2026 10:49
Add a CodeCompleterPlugin for Groovy, driven by Groovy's own compiler:
the script up to the caret is compiled, with errors tolerated, and run
through the static type checker, which infers expression types.

* Members after a dot, including GDK methods, static members of classes,
  members of classes defined in the script, and classes of packages.
* Variables in scope, keywords, class names (imported on acceptance) and
  import statements.
* Script parameters (#@) and live interpreter bindings, typed.
* Signature help: overloads of methods and constructors, rated against
  the arguments' inferred types.
* Nothing in strings and comments; a syntax error above the caret falls
  back to analyzing the caret's line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GroovyDialect declares predefined variables as Java types and blanks # lines (now with spaces, keeping offsets) in place of GroovyAnalysis's own preamble.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GroovyLanguageServer (offered by GroovyServerPlugin) replaces GroovyCodeCompleter, with the same analysis: callables become snippets with typed label details, signatures are rated as before. In a call's arguments, with nothing typed, it now offers the variables fitting the parameter first (replacing parameter choices); live bindings come from the server's Environment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its remaining types (ScriptDocument, ScriptDialect, ClassIndex,
Signatures, Environment) come from scijava-code-lsp, and script
parameters from the LanguageServerService.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Variables assigned without a declaration (e.g. z = "abc") are script
bindings, which Groovy's type checker leaves untyped. A type-checking
extension now types each use of one as last assigned, in source order,
so that members complete (z.toU), and types flow on through calls
(y = z.subList(0, 1)). Bindings are offered with their types, too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Groovy language server now publishes the problems Groovy's compiler
and type checker find that also trouble a script when it runs: syntax
errors and unresolvable classes, as errors; and methods or properties a
known type lacks (e.g. "abc".fooBar()), as warnings. Complaints about
dynamically typed code, which Groovy resolves at run time, are left
out. Positions are those of the script as written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
code-lsp's signatures no longer carry their fit; the best fits still
come first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The server no longer reads #@ lines: the session declares the
parameters (in GroovyDialect), and blanks those lines. It still
declares a live interpreter's variables itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The language server, its plugin, its dialect, and the analysis move to
the completion package, with their tests.

GroovyAnalysis becomes TypedAST (the typed syntax tree of a script up to
the caret, and questions about it); its source is built by markCaret
and closeBrackets, and the tree by build.

The plugin serves the groovy LSP language too, so that
LanguageServerService.launch("groovy", ...) gives a GroovyLanguageServer
(see GroovyServerPluginTest).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
code-lsp's sessions ask for the LSP language named as the script's
language, in lower case, so the plugin no longer declares the script
language it serves separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GroovyDialect is now a ScriptDialect plugin, showing Groovy scripts to
scijava-code-lsp-groovy's server as plain Groovy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GroovyDialectTest keeps what needs SciJava scripts (#@ parameters).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The server sees the parameters declared in a line of their own and the
parameter lines blanked: one assertion checks that problems still map
back to the script's lines, the other that the blanking happens.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow scijava-code-lsp's rename of runtimeType to parameterType. The
dialect's tests now test each of its methods; what the server and
scijava-code-lsp do is theirs to test, but for one integration test
that the rewritten scripts are valid Groovy. So scijava-code-lsp-groovy
is needed only to test: applications choose their servers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dialect writes its parameters' declarations in one header line;
scijava-code-lsp now blanks the #@ lines itself, as SciJava removes them
before a script runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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