Ich habe einen LSP und habe versucht, eine Umgebung zum Schreiben von Java mit Vim (NeoVim) zu erstellen, aber ich konnte die IDE nicht übertreffen ...

Ich glaube, es war vor ungefähr einem Jahr, aber ich habe eclim verwendet, um eine Java-Entwicklungsumgebung mit NeoVim zu erstellen.

Dieses Eclim ist sehr leistungsfähig, da es Eclipse im Hintergrund startet und eine Java-Entwicklungsumgebung bereitstellt. Es erfordert jedoch einen Arbeitsbereich wie Eclipse, und Eclipse wird im Hintergrund gestartet, sodass es schwer ist, obwohl es sich um Vim handelt Es gab viele schmerzhafte Teile, wie zum Beispiel nervig und schwer zu automatisieren, also habe ich sie fast nutzlos gelöscht.

Immerhin habe ich beim Schreiben von Java die IDE verwendet, aber kürzlich gab es einen Java-LSP namens eclipse.jdt.ls. ich fand

Für mich während der Kampagne, die Entwicklungsumgebung durch LSP zu ersetzen

"Es sieht aus wie das offizielle Programm von Eclipse, und es scheint, dass die Umgebungskonstruktion automatisiert werden kann, und dies hat gewonnen (weißes Chi)."

Ich habe versucht, eine Umgebung mit einem ähnlichen Gefühl zu schaffen.

Immerhin konnte ich die IDE nicht schlagen, aber ich war damit zufrieden, also werde ich sie vorstellen.

Ich verwende NeoVim, sollte aber auf die gleiche Weise eine Umgebung mit einem normalen Vim erstellen können.

Erstens ... Was ist LSP?

LSP ist eine Abkürzung für "Language Server Protocel", eine Spezifikation, die von Microsoft im Juni 2016 veröffentlicht wurde.

Hier geht es darum, dass allgemeine Spezifikationen für die Bereitstellung von Funktionen wie Code-Vervollständigung und Fehleranalyse definiert werden, die für die IDE als Dienste erforderlich sind.

Durch die Standardisierung der Spezifikationen auf diese Weise kann die IDE-Funktion in jeder Umgebung verwendet werden, sofern eine Implementierung der LSP-Sprache vorhanden ist und der verwendete Editor über einen LSP-Client verfügt.

LSP wird in diesem Artikel ausführlich beschrieben und die Spezifikationen werden auf der offiziellen Website und auf GitHub veröffentlicht. Wenn Sie also interessiert sind, schauen Sie bitte.

Darüber hinaus sind die Implementierung für jede Sprache und der Client für jeden Editor unten zusammengefasst.

In dieser Umgebungskonstruktion habe ich versucht, eine Java-Entwicklungsumgebung mit der Java-Implementierung dieses LSP "eclipse.jdt.ls" und dem LSP-Client "LanguageClient-neovim" von NeoVim zu erstellen.

Hier sind einige der coolsten Tools, die ich dieses Mal verwendet habe!

dein.vim Derjenige, der diese Person nicht kennt, soll Moguri (Selbstprüfung) sein. Ein Plug-in-Management-Tool, das von Mr. Shougo, auch bekannt als Dark Minou, entwickelt wurde. Es wird an verschiedenen Stellen eingeführt und die Erklärung wird weggelassen.

Einzelheiten entnehmen Sie bitte hier.

deoplete.nvim Ein ebenfalls von Shougo entwickeltes Plug-In zur Code-Vervollständigung. Ich muss jetzt auch nicht darüber reden. (geeignet)

Ich werde die Details in einem anderen Artikel werfen.

eclipse.jdt.ls Java-Implementierung von LSP oben erwähnt. Die Hauptrolle dieser Zeit, Teil 1. Wenn NeoVim gestartet wird, wird es automatisch gestartet. Durch den Austausch von Nachrichten mit LanguageClient-neovim, der später beschrieben wird, ist es ein hasserfüllter Typ, der den Wind der IDE in NeoVim bläst.

Die Startgeschwindigkeit und die Speichernutzung sind viel besser als bei eclim, und die Installation ist vorerst einfach zu automatisieren.

LanguageClient-neovim NeoVim-Client von LSP oben erwähnt. Die Hauptrolle dieser Zeit, Teil 2.

