[ 
https://issues.apache.org/jira/browse/GROOVY-12411?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Daniel Sun updated GROOVY-12411:
--------------------------------
    Description: 
Apache Groovy needs a language server that uses the compiler in this 
repository. Community servers compile against a published Groovy jar, so parser 
and type-system changes reach an editor only after that jar is released. This 
change adds an optional {{groovy-lsp}} module and a {{groovylsp}} command. 
Editors, and later AI tools, share that language core. It is not a full IDE, 
and it does not replace Groovy-Eclipse or IntelliJ.

h2. Why this shape

The server compiles the open buffers and answers Language Server Protocol (LSP) 
requests from that snapshot. A language change in this tree shows up in the 
server without forking a community project. The server refuses edits that would 
guess: it will not rename an unbound dynamic call, and it will not rewrite 
every token that happens to spell the same name.

There is no public extension SPI in this first cut. No ServiceLoader hook, no 
OSGi bundle, and no second hover or completion API. Static type checking of 
annotated members is core behavior, not a plugin. A later {{groovy-mcp}} 
wrapper may call the in-process engine. That wrapper is not part of this change.

h2. What lands

* Optional subproject {{groovy-lsp}}. It is not part of {{groovy-all}}.
* {{groovylsp}} and {{groovylsp.bat}} on the binary distribution. The default 
transport is stdio. {{\-\-socket}} accepts one TCP client. {{\-\-help}} and 
{{\-\-version}} print and exit.
* LSP 3.18, carried by Eclipse LSP4J 1.0. Fields from a newer draft that the 
server does not understand are ignored. A capability is advertised only when it 
is implemented.
* LSP4J is an EPL 2.0 Category B binary. Its sources are not copied into Groovy.
* Open Groovy buffers compile through semantic analysis. The server does not 
generate Groovy classes.
* {{.java}} files in the workspace are joint-compiled with 
{{JavaAwareCompilationUnit}} ({{memStub}}) and {{javax.tools}} javac, with 
annotation processing off.
* After semantic analysis, a core pass type-checks members annotated 
{{@TypeChecked}} or {{@CompileStatic}}. It skips {{@CompileDynamic}} and 
{{TypeCheckingMode.SKIP}}, and it does not force static checking on ordinary 
dynamic Groovy.
* {{GroovyLanguageEngine}} is the in-process API: file paths, 0-based UTF-16 
positions, and short source snippets. Rename returns edits and does not write 
the files.
* {{LocatedMessage.toDiagnostic()}} and {{write()}} no longer throw 
{{NullPointerException}} when the parse context is null. They report the 
message with no line or column.
* {{ASTNode}} column javadoc now matches the compiler: columns are 1-based 
Unicode code points, the end column is exclusive, and a missing position is -1. 
Getters, setters, and stored values are unchanged. See GROOVY-12085.
* User guide {{groovy-lsp.adoc}} and contributor map 
{{subprojects/groovy-lsp/ARCHITECTURE.md}}.

h2. What an editor gets

Recognized sources are {{.groovy}}, {{.gvy}}, {{.gy}}, {{.gsh}}, or language id 
{{groovy}}.

* *Editing:* incremental sync; completion of keywords, snippets, members, 
workspace types (with an import edit), and GDK members; Groovydoc filled in 
when the client resolves a completion item; format, range format, and on-type 
indent; organize imports, keeping star, static, and alias imports; 
unused-import hints; code actions to add an import, add a package from the 
path, implement abstract methods, insert an inferred type, create a missing 
class stub, add {{@Override}}, and generate accessors, {{toString}}, {{equals}} 
and {{hashCode}}, and a constructor.
* *Navigation:* definition, type definition, implementation, declaration, and 
references. References match the declaration (owner, name, and descriptor), not 
the bare spelling. Call hierarchy and type hierarchy. Document symbols and 
workspace symbols. A workspace-symbol query may be a case-insensitive substring 
or CamelHumps, so {{ASF}} finds {{AbstractServerFactory}}. Folding, selection 
ranges, document highlight, and document links on imports.
* *Presentation:* push and pull diagnostics (compiler messages, unused imports, 
static-type errors on annotated members, and javac messages from a joint 
compile). Semantic tokens. Inlay hints for declaration types and for parameter 
names. Code lenses that show a reference count.
* *Workspace:* workspace folders, watched files, configuration, and progress 
when the client asks for it. {{workspace/willRenameFiles}} updates one 
top-level Groovy class whose name matches the file name without its extension. 
It refuses a script, a file that declares several types, a class name that does 
not match, and {{.java}}.

Commands:

* {{groovy.lsp.organizeImports}}
* {{groovy.lsp.showReferences}}
* {{groovy.lsp.gotoSuperMethod}} (nearest overridden method that has source; 
skips {{Object}} and {{GroovyObject}})

h2. Rename

{{methodTarget}} is often empty on a dynamic call. A match by name and arity is 
enough to display, and not enough to edit.

||Feature||When the compiler bound the call||When it did not||
|Hover|The bound signature|One arity match on a resolved receiver, marked 
{{_inferred_}}; otherwise the name only|
|Definition|That method|Every arity match that has source. Never an arbitrary 
first hit|
|Rename and prepare-rename|Allowed|Refused|

A class, method, field, parameter, or bound local is renamed by identity. 
Renaming a class also renames the file when the class name matches the file 
name without its extension. An inlay marked {{inferred}} is display only. It 
does not insert text.

h2. Groovy and Java in one workspace

Joint compilation lets Groovy and Java sources in the workspace see each 
other's types. Go to definition crosses the language boundary through 
{{JavaSymbolIndex}}, and javac diagnostics are published the same way. javac 
class files go to a temporary directory and are removed on the next compile. 
This is not a Java language server. Java completion, Java formatting, and 
Java-only rename stay with a Java language server. Eclipse JDT and 
groovy-eclipse remain the stack for a full Java IDE. No source is copied from 
the EPL server groovy-language-server-edt, and its identifier-scan rename is 
not adopted.

||Question||groovy-lsp||Other Groovy language servers||
|Which compiler|The compiler in this repository|A published Groovy jar, or JDT 
plus groovy-eclipse|
|Java IDE features|Joint type resolution and cross-language definition|Java 
completion, formatting, and Java-only rename|
|GDSL and dependency download|Not included|groovyls adds Jenkins GDSL and 
dependency download|
|Unbound-call rename|Refused|An identifier-scan fallback exists in 
groovy-language-server-edt|

h2. Configuration and safety

On {{initialized}}, if the client advertised {{workspace/configuration}}, the 
server asks for the {{groovy}} section without blocking the JSON-RPC reader. 
The client can also push {{workspace/didChangeConfiguration}}.

||Key||Meaning||
|classpath|Extra jars and directories. The server does not run Gradle or Maven|
|sourcePaths|Extra source roots, relative to a workspace folder when not 
absolute|
|grapeEnabled|Allow {{@Grab}} while compiling. Default is off|
|astTestEnabled|Allow {{@ASTTest}} while compiling. Default is off|

Any other key in the {{groovy}} section is stored as text. The server does not 
interpret it and does not download anything for it. Changing it builds a new 
class loader and recompiles.

When classpath and source paths are empty, the server looks for 
{{src/main/groovy}}, {{src/test/groovy}}, {{src/main/java}}, and 
{{src/test/java}}, then {{src}}, then the workspace folder itself, plus jars 
directly under {{lib}} or {{libs}}.

Diagnostics are limited to the file that owns them. Unchanged buffers are not 
compiled again. {{@Grab}} and {{@ASTTest}} stay off unless the client turns 
them on, because both can run code at compile time.

h2. Out of scope

* A full Java language server.
* GDSL and Jenkins pipeline descriptors.
* Invoking Gradle or Maven, including the Tooling API.
* A debugger or a test runner.
* Renaming by identifier text.
* Name-span fields on {{AnnotatedNode}}. Identifier ranges stay inside 
groovy-lsp.
* A public plugin SPI.

h2. Positions

This is not an LSP break. Compiler columns are already 1-based Unicode code 
points (GROOVY-12085). LSP positions stay 0-based in the encoding chosen at 
initialize: {{utf-16}} unless the client offers {{utf-8}} or {{utf-32}}. The 
server converts both ways, including characters outside the Basic Multilingual 
Plane. Existing clients keep sending positions as they do today.

h2. Running

{code}
groovylsp
groovylsp --stdio
groovylsp --socket PORT
groovylsp --help
groovylsp --version
{code}

An editor should start that process and speak JSON-RPC on stdin and stdout. 
While the server is on stdio, standard output is redirected to standard error 
so a print from Groovy code cannot corrupt the protocol stream.


  was:
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 for a full Java IDE; they cannot 
replace this compiler through the SPI.

h2. Out of scope

These are strengths of other implementations and stay out on purpose:

* A full Java language server (Java completion, Java format, Java-only rename). 
Joint *type resolution* is in scope (see below)
* 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. Joint Groovy and Java sources

When the workspace contains {{.java}} files, groovy-lsp joint-compiles them 
with Groovy through in-tree {{JavaAwareCompilationUnit}} ({{memStub}}): Parrot 
to {{CONVERSION}}, in-memory Java stubs, {{javax.tools}} javac with annotation 
processing off, then Groovy {{SEMANTIC_ANALYSIS}} (no Groovy class generation). 
Open Java buffers overlay the filesystem. Javac diagnostics and 
go-to-definition cross the language boundary via {{JavaSymbolIndex}} 
({{com.sun.source}} {{Trees}}, captured before {{generate()}}).

That is type resolution and navigation, not a Java language server. Java 
completion, Java formatting, and Java-only rename stay with a Java LS or 
[groovy-language-server-edt|https://github.com/tomaszrup/groovy-language-server-edt].

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. Full Java LS and joint IDE features. 
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 Groovy 
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|{{JavaAwareCompilationUnit}} + {{memStub}}; 
def/hover|no|no|yes (JDT IDE)|
|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, conservative navigation, and joint type resolution 
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 replace {{CompilationUnit}} with JDT 
through the SPI. Joint *type resolution* is now in groovy-lsp core; edt remains 
the complementary full Java IDE (library sources, file-move imports). 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 Groovy buffers through {{SEMANTIC_ANALYSIS}} (no Groovy class 
generation)
* Joint compile of workspace {{.java}} via {{JavaAwareCompilationUnit}} + 
{{memStub}} and {{javax.tools}} javac
* 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}}. 
Workspace {{.java}} participates in joint compile (diagnostics, definition, 
hover), not as a Java language server.

