dense-analysis / ale

Check syntax in Vim/Neovim asynchronously and fix files, with Language Server Protocol (LSP) support
BSD 2-Clause "Simplified" License
13.56k stars 1.44k forks source link

AleGoToDefinition does not support urls with `jar:file` scheme #4855

Open ahakanbaba opened 1 week ago

ahakanbaba commented 1 week ago

Information

VIM version

VIM - Vi IMproved 9.1 (2024 Jan 02, compiled Oct 22 2024 20:01:46) macOS version - arm64

Operating System:

Mac OS Sequoia 15.0.1 (24A348)

What went wrong

I am NOT a Java expert and I am trying to setup Java development in vim. I set up javalsp via Ale.

Completed the setup instructions for java-language-server and put together a very very simple java project. java-tutorial-main.zip Adding the zip file of the java project in the attachment.

Then I try to jump to the definition of a class that is in an external dependency, ALE cannot process the uri in the language-server's response.

For example in the code ( Word.java from the java-tutorial-main.zip file)

package com.ahakanbaba.java_tutorial;

import lombok.Data;

@Data
public class Word {
  private String value;

  public Word(String value) {
    this.value = value;
  }
}

When I do :ALEGoToDefinition on lombok.Data, the java-language-server request-response looks like this

{"method":"textDocument/definition","jsonrpc":"2.0","id":6,"params":{"textDocument":{"uri":"file:///Users/hakanbaba/src/ahakanbaba/java-tutorial/src/main/java/com/ahakanbaba/java_tutorial/Word.java"},"position":{"character":15,"line":3}}}Content-Length: 368

{"jsonrpc":"2.0","id":6,"result":[{"uri":"jar:file:///Users/hakanbaba/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.34/861d5074b9a04a7f1c1e128584a66b2b815fc3d4/lombok-1.18.34-sources.jar!/lombok/Data.java","range":{"start":{"line":46,"character":18},"end":{"line":46,"character":22}}}]}Content-Length: 331

The location in the language-server's response looks correct to me.

jar:file:///Users/hakanbaba/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.34/861d5074b9a04a7f1c1e128584a66b2b815fc3d4/lombok-1.18.34-sources.jar!/lombok/Data.java

That is the jar file from the gradle cache. When I extract the tar file and find the lombok/Data.java, the contents looks correct to me.

The LSP defintion.vim handler in Ale cannot handle this response.

The result here looks like this

l:result[{'uri': 'jar:file:///Users/hakanbaba/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.34/861d5074b9a04a7f1c1e128584a66b2b815fc3d4/lombok-1.18.34-sources.jar!/lombok/Data.java', 'range': {'end': {'character': 22, 'line': 46}, 'start': {'character': 18, 'line': 46}}}]

Then the item_list here looks like this