Code-Vervollständigung, Code-Format, Syntaxprüfung, Dokumentanzeige, Definitionsquellensprung usw., die das für die Codierung erforderliche Minimum zu sein scheint, können durchgeführt werden, indem dieser Typ und LSP für jede Sprache, den besten Tintenfisch-Typ, vorbereitet werden ..

In meinem Fall verwende ich keine Syntaxprüfung und kein Codeformat, da ich es einem anderen Plug-In überlasse.

Es gibt auch vim-lsp, das von einem MS-Mitarbeiter entwickelt wurde (ich glaube, ich habe es irgendwo gehört), aber es unterstützt deoplete. Ich benutze das. Die meisten Stars auf GitHub sind Language Client-neovim.

Übrigens sagt der Name "neovim", aber es scheint, dass es mit gewöhnlichen vim verwendet werden kann. Ich habe es nicht versucht.

ale.vim Ein Plug-In, das während der Codierung Syntaxprüfungen asynchron durchführt.

** Bild Bild ** ale.vim

LanguageClient-neovim hat eine ähnliche Funktion, aber ich verwende dieses Plug-In zum Zwecke der Vereinheitlichung, da ich Sprachen verwende, die LSP nicht unterstützen.

Sie können das Prüftool auch nach Ihren Wünschen anpassen.

Im Fall von Java scheint es, dass der Standard "javac" und "google-java-format (später beschrieben)" [^ 1] verwendet, um die Syntaxprüfung durchzuführen. [^ 1]: Die Prüfung mit dem Google-Java-Format wird nur ausgeführt, wenn das Tool installiert ist.

vim-autoformat Ein Plug-In, mit dem Sie ein Formatierungswerkzeug für die Codeformatierung angeben können. Einige Standardformatierer werden abhängig vom Dateityp festgelegt und ausgeführt, sofern der Formatierer nicht angegeben ist.

Es gibt eine ähnliche Funktion in ale.vim, aber ich benutze dieses Plug-In schon lange und es wird immer noch verwendet.

Stellen Sie den Code beim Speichern so ein, dass er mit dem später beschriebenen "Google-Java-Format" formatiert wird.

