[
https://issues.apache.org/jira/browse/GROOVY-12411?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Daniel Sun updated GROOVY-12411:
--------------------------------
Description:
Ship an optional first-party language server ({{{}groovy-lsp{}}}) so editors
and AI tools can offer Groovy completion, navigation, diagnostics, and
conservative rename against the *in-tree* compiler.
h2. Why
Community servers lag language changes because they compile against a Groovy
snapshot, not this repository. {{groovy-lsp}} uses the same {{CompilationUnit}}
as the rest of Groovy, so parser and type-system work appear in editors
automatically.
It is a Groovy *language core* for the Language Server Protocol, not a
workspace or IDE. The differentiator is the same compiler, a small surface, and
edits that refuse to guess, not more IDE features.
h2. Intended use
* *Editor / IDE:* start {{groovylsp}} and speak stdio JSON-RPC. The client
supplies {{groovy.classpath}} / {{{}groovy.sourcePaths{}}}.
* *AI tools:* the same process is the semantic backend. A later {{groovy-mcp}}
module is expected to wrap it so a model can ask what an identifier is without
embedding the compiler.
* *Other Apache-2.0 Groovy LSPs:* extend the compile and protocol loop through
the incubating {{GroovyLspExtension}} SPI instead of forking it. Eclipse JDT /
groovy-eclipse servers remain a parallel stack; they cannot replace this
compiler through the SPI.
h2. Out of scope
These are strengths of other implementations and stay out on purpose:
* Joint Groovy+Java compilation and cross-language rename
* GDSL / Jenkins pipeline descriptors (a plugin may add them; this module does
not load GDSL)
* Invoking Gradle or Maven (no Tooling API)
* Debugger (DAP) and test runner
* Identifier-text rename fallbacks (rename every {{foo}} in the file)
* Extra name-span fields on {{AnnotatedNode}} (identifier selection is
{{Positions.toNameRange}} in groovy-lsp)
h2. Comparison with other Groovy language servers
Four implementations, four jobs. *groovy-lsp* is the in-tree language core. The
others keep the IDE-shaped work this module refuses.
*
[groovy-language-server|https://github.com/GroovyLanguageServer/groovy-language-server]
(Prominic): community server for Moonshine IDE. Apache 2.0 on a Groovy 4.0.26
dependency.
* [groovyls|https://github.com/trustytrojan/groovyls] (trustytrojan): Apache
2.0 fork of Prominic. Jenkins GDSL, forced STC on every class, Aether
downloads. Those features are hard-wired, not a plugin.
*
[groovy-language-server-edt|https://github.com/tomaszrup/groovy-language-server-edt]:
EPL 2.0, Equinox + JDT + groovy-eclipse. Joint Groovy+Java. Complementary
stack; none of its source is copied.
||Aspect||groovy-lsp||Prominic||groovyls||edt||
|License|Apache 2.0|Apache 2.0|Apache 2.0|EPL 2.0|
|Compiler|in-tree {{CompilationUnit}}|Groovy 4.0.26 jar|Groovy 5.1.1 jar|JDT +
groovy-eclipse|
|Phase|{{{}SEMANTIC_ANALYSIS{}}}, no
classgen|{{CANONICALIZATION}}|{{CANONICALIZATION}} + forced STC|JDT compile|
|Classpath|client {{groovy.classpath}}|client {{groovy.classpath}}|client +
Aether downloads|Red Hat Java / Gradle wrapper|
|GDSL / Jenkins|plugin, not core|no|yes|no|
|Joint Groovy+Java|no|no|no|yes|
|Rename|declarations and bound calls only|AST references + name regex|same as
Prominic|JDT; identifier-scan fallback|
|Extension point|incubating {{GroovyLspExtension}}|none|none (baked in)|OSGi /
Equinox|
h2. Extensibility as a reusable base
{{groovy-lsp}} is meant to be the compile + protocol loop other *Apache-2.0*
Groovy language servers sit on, not a fork point. Plugins implement incubating
{{GroovyLspExtension}} ({{{}ServiceLoader{}}}; tests use
{{{}ExtensionHost{}}}). There is no second hover/completion SPI: inject members
in {{afterCompile}} so core hover, completion, navigation, and rename see them.
||Hook||For||
|{{configure(config, session)}}|extra classpath, extra {{groovy.*}} settings
(for example {{{}groovy.dependencies{}}})|
|{{initialized}} / {{shutdown}}|load or release catalogs|
|{{afterCompile(CompilationUnit)}}|GDSL injection, a forced STC pass; must not
generate class files|
|{{extraDiagnostics}} / {{extraCodeActions}}|plugin diagnostics and actions
({{{}ModuleNode{}}} is groovy-core AST)|
|{{commands}} / {{executeCommand}}|extra workspace commands via
{{GroovyLspSession.applyEdit}}|
{{GroovyLspSession}} is apply-edit, document text, folders, classpath, source
paths, extra settings, and position encoding. It is not a compile handle. A
throwing plugin is isolated and must not compile or publish on its own. The
built-in {{groovy.lsp.stc}} extension is the example: annotated
{{@TypeChecked}} / {{@CompileStatic}} only.
* *groovyls* can sit on this SPI. GDSL inject and forced-on-all-classes STC
belong in {{{}afterCompile{}}}; Aether downloads belong in {{configure}} from
extra settings. Semantic tokens and conservative navigation are already in
core. That is a plugin, not a paste of groovyls sources.
* *Prominic groovy-language-server* has no unique language feature left.
Moonshine can run {{groovylsp}} and supply {{{}groovy.classpath{}}}. A
Moonshine-only command would be a tiny plugin.
* *groovy-language-server-edt* cannot. The SPI does not replace
{{CompilationUnit}} with JDT. Joint compilation stays on that parallel stack.
Its identifier-scan rename fallback is not adopted.
The SPI is incubating: design may still settle. It is a seam for Apache-2.0
reuse, not a stability promise and not a slot for an Equinox compiler.
h2. Rename and dynamically typed Groovy
{{MethodCallExpression.methodTarget}} is often empty in dynamic Groovy. A
name-and-arity match is a heuristic: good enough for hover, not for rewriting
source.
||Feature||When {{methodTarget}} is set||When it is not (typical dynamic
Groovy)||
|Hover|Bound signature|Unique arity match on a resolved receiver, labelled
{{{}_inferred_{}}}; otherwise {{name(...)}}|
|Definition|That method|Every arity-matching candidate with a source location;
never a random first match|
|Rename / prepareRename|Allowed|Refused. A heuristic must not rewrite the wrong
overload.|
Declarations (class, method, field, parameter, bound local) rename by identity
(owner + name + descriptor), not the unqualified identifier. Class rename also
renames the file when the class name matches the file stem.
h2. AST columns (not a breaking change)
Compiler AST columns were already 1-based. The parser writes
{{{}setColumnNumber(token.getCharPositionInLine() + 1){}}}; ANTLR's
{{getCharPositionInLine()}} is 0-based, Groovy's AST is not. Authored source
starts at column 1, the end column is exclusive, and missing positions are
{{{}-1{}}}.
GROOVY-12085 changed the *unit* (Unicode code points instead of UTF-16 units).
It did not change 0-based vs 1-based.
The patch also corrects {{ASTNode}} javadoc that had said "0-indexed" (added
2026-05-03, never shipped in a release). Getters, setters, and stored values
are unchanged. That is a documentation fix, not a runtime ABI change.
LSP positions stay 0-based in the encoding negotiated at {{initialize}}
({{{}utf-16{}}} by default; {{utf-8}} / {{utf-32}} optional). The server
converts; clients never see AST columns. Existing LSP clients do not need to
change how they send positions.
h2. What lands
* Optional subproject {{groovy-lsp}} ({{{}optionalModule(){}}}, not
{{{}groovy-all{}}})
* {{groovylsp}} / {{groovylsp.bat}} on the binary distribution (stdio JSON-RPC)
* LSP 3.18 over Eclipse LSP4J 1.0; unknown 3.19 fields ignored; advertise only
implemented capabilities
* LSP4J is EPL 2.0 Category B {*}binary{*}; its source is not mixed into Groovy
* Compile open buffers through {{SEMANTIC_ANALYSIS}} (no class generation)
* Incubating {{GroovyLspExtension}} ({{{}ServiceLoader{}}}). Built-in
{{groovy.lsp.stc}} runs STC only on {{@TypeChecked}} / {{@CompileStatic}}
members
* {{{}LocatedMessage{}}}: {{toDiagnostic()}} / {{write()}} no longer NPE when
the CST context is null
* Docs: {{{}groovy-lsp.adoc{}}}, {{subprojects/groovy-lsp/ARCHITECTURE.md}}
h2. Language features
File types: {{{}.groovy{}}}, {{{}.gvy{}}}, {{{}.gy{}}}, {{{}.gsh{}}}, or
{{{}languageId=groovy{}}}.
* *Editing:* incremental sync; completion (keywords, snippets, members,
workspace types with auto-import, GDK) and {{{}completionItem/resolve{}}};
format / range format / on-type indent; organize imports; unused-import hints;
generate accessors / {{toString}} / {{{}equals{}}}/{{{}hashCode{}}} /
constructor; add import, package, {{{}@Override{}}}, missing class stub
* *Navigation:* definition, type definition, implementation, declaration,
references (by identity); call and type hierarchy; document / workspace
symbols; folding; selection range; document highlight; import document links
* *Presentation:* push/pull diagnostics (compiler + unused import + STC on
annotated members); semantic tokens; inlay hints; reference-count code lenses
* *Workspace:* folders, watched files, configuration,
{{{}window/workDoneProgress{}}}, {{workspace/willRenameFiles}} for Groovy
sources
* *Commands:* {{{}groovy.lsp.organizeImports{}}},
{{{}groovy.lsp.showReferences{}}}, {{groovy.lsp.gotoSuperMethod}}
h2. Safety and classpath
* {{@Grab}} and {{@ASTTest}} off unless the client sets {{grapeEnabled}} /
{{astTestEnabled}}
* Diagnostics scoped to the owning source unit (shared {{{}ErrorCollector{}}})
* No Gradle or Maven Tooling API. If {{classpath}} / {{sourcePaths}} are
empty, fall back to {{src/main/groovy}} (and friends) and jars under {{lib}} /
{{libs}}
* Unchanged inputs skip recompilation; {{GroovyClassLoader}} is reused and
closed on shutdown
* A throwing plugin must not abort compile or a request
h2. How to run
{code:java}
groovylsp
groovylsp --stdio
groovylsp --socket <port>
groovylsp --help
groovylsp --version
{code}
Do not write to stdout from Groovy code running inside the server; the launcher
redirects {{System.out}} to {{System.err}} so stray prints cannot break the
protocol stream.
h2. See also
* GROOVY-12085 (code-point columns; not an origin change)
was:
Ship an optional first-party language server so editors and AI tools can offer
Groovy completion, navigation, diagnostics, and conservative rename against the
in-tree compiler.
h3. Why
Community servers lag language changes because they compile with a snapshot of
Groovy, not the tree this repository ships. {{groovy-lsp}} uses the same
{{CompilationUnit}} as the rest of Groovy, so parser and type-system work land
in editors automatically. It is a Groovy *language core* for LSP, not a
workspace or IDE: the differentiator is the same compiler, a small surface, and
edits that refuse to guess, not more IDE features.
h3. Intended use and vision
* Direct use in an IDE or editor: start {{groovylsp}} and speak stdio JSON-RPC.
The client supplies {{classpath}} / {{sourcePaths}}.
* The same process is the semantic backend for Groovy-aware AI. A later
{{groovy-mcp}} module is expected to wrap it so a model can ask what an
identifier is without embedding the compiler.
* Other Apache-2.0 Groovy language servers (and {{groovy-mcp}}) may extend the
compile and protocol loop through the incubating {{GroovyLspExtension}} SPI
instead of forking it. Eclipse JDT / groovy-eclipse servers remain a parallel
stack; they cannot replace this compiler through the SPI.
h3. What this is not
Out of scope on purpose (these are strengths of other implementations):
* Joint Groovy+Java compilation and cross-language rename
* GDSL / Jenkins pipeline descriptors (a plugin may add them; this module does
not load GDSL itself)
* Invoking Gradle or Maven (no Tooling API)
* Debugger (DAP) and test runner
* Identifier-text "rename every {{foo}} in the file" fallbacks
* Extra name-span fields on {{AnnotatedNode}}: identifier selection lives in
groovy-lsp ({{Positions.toNameRange}})
h3. Relation to other Groovy language servers
* Prominic {{groovy-language-server}}: earlier community server; this module is
a new implementation, not a fork.
* {{trustytrojan/groovyls}} (Apache 2.0): Jenkins GDSL and a forced
static-type-checking pass. Natural SPI consumer; those features stay out of
this module.
* {{tomaszrup/groovy-language-server-edt}} (EPL 2.0, JDT + groovy-eclipse):
complementary product for joint compilation and Java interop. None of its
source is copied. Its identifier-scan rename fallback is not used.
h3. Positions (not an LSP break)
GROOVY-12085 made *compiler* AST columns 1-based Unicode code points. That is
not an LSP coordinate change. Protocol positions stay 0-based in the encoding
negotiated at {{initialize}} ({{utf-16}} by default). The server converts;
clients never see AST columns. Existing LSP clients do not need to change how
they send positions.
h3. Rename and dynamically typed Groovy
{{MethodCallExpression.methodTarget}} is often empty in dynamic Groovy. A
name-and-arity match is a heuristic: good enough for hover, not for rewriting
source.
||Feature||When {{methodTarget}} is set||When it is not (typical dynamic
Groovy)||
|Hover|Bound signature|Unique arity match on a resolved receiver, labelled
{{inferred}}; otherwise {{name(...)}}|
|Definition|That method|Every arity-matching candidate with a source location;
never a random first match|
|Rename / prepareRename|Allowed|Refused. A heuristic must not rewrite the wrong
overload.|
Declarations (class, method, field, parameter, bound local) rename by identity
(owner + name + descriptor), not the unqualified identifier. Class rename also
renames the file when the class name matches the file stem.
h3. What to ship
* New optional subproject {{groovy-lsp}} (not part of {{groovy-all}})
* {{groovylsp}} / {{groovylsp.bat}} launchers (stdio JSON-RPC; optional
{{\-\-socket}})
* LSP 3.18 over Eclipse LSP4J 1.0; unknown 3.19 fields ignored; advertise only
implemented capabilities
* Compile open buffers through {{SEMANTIC_ANALYSIS}} (no class generation)
* Identifier selection in groovy-lsp from the node's existing source span (no
extra {{AnnotatedNode}} fields)
* Incubating {{GroovyLspExtension}} SPI ({{ServiceLoader}} / {{ExtensionHost}})
h3. Language features
* Incremental sync, push/pull diagnostics
* Completion (keywords, snippets, members, workspace types with auto-import,
GDK with a prefix) and {{completionItem/resolve}}
* Hover, signature help, document highlight
* Definition, type definition, implementation, declaration, references (by
declaration identity)
* Prepare-rename / rename as in the table above
* Document and workspace symbols, folding, selection range, semantic tokens,
inlay hints
* Organize imports (star, static, alias); unused-import hints
* Code actions: add import, implement abstracts, insert inferred field type,
add package from path, create missing class stub, generate accessors /
{{toString}} / {{equals}}/{{hashCode}} / constructor, add {{@Override}}
* Call hierarchy and type hierarchy
* Reference-count code lenses
h3. Safety and classpath
* {{@Grab}} and {{@ASTTest}} off unless the client sets {{grapeEnabled}} /
{{astTestEnabled}}
* Diagnostics scoped to the owning source unit (shared {{ErrorCollector}})
* No Gradle or Maven Tooling API; the client supplies {{classpath}} /
{{sourcePaths}}. If those are empty, fall back to {{src/main/groovy}} (and
friends) and jars under {{lib}} / {{libs}} (paths stored with {{/}} separators)
* Unchanged inputs skip recompilation; {{GroovyClassLoader}} is reused and
closed on shutdown
* A throwing plugin must not abort compile or a request
h3. How to run
{code}
groovylsp
{code}
Optional flags: {{\-\-stdio}} (default), {{\-\-socket port}}, {{\-\-help}},
{{\-\-version}}.
> Add a first-party Language Server Protocol implementation (groovy-lsp)
> ----------------------------------------------------------------------
>
> Key: GROOVY-12411
> URL: https://issues.apache.org/jira/browse/GROOVY-12411
> Project: Groovy
> Issue Type: Improvement
> Reporter: Daniel Sun
> Priority: Major
>
> Ship an optional first-party language server ({{{}groovy-lsp{}}}) so editors
> and AI tools can offer Groovy completion, navigation, diagnostics, and
> conservative rename against the *in-tree* compiler.
> h2. Why
> Community servers lag language changes because they compile against a Groovy
> snapshot, not this repository. {{groovy-lsp}} uses the same
> {{CompilationUnit}} as the rest of Groovy, so parser and type-system work
> appear in editors automatically.
> It is a Groovy *language core* for the Language Server Protocol, not a
> workspace or IDE. The differentiator is the same compiler, a small surface,
> and edits that refuse to guess, not more IDE features.
> h2. Intended use
> * *Editor / IDE:* start {{groovylsp}} and speak stdio JSON-RPC. The client
> supplies {{groovy.classpath}} / {{{}groovy.sourcePaths{}}}.
> * *AI tools:* the same process is the semantic backend. A later
> {{groovy-mcp}} module is expected to wrap it so a model can ask what an
> identifier is without embedding the compiler.
> * *Other Apache-2.0 Groovy LSPs:* extend the compile and protocol loop
> through the incubating {{GroovyLspExtension}} SPI instead of forking it.
> Eclipse JDT / groovy-eclipse servers remain a parallel stack; they cannot
> replace this compiler through the SPI.
> h2. Out of scope
> These are strengths of other implementations and stay out on purpose:
> * Joint Groovy+Java compilation and cross-language rename
> * GDSL / Jenkins pipeline descriptors (a plugin may add them; this module
> does not load GDSL)
> * Invoking Gradle or Maven (no Tooling API)
> * Debugger (DAP) and test runner
> * Identifier-text rename fallbacks (rename every {{foo}} in the file)
> * Extra name-span fields on {{AnnotatedNode}} (identifier selection is
> {{Positions.toNameRange}} in groovy-lsp)
> h2. Comparison with other Groovy language servers
> Four implementations, four jobs. *groovy-lsp* is the in-tree language core.
> The others keep the IDE-shaped work this module refuses.
> *
> [groovy-language-server|https://github.com/GroovyLanguageServer/groovy-language-server]
> (Prominic): community server for Moonshine IDE. Apache 2.0 on a Groovy
> 4.0.26 dependency.
> * [groovyls|https://github.com/trustytrojan/groovyls] (trustytrojan): Apache
> 2.0 fork of Prominic. Jenkins GDSL, forced STC on every class, Aether
> downloads. Those features are hard-wired, not a plugin.
> *
> [groovy-language-server-edt|https://github.com/tomaszrup/groovy-language-server-edt]:
> EPL 2.0, Equinox + JDT + groovy-eclipse. Joint Groovy+Java. Complementary
> stack; none of its source is copied.
> ||Aspect||groovy-lsp||Prominic||groovyls||edt||
> |License|Apache 2.0|Apache 2.0|Apache 2.0|EPL 2.0|
> |Compiler|in-tree {{CompilationUnit}}|Groovy 4.0.26 jar|Groovy 5.1.1 jar|JDT
> + groovy-eclipse|
> |Phase|{{{}SEMANTIC_ANALYSIS{}}}, no
> classgen|{{CANONICALIZATION}}|{{CANONICALIZATION}} + forced STC|JDT compile|
> |Classpath|client {{groovy.classpath}}|client {{groovy.classpath}}|client +
> Aether downloads|Red Hat Java / Gradle wrapper|
> |GDSL / Jenkins|plugin, not core|no|yes|no|
> |Joint Groovy+Java|no|no|no|yes|
> |Rename|declarations and bound calls only|AST references + name regex|same as
> Prominic|JDT; identifier-scan fallback|
> |Extension point|incubating {{GroovyLspExtension}}|none|none (baked in)|OSGi
> / Equinox|
> h2. Extensibility as a reusable base
> {{groovy-lsp}} is meant to be the compile + protocol loop other *Apache-2.0*
> Groovy language servers sit on, not a fork point. Plugins implement
> incubating {{GroovyLspExtension}} ({{{}ServiceLoader{}}}; tests use
> {{{}ExtensionHost{}}}). There is no second hover/completion SPI: inject
> members in {{afterCompile}} so core hover, completion, navigation, and rename
> see them.
> ||Hook||For||
> |{{configure(config, session)}}|extra classpath, extra {{groovy.*}} settings
> (for example {{{}groovy.dependencies{}}})|
> |{{initialized}} / {{shutdown}}|load or release catalogs|
> |{{afterCompile(CompilationUnit)}}|GDSL injection, a forced STC pass; must
> not generate class files|
> |{{extraDiagnostics}} / {{extraCodeActions}}|plugin diagnostics and actions
> ({{{}ModuleNode{}}} is groovy-core AST)|
> |{{commands}} / {{executeCommand}}|extra workspace commands via
> {{GroovyLspSession.applyEdit}}|
> {{GroovyLspSession}} is apply-edit, document text, folders, classpath, source
> paths, extra settings, and position encoding. It is not a compile handle. A
> throwing plugin is isolated and must not compile or publish on its own. The
> built-in {{groovy.lsp.stc}} extension is the example: annotated
> {{@TypeChecked}} / {{@CompileStatic}} only.
> * *groovyls* can sit on this SPI. GDSL inject and forced-on-all-classes STC
> belong in {{{}afterCompile{}}}; Aether downloads belong in {{configure}} from
> extra settings. Semantic tokens and conservative navigation are already in
> core. That is a plugin, not a paste of groovyls sources.
> * *Prominic groovy-language-server* has no unique language feature left.
> Moonshine can run {{groovylsp}} and supply {{{}groovy.classpath{}}}. A
> Moonshine-only command would be a tiny plugin.
> * *groovy-language-server-edt* cannot. The SPI does not replace
> {{CompilationUnit}} with JDT. Joint compilation stays on that parallel stack.
> Its identifier-scan rename fallback is not adopted.
> The SPI is incubating: design may still settle. It is a seam for Apache-2.0
> reuse, not a stability promise and not a slot for an Equinox compiler.
> h2. Rename and dynamically typed Groovy
> {{MethodCallExpression.methodTarget}} is often empty in dynamic Groovy. A
> name-and-arity match is a heuristic: good enough for hover, not for rewriting
> source.
> ||Feature||When {{methodTarget}} is set||When it is not (typical dynamic
> Groovy)||
> |Hover|Bound signature|Unique arity match on a resolved receiver, labelled
> {{{}_inferred_{}}}; otherwise {{name(...)}}|
> |Definition|That method|Every arity-matching candidate with a source
> location; never a random first match|
> |Rename / prepareRename|Allowed|Refused. A heuristic must not rewrite the
> wrong overload.|
> Declarations (class, method, field, parameter, bound local) rename by
> identity (owner + name + descriptor), not the unqualified identifier. Class
> rename also renames the file when the class name matches the file stem.
> h2. AST columns (not a breaking change)
> Compiler AST columns were already 1-based. The parser writes
> {{{}setColumnNumber(token.getCharPositionInLine() + 1){}}}; ANTLR's
> {{getCharPositionInLine()}} is 0-based, Groovy's AST is not. Authored source
> starts at column 1, the end column is exclusive, and missing positions are
> {{{}-1{}}}.
> GROOVY-12085 changed the *unit* (Unicode code points instead of UTF-16
> units). It did not change 0-based vs 1-based.
> The patch also corrects {{ASTNode}} javadoc that had said "0-indexed" (added
> 2026-05-03, never shipped in a release). Getters, setters, and stored values
> are unchanged. That is a documentation fix, not a runtime ABI change.
> LSP positions stay 0-based in the encoding negotiated at {{initialize}}
> ({{{}utf-16{}}} by default; {{utf-8}} / {{utf-32}} optional). The server
> converts; clients never see AST columns. Existing LSP clients do not need to
> change how they send positions.
> h2. What lands
> * Optional subproject {{groovy-lsp}} ({{{}optionalModule(){}}}, not
> {{{}groovy-all{}}})
> * {{groovylsp}} / {{groovylsp.bat}} on the binary distribution (stdio
> JSON-RPC)
> * LSP 3.18 over Eclipse LSP4J 1.0; unknown 3.19 fields ignored; advertise
> only implemented capabilities
> * LSP4J is EPL 2.0 Category B {*}binary{*}; its source is not mixed into
> Groovy
> * Compile open buffers through {{SEMANTIC_ANALYSIS}} (no class generation)
> * Incubating {{GroovyLspExtension}} ({{{}ServiceLoader{}}}). Built-in
> {{groovy.lsp.stc}} runs STC only on {{@TypeChecked}} / {{@CompileStatic}}
> members
> * {{{}LocatedMessage{}}}: {{toDiagnostic()}} / {{write()}} no longer NPE
> when the CST context is null
> * Docs: {{{}groovy-lsp.adoc{}}}, {{subprojects/groovy-lsp/ARCHITECTURE.md}}
> h2. Language features
> File types: {{{}.groovy{}}}, {{{}.gvy{}}}, {{{}.gy{}}}, {{{}.gsh{}}}, or
> {{{}languageId=groovy{}}}.
> * *Editing:* incremental sync; completion (keywords, snippets, members,
> workspace types with auto-import, GDK) and {{{}completionItem/resolve{}}};
> format / range format / on-type indent; organize imports; unused-import
> hints; generate accessors / {{toString}} / {{{}equals{}}}/{{{}hashCode{}}} /
> constructor; add import, package, {{{}@Override{}}}, missing class stub
> * *Navigation:* definition, type definition, implementation, declaration,
> references (by identity); call and type hierarchy; document / workspace
> symbols; folding; selection range; document highlight; import document links
> * *Presentation:* push/pull diagnostics (compiler + unused import + STC on
> annotated members); semantic tokens; inlay hints; reference-count code lenses
> * *Workspace:* folders, watched files, configuration,
> {{{}window/workDoneProgress{}}}, {{workspace/willRenameFiles}} for Groovy
> sources
> * *Commands:* {{{}groovy.lsp.organizeImports{}}},
> {{{}groovy.lsp.showReferences{}}}, {{groovy.lsp.gotoSuperMethod}}
> h2. Safety and classpath
> * {{@Grab}} and {{@ASTTest}} off unless the client sets {{grapeEnabled}} /
> {{astTestEnabled}}
> * Diagnostics scoped to the owning source unit (shared
> {{{}ErrorCollector{}}})
> * No Gradle or Maven Tooling API. If {{classpath}} / {{sourcePaths}} are
> empty, fall back to {{src/main/groovy}} (and friends) and jars under {{lib}}
> / {{libs}}
> * Unchanged inputs skip recompilation; {{GroovyClassLoader}} is reused and
> closed on shutdown
> * A throwing plugin must not abort compile or a request
> h2. How to run
> {code:java}
> groovylsp
> groovylsp --stdio
> groovylsp --socket <port>
> groovylsp --help
> groovylsp --version
> {code}
> Do not write to stdout from Groovy code running inside the server; the
> launcher redirects {{System.out}} to {{System.err}} so stray prints cannot
> break the protocol stream.
> h2. See also
> * GROOVY-12085 (code-point columns; not an origin change)
--
This message was sent by Atlassian Jira
(v8.20.10#820010)