* *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; 
Groovy to Java and Java to Groovy definition on jointly compiled types
* *Presentation:* push/pull diagnostics (compiler + unused import + STC on 
annotated members + javac); 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}}, {{src/main/java}} (and friends) and jars 
under {{lib}} / {{libs}}
* Unchanged inputs skip recompilation; {{GroovyClassLoader}} is reused and 
closed on shutdown
* Joint javac output is a per-compile directory under {{.groovy/lsp-javac}}, 
owner-only where POSIX allows, deleted on the next compile
* A throwing plugin must not abort compile or a request

h2. How to run

{code}
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)


> 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
>
> Apache Groovy needs a language server that uses the compiler in this 
> repository. Community servers compile against a published Groovy jar, so 
> parser and type-system changes reach an editor only after that jar is 
> released. This change adds an optional {{groovy-lsp}} module and a 
> {{groovylsp}} command. Editors, and later AI tools, share that language core. 
> It is not a full IDE, and it does not replace Groovy-Eclipse or IntelliJ.
> h2. Why this shape
> The server compiles the open buffers and answers Language Server Protocol 
> (LSP) requests from that snapshot. A language change in this tree shows up in 
> the server without forking a community project. The server refuses edits that 
> would guess: it will not rename an unbound dynamic call, and it will not 
> rewrite every token that happens to spell the same name.
> There is no public extension SPI in this first cut. No ServiceLoader hook, no 
> OSGi bundle, and no second hover or completion API. Static type checking of 
> annotated members is core behavior, not a plugin. A later {{groovy-mcp}} 
> wrapper may call the in-process engine. That wrapper is not part of this 
> change.
> h2. What lands
> * Optional subproject {{groovy-lsp}}. It is not part of {{groovy-all}}.
> * {{groovylsp}} and {{groovylsp.bat}} on the binary distribution. The default 
> transport is stdio. {{\-\-socket}} accepts one TCP client. {{\-\-help}} and 
> {{\-\-version}} print and exit.
> * LSP 3.18, carried by Eclipse LSP4J 1.0. Fields from a newer draft that the 
> server does not understand are ignored. A capability is advertised only when 
> it is implemented.
> * LSP4J is an EPL 2.0 Category B binary. Its sources are not copied into 
> Groovy.
> * Open Groovy buffers compile through semantic analysis. The server does not 
> generate Groovy classes.
> * {{.java}} files in the workspace are joint-compiled with 
> {{JavaAwareCompilationUnit}} ({{memStub}}) and {{javax.tools}} javac, with 
> annotation processing off.
> * After semantic analysis, a core pass type-checks members annotated 
> {{@TypeChecked}} or {{@CompileStatic}}. It skips {{@CompileDynamic}} and 
> {{TypeCheckingMode.SKIP}}, and it does not force static checking on ordinary 
> dynamic Groovy.
> * {{GroovyLanguageEngine}} is the in-process API: file paths, 0-based UTF-16 
> positions, and short source snippets. Rename returns edits and does not write 
> the files.
> * {{LocatedMessage.toDiagnostic()}} and {{write()}} no longer throw 
> {{NullPointerException}} when the parse context is null. They report the 
> message with no line or column.
> * {{ASTNode}} column javadoc now matches the compiler: columns are 1-based 
> Unicode code points, the end column is exclusive, and a missing position is 
> -1. Getters, setters, and stored values are unchanged. See GROOVY-12085.
> * User guide {{groovy-lsp.adoc}} and contributor map 
> {{subprojects/groovy-lsp/ARCHITECTURE.md}}.
> h2. What an editor gets
> Recognized sources are {{.groovy}}, {{.gvy}}, {{.gy}}, {{.gsh}}, or language 
> id {{groovy}}.
> * *Editing:* incremental sync; completion of keywords, snippets, members, 
> workspace types (with an import edit), and GDK members; Groovydoc filled in 
> when the client resolves a completion item; format, range format, and on-type 
> indent; organize imports, keeping star, static, and alias imports; 
> unused-import hints; code actions to add an import, add a package from the 
> path, implement abstract methods, insert an inferred type, create a missing 
> class stub, add {{@Override}}, and generate accessors, {{toString}}, 
> {{equals}} and {{hashCode}}, and a constructor.
> * *Navigation:* definition, type definition, implementation, declaration, and 
> references. References match the declaration (owner, name, and descriptor), 
> not the bare spelling. Call hierarchy and type hierarchy. Document symbols 
> and workspace symbols. A workspace-symbol query may be a case-insensitive 
> substring or CamelHumps, so {{ASF}} finds {{AbstractServerFactory}}. Folding, 
> selection ranges, document highlight, and document links on imports.
> * *Presentation:* push and pull diagnostics (compiler messages, unused 
> imports, static-type errors on annotated members, and javac messages from a 
> joint compile). Semantic tokens. Inlay hints for declaration types and for 
> parameter names. Code lenses that show a reference count.
> * *Workspace:* workspace folders, watched files, configuration, and progress 
> when the client asks for it. {{workspace/willRenameFiles}} updates one 
> top-level Groovy class whose name matches the file name without its 
> extension. It refuses a script, a file that declares several types, a class 
> name that does not match, and {{.java}}.
> Commands:
> * {{groovy.lsp.organizeImports}}
> * {{groovy.lsp.showReferences}}
> * {{groovy.lsp.gotoSuperMethod}} (nearest overridden method that has source; 
> skips {{Object}} and {{GroovyObject}})
> h2. Rename
> {{methodTarget}} is often empty on a dynamic call. A match by name and arity 
> is enough to display, and not enough to edit.
> ||Feature||When the compiler bound the call||When it did not||
> |Hover|The bound signature|One arity match on a resolved receiver, marked 
> {{_inferred_}}; otherwise the name only|
> |Definition|That method|Every arity match that has source. Never an arbitrary 
> first hit|
> |Rename and prepare-rename|Allowed|Refused|
> A class, method, field, parameter, or bound local is renamed by identity. 
> Renaming a class also renames the file when the class name matches the file 
> name without its extension. An inlay marked {{inferred}} is display only. It 
> does not insert text.
> h2. Groovy and Java in one workspace
> Joint compilation lets Groovy and Java sources in the workspace see each 
> other's types. Go to definition crosses the language boundary through 
> {{JavaSymbolIndex}}, and javac diagnostics are published the same way. javac 
> class files go to a temporary directory and are removed on the next compile. 
> This is not a Java language server. Java completion, Java formatting, and 
> Java-only rename stay with a Java language server. Eclipse JDT and 
> groovy-eclipse remain the stack for a full Java IDE. No source is copied from 
> the EPL server groovy-language-server-edt, and its identifier-scan rename is 
> not adopted.
> ||Question||groovy-lsp||Other Groovy language servers||
> |Which compiler|The compiler in this repository|A published Groovy jar, or 
> JDT plus groovy-eclipse|
> |Java IDE features|Joint type resolution and cross-language definition|Java 
> completion, formatting, and Java-only rename|
> |GDSL and dependency download|Not included|groovyls adds Jenkins GDSL and 
> dependency download|
> |Unbound-call rename|Refused|An identifier-scan fallback exists in 
> groovy-language-server-edt|
> h2. Configuration and safety
> On {{initialized}}, if the client advertised {{workspace/configuration}}, the 
> server asks for the {{groovy}} section without blocking the JSON-RPC reader. 
> The client can also push {{workspace/didChangeConfiguration}}.
> ||Key||Meaning||
> |classpath|Extra jars and directories. The server does not run Gradle or 
> Maven|
> |sourcePaths|Extra source roots, relative to a workspace folder when not 
> absolute|
> |grapeEnabled|Allow {{@Grab}} while compiling. Default is off|
> |astTestEnabled|Allow {{@ASTTest}} while compiling. Default is off|
> Any other key in the {{groovy}} section is stored as text. The server does 
> not interpret it and does not download anything for it. Changing it builds a 
> new class loader and recompiles.
> When classpath and source paths are empty, the server looks for 
> {{src/main/groovy}}, {{src/test/groovy}}, {{src/main/java}}, and 
> {{src/test/java}}, then {{src}}, then the workspace folder itself, plus jars 
> directly under {{lib}} or {{libs}}.
> Diagnostics are limited to the file that owns them. Unchanged buffers are not 
> compiled again. {{@Grab}} and {{@ASTTest}} stay off unless the client turns 
> them on, because both can run code at compile time.
> h2. Out of scope
> * A full Java language server.
> * GDSL and Jenkins pipeline descriptors.
> * Invoking Gradle or Maven, including the Tooling API.
> * A debugger or a test runner.
> * Renaming by identifier text.
> * Name-span fields on {{AnnotatedNode}}. Identifier ranges stay inside 
> groovy-lsp.
> * A public plugin SPI.
> h2. Positions
> This is not an LSP break. Compiler columns are already 1-based Unicode code 
> points (GROOVY-12085). LSP positions stay 0-based in the encoding chosen at 
> initialize: {{utf-16}} unless the client offers {{utf-8}} or {{utf-32}}. The 
> server converts both ways, including characters outside the Basic 
> Multilingual Plane. Existing clients keep sending positions as they do today.
> h2. Running
> {code}
> groovylsp
> groovylsp --stdio
> groovylsp --socket PORT
> groovylsp --help
> groovylsp --version
> {code}
> An editor should start that process and speak JSON-RPC on stdin and stdout. 
> While the server is on stdio, standard output is redirected to standard error 
> so a print from Groovy code cannot corrupt the protocol stream.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to