[ 
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 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}}.

  was:
Ship an optional first-party language server so editors can offer Groovy 
completion, navigation, diagnostics, and refactorings against the in-tree 
compiler rather than a community fork.

h3. Why

Community servers ({{groovy-language-server}}, {{gvy}}/{{gls}}) lag language 
changes. A module in this repository compiles with the same {{CompilationUnit}} 
the rest of Groovy uses, so parser and type-system work land in the IDE 
automatically.

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
* Compile open buffers through {{SEMANTIC_ANALYSIS}} (no class generation)
* Identifier name spans on {{AnnotatedNode}} so rename/highlight select the 
name, not the whole declaration (same 1-based code-point columns as 
GROOVY-12085)

h3. Language features (advertise only what is implemented)

* 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 (rename the file when the class name matches the file 
stem)
* 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}}
* Unchanged inputs skip recompilation; {{GroovyClassLoader}} is reused and 
closed on shutdown

h3. Out of scope

* Debugger (DAP)
* Test runner
* Invoking Gradle or Maven to resolve the project

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 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}}.



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

Reply via email to