google-java-format Ein CLI-Tool, das Code gemäß [Google Java Style] formatieren kann (https://google.github.io/styleguide/javaguide.html).

Standardmäßig ist es mit einem Einzug mit zwei Leerzeichen formatiert, mit dem viele Java-Onkel möglicherweise nicht vertraut sind. Seien Sie versichert, dass Sie einen 4-Leerzeichen-Einzug erstellen können, indem Sie die Option "--aosp" (Android Open Source Project) angeben.

Einstellungen dafür ... und Automatisierung dafür ...?

Also die Erklärung der Plug-In-Einstellungen.

Die Einstellungen für dein.vim und deoplete.nvim werden weggelassen, da sie meiner Meinung nach nicht viel mit dieser Zeit zu tun haben.

Die Verzeichnisstruktur sieht übrigens so aus.

$XDG_CONFIG_HOME/nvim
  ├── autoload
  │   └── hook
  │       ├── add
  │       │   ├── ale.vim
  │       │   ├── language_client_neovim.vim
  │       │   └── vim_autoformat.vim
  │       ├── post_update
  │       │   ├── ale.vim
  │       │   ├── language_client_neovim.vim
  │       │   └── vim_autoformat.vim
  │       └── source
  │           └── deoplete.vim
  ├── dein
  │   ├── dein.toml
  │   └── dein_lazy.toml
  └── init.vim

LanguageClient-Einstellungen um neovim

Zuallererst ist es aus der Einstellung des Hauptfeatures LanguageClient-neovim. Es ist in dein.toml wie folgt definiert.

dein/dein.toml


[[plugins]]
repo             = 'autozimu/LanguageClient-neovim'
rev              = 'next'
#Rückruf beim Aktualisieren eines Plug-Ins
hook_post_update = 'call hook#post_update#language_client_neovim#load()'
#Rückruf, der aufgerufen wird, wenn das Plug-In geladen wird
hook_add         = 'call hook#add#language_client_neovim#load()'

Zwei Funktionen werden zum Zeitpunkt der Aktualisierung und zum Zeitpunkt des Ladens aufgerufen, um einzustellen.

Beim Aktualisieren eines Plug-Ins wird festgestellt, ob "eclipse.jdt.ls" installiert ist. Wenn es nicht installiert ist, wird der Installationsvorgang gestartet.

autoload/hook/post_update/language_client_neovim.vim


function! hook#post_update#language_client_neovim#load() abort
  !./install.sh
  " g:outher_package_Weg ist`eclipse.jdt.ls`Das Verzeichnis, in dem externe Tools wie installiert sind.
  "Obwohl weggelassen,`init.vim`Es ist in gesetzt.
  let l:jdt_lsp_path = expand(g:outher_package_path) . "/jdt-lsp"
  "Im angegebenen Verzeichnis`eclipse.jdt.ls`Überprüfen Sie, ob vorhanden
  if !executable(l:jdt_lsp_path . "/plugins/org.eclipse.equinox.launcher_1.5.0.v20180207-1446.jar")
    " `eclipse.jdt.ls`Herunterladen
    !curl -o /tmp/tmp_jdt_lsp.tar.gz http://download.eclipse.org/jdtls/snapshots/jdt-language-server-0.16.0-201803280253.tar.gz
    " `eclipse.jdt.ls`Erstellen Sie ein Zielverzeichnis für
    call mkdir(l:jdt_lsp_path, "p")
    "Entpacken Sie die heruntergeladene Datei in das Speicherverzeichnis
    execute "!tar xf /tmp/tmp_jdt_lsp.tar.gz -C " . l:jdt_lsp_path
    " tar.Gz-Datei löschen
    !rm /tmp/tmp_jdt_lsp.tar.gz
  endif
endfunction

Als nächstes folgt die Einstellung zum Zeitpunkt des Lesens. Die LSP-Starteinstellungen werden festgelegt und bei jedem Start von NeoVim aufgerufen.

autoload/hook/add/language_client_neovim.vim


function! hook#add#language_client_neovim#load() abort
  let g:LanguageClient_autoStart         = 1 "LSP wird automatisch gestartet, wenn NeoVim gestartet wird
  let g:LanguageClient_diagnosticsEnable = 0 "Deaktivieren Sie die Syntaxprüfung

  let g:LanguageClient_serverCommands = {}
  " `eclipse.jdt.ls`Bestätigung des Vorhandenseins des in verwendeten Datenspeicherzielverzeichnisses
  "Erstellen Sie ein Verzeichnis, wenn es nicht vorhanden ist
  let l:jdt_lsp_data_dir = expand(g:outher_package_path) . "/jdt-data"
  if !isdirectory(l:jdt_lsp_data_dir)
    call mkdir(l:jdt_lsp_data_dir, "p")
  endif
  "LSP-Starteinstellungen
  " `configuration`Die Optionen müssen für jedes Betriebssystem unterschiedlich eingestellt werden.
  " `eclipse.jdt.ls`Im Installationsverzeichnis`config_linux`, `config_mac`, `config_win`Da ein Verzeichnis aufgerufen wird, geben Sie den Pfad der Einstellungsdatei für jedes Betriebssystem an.
  let g:LanguageClient_serverCommands["java"] = [
        \ 'java',
        \ '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044',
        \ '-Declipse.application=org.eclipse.jdt.ls.core.id1',
        \ '-Dosgi.bundles.defaultStartLevel=4',
        \ '-Declipse.product=org.eclipse.jdt.ls.core.product',
        \ '-Dlog.protocol=true',
        \ '-Dlog.level=ALL',
        \ '-noverify',
        \ '-Xmx1G',
        \ '-jar',
        \ expand(g:outher_package_path) . '/jdt-lsp/plugins/org.eclipse.equinox.launcher_1.5.0.v20180207-1446.jar',
        \ '-configuration',
        \ expand(g:outher_package_path) . '/jdt-lsp/config_mac',
        \ '-data',
        \ l:jdt_lsp_data_dir]

  "Schlüsselzuordnung
  nnoremap <silent> K :call LanguageClient_textDocument_hover()<CR>
  nnoremap <silent> gd :call LanguageClient_textDocument_definition()<CR>
  nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
  nnoremap <silent> <F3> :call LanguageClient_textDocument_references()<CR>
endfunction

ale.vim Für Java verwendet ale.vim die Standardeinstellungen. Da das Symbol zum Zeitpunkt der Syntaxprüfung geändert wird, werde ich es vorerst einführen

dein/dein.toml


[[plugins]]
repo     = 'w0rp/ale'
#Rückruf beim Laden eines Plugins
hook_add = 'call hook#add#ale#load()'

autoload/hook/add/ale.vim


function! hook#add#ale#load() abort
  let g:ale_sign_error      = '✖' "Fehlersymbol
  let g:ale_sign_warning    = '⚠' "Warnsymbol
endfunction

vim-autoformat Ähnlich wie bei LanguageClient-neovim wird der Formatierer zum Zeitpunkt des Updates installiert und das Plug-In zum Zeitpunkt des Ladens festgelegt.

dein/dein.toml


[[plugins]]
repo             = 'Chiel92/vim-autoformat'
#Rückruf beim Laden eines Plugins
hook_add         = 'call hook#add#vim_autoformat#load()'
#Rückruf beim Aktualisieren eines Plug-Ins
hook_post_update = 'call hook#post_update#vim_autoformat#load()'

Der Rückrufprozess zum Zeitpunkt der Aktualisierung sieht folgendermaßen aus

autoload/hook/post_update/vim_autoformat.vim


function! hook#post_update#vim_autoformat#load() abort
  " `google_java_formatter`Überprüfen Sie, ob installiert ist
  let l:google_java_formatter = expand(g:outher_package_path) . "/google-java-format-1.5-all-deps.jar"
  if !executable(l:google_java_formatter)
    "Laden Sie jar herunter, wenn es nicht installiert ist
    execute "!wget https://github.com/google/google-java-format/releases/download/google-java-format-1.5/google-java-format-1.5-all-deps.jar -P " . expand(g:outher_package_path)
  endif
endfunction

Die Einstellungen zum Zeitpunkt des Lesens sind wie folgt. Die Formatierungseinstellungen und das automatische Format beim Speichern werden festgelegt.

autoload/hook/add/vim_autoformat.vim


function! hook#add#vim_autoformat#load() abort
  let g:autoformat_remove_trailing_spaces = 1 "Entfernen von nachgestellten Leerzeichen

  " google_java_Einstellungen für den Formatierungsstartbefehl
  let g:formatdef_google_java_formatter = '"java -jar ' . g:outher_package_path . '/' . g:google_java_formatter . ' - --aosp"'

  "Java-Formatierungseinstellungen
  let g:formatters_java = ['google_java_formatter']

  "Auf automatische Code-Formatierung beim Speichern einstellen
  call s:set_autoformat("java")
endfunction

function! s:set_autoformat(...) abort
  augroup AutoIndentPreWrite
    autocmd!
  augroup End

  for var in a:000
    let l:cmd = 'autocmd AutoIndentPreWrite BufWrite *.' . var . ' :Autoformat'
    execute l:cmd
  endfor
endfunction

Wow, es bewegt sich (kleines Durchschnittsgefühl)

Wenn Sie es für das oben Gesagte einstellen, wird es so funktionieren.

** Code-Vervollständigung und automatische Formatierung **

Auf diese Weise ergänzt der Lambda-Ausdruck auch den Code fest.

** Dokumentreferenz und Definitionsquellensprung **

Ich konnte nicht zu einem Standardpaket oder einer externen Bibliothek springen.

Hmm. Also, was ist der Schmerz?

  1. Kein automatischer Import
  2. Die abstrakte Methode wird nicht automatisch implementiert, wenn die Schnittstelle implementiert wird.
  3. Im ~~ Gradle-Projekt funktioniert es nicht gut. ~~

Hauptsächlich hier. Ich hatte keine Lust auf Go for 1 und 2, also dachte ich, ich könnte nach Java gehen, aber es war unerwartet schmerzhaft.

In Bezug auf ~~ 3 funktionieren im Maven-Projekt die Code-Vervollständigung des externen Pakets und die Dokumentreferenz ordnungsgemäß, sodass die Möglichkeit besteht, dass etwas mit den Einstellungen nicht stimmt ...? ~~ [Addition-It hat im Gradle-Projekt gut funktioniert](Im # Gradle-Projekt hat es gut funktioniert)

Nachtrag

## Im Gradle-Projekt hat es gut funktioniert Für das Gradle-Projekt brauchte ich das "Eclipse Plugin".

build.gradle


plugins {
    id 'java'
    id 'application'
    id 'eclipse'
}

mainClassName = 'App'

dependencies {
    compile 'com.google.guava:guava:23.0'

    testCompile 'junit:junit:4.12'
}

repositories {
    jcenter()
}

Führen Sie nach dem Anwenden des Eclipse-Plugins die Task "eclipseJdt" im Projektstamm aus.

$ gradle eclipseJdt
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

Jetzt können Sie die LSP-Funktion im Gradle-Projekt verwenden.

Zusammenfassung

Deshalb konnte ich die IDE nicht schlagen ... Es ist jedoch einfacher, den Code zu bearbeiten als die IDE, und die Code-Vervollständigung ist auch sehr gut, so dass es unwahrscheinlich ist, dass Sie ihn löschen, ohne ihn wie eclim zu verwenden.

Selbst wenn Sie der Meinung sind, dass es momentan schwierig ist, ist es möglicherweise einfacher, sich daran zu gewöhnen, und vielleicht gibt es ein nützliches Tool, nur weil Sie es nicht kennen. Deshalb werde ich die Umgebung auch in meiner Freizeit noch einmal überprüfen.

Referenzseite

Recommended Posts

Ich habe einen LSP und habe versucht, eine Umgebung zum Schreiben von Java mit Vim (NeoVim) zu erstellen, aber ich konnte die IDE nicht übertreffen ...
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
[Java] Ich habe JDBC installiert und versucht, eine Verbindung mit Servlet + MySQL herzustellen. (Es gibt eine Version mit DAO / Bean)
Ich habe mit Vagrant eine CentOS 8-Umgebung erstellt und versucht, den Ordner zu synchronisieren, aber ich habe einen Fehler erhalten, also habe ich ihn behoben.
Ich habe versucht, mit Java und Spring eine Funktion / einen Bildschirm für den Administrator einer Einkaufsseite zu erstellen
Ich habe versucht, das Problem mit der Ruby-Karaoke-Maschine zu lösen (es gibt ein Beispiel für die Antwort).
Ich habe versucht, das Problem mit dem Ruby-Bonusgetränk zu lösen (es gibt ein Beispiel für die Antwort).
[Rails 6.0, Docker] Ich habe versucht, die Konstruktion der Docker-Umgebung und die zum Erstellen eines Portfolios erforderlichen Befehle zusammenzufassen
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen
Was benötigen Sie am Ende, um eine Web-App mit Java zu erstellen? Erklären Sie den Mechanismus und was zum Lernen notwendig ist
Ich habe versucht, mit Docker eine Padrino-Entwicklungsumgebung zu erstellen
Ich habe versucht, das Problem bei der Erstellung von Ruby-Bingokarten zu lösen (es gibt ein Beispiel für die Antwort).
Nachdem ich Progate gelernt hatte, versuchte ich, eine SNS-Anwendung mit Rails in der lokalen Umgebung zu erstellen
Ich habe versucht, mit Docker eine Plant UML Server-Umgebung zu erstellen
Ich habe versucht, mit Eclipse + Tomcat eine http2-Entwicklungsumgebung zu erstellen
Ich habe versucht, eine Android-Anwendung mit MVC zu erstellen (Java)
Ich habe versucht, die Methoden von Java String und StringBuilder zusammenzufassen
Ich habe versucht, die letzten 10 Fragen zu lösen, die nach der Registrierung bei AtCoder in Java gelöst werden sollten
Ich habe versucht, mit Java zu interagieren
[Einführung in Java] Ich habe versucht, das Wissen zusammenzufassen, das ich für wesentlich halte
01. Ich habe versucht, eine Umgebung mit SpringBoot + IntelliJ + MySQL (MyBatis) (Windows 10) zu erstellen.
Ich habe versucht, die Geschwindigkeit von Graal VM mit JMH zu messen und zu vergleichen
Immerhin wollte ich den Inhalt von MySQL mit Docker in der Vorschau anzeigen ...
Nachdem ich das Montyhall-Problem mit Ruby überprüft hatte, war es eine Geschichte, die ich gut verstehen konnte und die ich nicht gut verstand
Ich habe versucht, mit der Java Stream-API eine Methode zu erstellen, die mehrere Filter gleichzeitig anwendet. Ist das in Ordnung?
Ich habe ein Programm erstellt, das aus dem mit Java überladenen Prozess nach der Zielklasse sucht