[ 
https://issues.apache.org/jira/browse/GROOVY-12411?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18124625#comment-18124625
 ] 

ASF GitHub Bot commented on GROOVY-12411:
-----------------------------------------

sonarqubecloud[bot] commented on PR #2936:
URL: https://github.com/apache/groovy/pull/2936#issuecomment-6043753494

   ## [![Quality Gate 
Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png
 'Quality Gate 
Passed')](https://sonarcloud.io/dashboard?id=apache_groovy&pullRequest=2936) 
**Quality Gate passed**  
   Issues  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [1 New 
issue](https://sonarcloud.io/project/issues?id=apache_groovy&pullRequest=2936&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png
 '') [0 Accepted 
issues](https://sonarcloud.io/project/issues?id=apache_groovy&pullRequest=2936&issueStatuses=ACCEPTED)
   
   Measures  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0 Security 
Hotspots](https://sonarcloud.io/project/security_hotspots?id=apache_groovy&pullRequest=2936&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [92.3% Coverage on New 
Code](https://sonarcloud.io/component_measures?id=apache_groovy&pullRequest=2936&metric=new_coverage&view=list)
  
   
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png
 '') [0.0% Duplication on New 
Code](https://sonarcloud.io/component_measures?id=apache_groovy&pullRequest=2936&metric=new_duplicated_lines_density&view=list)
  
     
   <!

> 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. Commit d014387ced2187dd7a129d77b34048a892bdecd5 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 with the in-tree compiler 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 an edit that would guess. It does not rename an unbound 
> dynamic call, and it does 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}}. The 
> binary distribution adds {{groovylsp}} and {{groovylsp.bat}}.
> * The default transport is stdio. {{\-\-socket}} accepts one TCP client. 
> {{\-\-help}} and {{\-\-version}} print and exit. On stdio, standard output is 
> redirected to standard error, so a print from Groovy code cannot corrupt the 
> protocol stream.
> * The protocol is 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 class files. Errors are collected, and a partial AST is still 
> queried.
> * {{.java}} files in the workspace are joint-compiled with 
> {{JavaAwareCompilationUnit}} ({{memStub}}) and {{javax.tools}} javac. 
> Annotation processing is off.
> * After semantic analysis, {{StaticTypeCheckingPass}} type-checks members 
> annotated {{@TypeChecked}} or {{@CompileStatic}}. It skips 
> {{@CompileDynamic}} and {{TypeCheckingMode.SKIP}}. It does not force static 
> checking on ordinary dynamic Groovy, and it does not raise the compile phase.
> * {{LocatedMessage.toDiagnostic()}} and {{write()}} report the message with 
> no line or column when the parse context is null. They no longer throw 
> {{NullPointerException}} in that case.
> * {{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}}. Contributor map 
> {{subprojects/groovy-lsp/ARCHITECTURE.md}}.
> h2. In-process engine
> {{GroovyLanguageEngine}} answers the same questions as the LSP handlers and 
> returns JDK records. Constructing it does not scan a workspace, so it does 
> not compile a checkout root.
> * {{open(Path)}} reads one file from disk and returns its URI. Queries take 
> that URI and use 0-based UTF-16 positions.
> * {{openBuffer}}, {{updateBuffer}}, and {{closeBuffer}} take any URI the 
> caller chooses. A URI whose scheme is not {{file}} is not treated as a path. 
> The engine does not reserve buffer names.
> * {{open}} and {{openBuffer}} compile immediately. {{updateBuffer}} only 
> replaces the text. The next query compiles when the buffer has changed, and 
> {{compileNow}} compiles at once. {{closeBuffer}} drops the buffer and 
> compiles what remains.
> * {{setParentLoader}} sets the parent loader. {{setClasspath}} replaces the 
> compile classpath. {{putExtra}} stores an opaque fingerprint so an in-place 
> change to the same loader still forces a new compile.
> * Rename, format, and organize-imports return edits. They do not write files.
> Groovy Console and groovysh are not connected to this engine in this change.
> 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 when a prefix is typed. 
> Groovydoc is filled when the client resolves a completion item. Format and 
> range format indent by braces and leave the text of a multiline string or a 
> block comment unchanged. A typed newline indents the next line. A typed 
> closing brace outdents, except inside a string, a comment, or a slashy regex.
> * *Imports and types.* Organize imports keeps star, static, and alias 
> imports, and does not re-insert Groovy's default imports. {{source.fixAll}} 
> only deletes unused imports. Other actions add one import, add every 
> unambiguous missing import in one edit, add a package taken from the file 
> path, and replace the {{def}} immediately before a field or local name with 
> an inferred type.
> * *Generate.* Implement abstract methods by inserting an {{@Override}} stub 
> that throws {{UnsupportedOperationException}}. Add {{@Override}} on a method 
> that already overrides. Drop the {{private}} modifier on a field that has no 
> accessor, so Groovy treats the field as a property. Insert 
> {{@groovy.transform.ToString}}, {{@groovy.transform.EqualsAndHashCode}}, or 
> {{@groovy.transform.TupleConstructor}}. Those three actions insert the 
> annotation only. They do not paste a method body. {{@ToString}} is skipped 
> when that annotation, {{@Canonical}}, or {{toString}} is already present. 
> {{@EqualsAndHashCode}} is skipped when that annotation, {{@Canonical}}, 
> {{equals}}, or {{hashCode}} is already present. {{@TupleConstructor}} is 
> skipped when that annotation, {{@Canonical}}, {{@MapConstructor}}, or a 
> declared constructor is already present, and when the class has no instance 
> field.
> * *Create class.* For an unresolved type, offer a sibling {{Name.groovy}} 
> next to the referencing file, using that file's package. A qualified name is 
> accepted only when its package is the same. The action is skipped when that 
> type is already defined, when the sibling is already open or on disk, or when 
> the client did not advertise file creation ({{documentChanges}} plus the 
> create resource operation). The stub is written only in that new file. The 
> create neither overwrites nor ignores an existing file.
> * *Calls.* At a call site, complete a parameter name as a named-argument 
> prefix when the call is bound or has one arity match. {{refactor.rewrite}} 
> converts such a positional call to named arguments.
> * *Navigation.* Definition, type definition, implementation, declaration, and 
> references. References match the declaration by owner, name, and descriptor, 
> not by 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 for the whole file or a range. Inlay hints for 
> declaration types and for parameter names. A parameter-name inlay is labelled 
> inferred unless the compiler bound the call, and an inferred inlay does not 
> insert text. Code lenses 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}}, the nearest overridden method that has 
> source. It 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.
> 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 can cross that boundary, and javac 
> diagnostics are published with the Groovy ones. javac writes class files to a 
> private temporary directory whose name starts with {{groovy-lsp-javac-}}, not 
> under the user home directory. On POSIX the directory is owner-only. It is 
> removed on the next compile and when the compiler closes. If that directory 
> cannot be created, the compile continues with Groovy only.
> 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 
> groovy-language-server-edt, and its identifier-scan rename is not used.
> ||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 definition from Groovy into 
> Java|groovy-language-server-edt also completes, formats, and renames Java|
> |GDSL and dependency download|Not included|groovyls adds Jenkins GDSL and 
> dependency download|
> |Unbound-call rename|Refused|groovy-language-server-edt can rename by 
> scanning the identifier text|
> 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. A relative path is resolved from a workspace 
> folder|
> |grapeEnabled|Allow {{@Grab}} while compiling. Default is off|
> |astTestEnabled|Allow {{@ASTTest}} while compiling. Default is off|
> Any other key under {{groovy}} is stored as text. The server does not 
> interpret it and does not download anything for it. Changing such a key 
> builds a new class loader and recompiles.
> An empty source-path list and an empty classpath are filled separately, and 
> only when the client left that list empty. Source roots are every existing 
> directory among {{src/main/groovy}}, {{src/test/groovy}}, {{src/main/java}}, 
> and {{src/test/java}}. If none of those four exists, the server uses {{src}} 
> when that directory exists, and otherwise the workspace folder itself. The 
> classpath gains jars that sit directly under {{lib}} or {{libs}}.
> Diagnostics for one file stay on that file. Unchanged buffers are not 
> compiled again. {{@Grab}} stays off unless the client turns it on, both by 
> omitting its global transform and by the process property 
> {{groovy.grape.enable}}. {{@ASTTest}} is a local transform, so it is turned 
> off only by {{groovy.asttest.enable}}. Both properties are process-wide for 
> the duration of a compile, then restored. One compile holds them so another 
> compile cannot restore them early.
> 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.
> * Wiring Groovy Console or groovysh.
> 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. Clients keep sending positions as they do today.
> h2. Running
> {code}
> groovylsp
> groovylsp --stdio
> groovylsp --socket PORT
> groovylsp --help
> groovylsp --version
> {code}
> An editor starts that process and speaks JSON-RPC on its standard input and 
> output. After shutdown, {{exit}} ends the process with code 0. {{exit}} 
> without a preceding shutdown ends it with code 1.



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

Reply via email to