l:item_list[{'filename': 'jar:file:///Users/hakanbaba/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.34/861d5074b9a04a7f1c1e128584a66b2b815fc3d4/lombok-1.18.34-sources.jar!/lombok/Data.java', 'col
umn': 19, 'line': 47}]

Then through ALE, vim tries to open this file "jar:file:///Users/hakanbaba/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.34/861d5074b9a04a7f1c1e128584a66b2b815fc3d4/lombok-1.18.34-sources.jar!/lombok/Data.java" [New DIRECTORY]

Instead of finding the file lombok/Data.java file inside the given jar archive.

Reproducing the bug

  1. Install a Java-Runtime
  2. Unzip the java-tutorial-main.zip.
  3. Run ./gradlew build idea at the project root directory
  4. Navigate to Word.java.
  5. Call :ALEGoToDefinition at the lombok.Data import.

:ALEInfo


 Current Filetype: java
Available Linters: ['checkstyle', 'cspell', 'eclipselsp', 'javac', 'javalsp', 'pmd']
   Linter Aliases:
'javalsp' -> ['java_language_server']
  Enabled Linters: ['javalsp']
  Ignored Linters: []
 Suggested Fixers:
  'clang-format' - Fix C, C++, C#, CUDA, Java, JavaScript, JSON, ObjectiveC and Protobuf files with clang-format.
  'google_java_format' - Fix Java files with google-java-format.
  'remove_trailing_lines' - Remove all blank lines at the end of a file.
  'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.
  'uncrustify' - Fix C, C++, C#, ObjectiveC, ObjectiveC++, D, Java, Pawn, and VALA files with uncrustify.

 Linter Variables:
let g:ale_java_javalsp_config = {'java': {'externalDependencies': ['org.projectlombok:lombok:1.18.34', 'junit:junit:4.13.2'], 'classPath': []}}
let g:ale_java_javalsp_executable = 'java-language-server'

 Global Variables:
let g:ale_cache_executable_check_failures = v:null
let g:ale_change_sign_column_color = 0
let g:ale_command_wrapper = ''
let g:ale_completion_delay = v:null
let g:ale_completion_enabled = 0
let g:ale_completion_max_suggestions = v:null
let g:ale_disable_lsp = 'auto'
let g:ale_echo_cursor = 1
let g:ale_echo_msg_error_str = 'Error'
let g:ale_echo_msg_format = '%code: %%s'
let g:ale_echo_msg_info_str = 'Info'
let g:ale_echo_msg_warning_str = 'Warning'
let g:ale_enabled = 1
let g:ale_fix_on_save = 1
let g:ale_fixers = {'*': ['remove_trailing_lines', 'trim_whitespace']}
let b:ale_fixers = ['google_java_format']
let g:ale_history_enabled = 1
let g:ale_info_default_mode = 'preview'
let g:ale_history_log_output = 1
let g:ale_keep_list_window_open = 0
let g:ale_lint_delay = 200
let g:ale_lint_on_enter = 1
let g:ale_lint_on_filetype_changed = 1
let g:ale_lint_on_insert_leave = 1
let g:ale_lint_on_save = 1
let g:ale_lint_on_text_changed = 'never'
let g:ale_linter_aliases = {}
let g:ale_linters = {}
let b:ale_linters = ['javalsp']
let g:ale_linters_explicit = 0
let g:ale_linters_ignore = {}
let g:ale_list_vertical = 0
let g:ale_list_window_size = 10
let g:ale_loclist_msg_format = '%code: %%s'
let g:ale_max_buffer_history_size = 20
let g:ale_max_signs = -1
let g:ale_maximum_file_size = v:null
let g:ale_open_list = 0
let g:ale_pattern_options = v:null
let g:ale_pattern_options_enabled = v:null
let g:ale_root = {}
let g:ale_set_balloons = 0
let g:ale_set_highlights = 0
let g:ale_set_loclist = 1
let g:ale_set_quickfix = 0
let g:ale_set_signs = 1
let g:ale_sign_column_always = 0
let g:ale_sign_error = 'E'
let g:ale_sign_info = 'I'
let g:ale_sign_offset = 1000000
let g:ale_sign_style_error = 'E'
let g:ale_sign_style_warning = 'W'
let g:ale_sign_warning = 'W'
let g:ale_sign_highlight_linenrs = 0
let g:ale_type_map = {}
let g:ale_use_neovim_diagnostics_api = 0
let g:ale_use_global_executables = v:null
let g:ale_virtualtext_cursor = 'all'
let g:ale_warn_about_trailing_blank_lines = 1
let g:ale_warn_about_trailing_whitespace = 1

  Command History:

(started) ['/bin/bash', '-c', '''java-language-server''']

The java-language-server executable is merely this

#!/bin/bash
pid=$$
tee /Users/hakanbaba/misc/java-language-server_in_${pid}.log | /Users/hakanbaba/src/georgewfraser/java-language-server/dist/lang_server_mac.sh | tee /Users/hakanbaba/misc/java-language-server_out_${pid}.log
ahakanbaba commented 1 week ago

I am quite interested in that codepath. If a maintainer could give some guidance, I am more than happy to send a PR.

I have followed the call stack to the following extend

ale#definition#FormatLSPResponse ale#util#ToResource ale#uri#GetURIHandler

And the GetURIHandler looks like the place to add the specialization here.

For example

let s:uri_handlers = {
\   'jdt': {
\       'OpenURILink': function('ale#uri#jdt#OpenJDTLink'),
\   }
\}

function! ale#uri#GetURIHandler(uri) abort
    for l:scheme in keys(s:uri_handlers)
        if a:uri =~# '^'.l:scheme.'://'
            return s:uri_handlers[scheme]
        endif
    endfor

    return v:null
endfunction

https://github.com/dense-analysis/ale/blame/4fca3824cc34f731cb5b3e51844698052c5f6c52/autoload/ale/uri.vim#L29-L43

There is special handling with jdt:// schemes. Maybe that is the place to extend for this new jar:file// scheme.