feat(zig,lsp)!: Inlay hints
This commit is contained in:
parent
c1989f0b0b
commit
0947fe5b0f
10 changed files with 219 additions and 9 deletions
|
@ -18,6 +18,11 @@ Changelog structure reference:
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
#### Zig/LSP
|
||||||
|
- Inlay hints
|
||||||
|
|
||||||
## [0.6.0]
|
## [0.6.0]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -13,6 +13,7 @@ Go to `Settings` -> `Languages & Frameworks` -> `Zig` -> `ZLS path` -> select yo
|
||||||
- Code completion
|
- Code completion
|
||||||
- Code folding
|
- Code folding
|
||||||
- Syntax highlighting
|
- Syntax highlighting
|
||||||
|
- Inlay hints
|
||||||
- Basic error diagnostics
|
- Basic error diagnostics
|
||||||
- Go to definition
|
- Go to definition
|
||||||
- Rename symbol
|
- Rename symbol
|
||||||
|
|
|
@ -57,6 +57,8 @@ import org.eclipse.lsp4j.ImplementationParams;
|
||||||
import org.eclipse.lsp4j.InitializeParams;
|
import org.eclipse.lsp4j.InitializeParams;
|
||||||
import org.eclipse.lsp4j.InitializeResult;
|
import org.eclipse.lsp4j.InitializeResult;
|
||||||
import org.eclipse.lsp4j.InitializedParams;
|
import org.eclipse.lsp4j.InitializedParams;
|
||||||
|
import org.eclipse.lsp4j.InlayHint;
|
||||||
|
import org.eclipse.lsp4j.InlayHintParams;
|
||||||
import org.eclipse.lsp4j.Location;
|
import org.eclipse.lsp4j.Location;
|
||||||
import org.eclipse.lsp4j.LocationLink;
|
import org.eclipse.lsp4j.LocationLink;
|
||||||
import org.eclipse.lsp4j.MessageActionItem;
|
import org.eclipse.lsp4j.MessageActionItem;
|
||||||
|
@ -676,6 +678,20 @@ public class DefaultRequestManager implements RequestManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<List<InlayHint>> inlayHint(InlayHintParams params) {
|
||||||
|
if (checkStatus()) {
|
||||||
|
try {
|
||||||
|
return (getServerCapabilities().getInlayHintProvider() != null)
|
||||||
|
? getTextDocumentService().inlayHint(params) : null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
crashed(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<List<FoldingRange>> foldingRange(FoldingRangeRequestParams params) {
|
public CompletableFuture<List<FoldingRange>> foldingRange(FoldingRangeRequestParams params) {
|
||||||
if (checkStatus()) {
|
if (checkStatus()) {
|
||||||
|
|
|
@ -69,6 +69,7 @@ import org.eclipse.lsp4j.HoverCapabilities;
|
||||||
import org.eclipse.lsp4j.InitializeParams;
|
import org.eclipse.lsp4j.InitializeParams;
|
||||||
import org.eclipse.lsp4j.InitializeResult;
|
import org.eclipse.lsp4j.InitializeResult;
|
||||||
import org.eclipse.lsp4j.InitializedParams;
|
import org.eclipse.lsp4j.InitializedParams;
|
||||||
|
import org.eclipse.lsp4j.InlayHintCapabilities;
|
||||||
import org.eclipse.lsp4j.OnTypeFormattingCapabilities;
|
import org.eclipse.lsp4j.OnTypeFormattingCapabilities;
|
||||||
import org.eclipse.lsp4j.RangeFormattingCapabilities;
|
import org.eclipse.lsp4j.RangeFormattingCapabilities;
|
||||||
import org.eclipse.lsp4j.ReferencesCapabilities;
|
import org.eclipse.lsp4j.ReferencesCapabilities;
|
||||||
|
@ -578,6 +579,7 @@ public class LanguageServerWrapper {
|
||||||
textDocumentClientCapabilities.setDocumentHighlight(new DocumentHighlightCapabilities());
|
textDocumentClientCapabilities.setDocumentHighlight(new DocumentHighlightCapabilities());
|
||||||
textDocumentClientCapabilities.setFormatting(new FormattingCapabilities());
|
textDocumentClientCapabilities.setFormatting(new FormattingCapabilities());
|
||||||
textDocumentClientCapabilities.setHover(new HoverCapabilities());
|
textDocumentClientCapabilities.setHover(new HoverCapabilities());
|
||||||
|
textDocumentClientCapabilities.setInlayHint(new InlayHintCapabilities());
|
||||||
textDocumentClientCapabilities.setOnTypeFormatting(new OnTypeFormattingCapabilities());
|
textDocumentClientCapabilities.setOnTypeFormatting(new OnTypeFormattingCapabilities());
|
||||||
textDocumentClientCapabilities.setRangeFormatting(new RangeFormattingCapabilities());
|
textDocumentClientCapabilities.setRangeFormatting(new RangeFormattingCapabilities());
|
||||||
textDocumentClientCapabilities.setReferences(new ReferencesCapabilities());
|
textDocumentClientCapabilities.setReferences(new ReferencesCapabilities());
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 FalsePattern
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.falsepattern.zigbrains.lsp.contributors;
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.lsp.editor.EditorEventManagerBase;
|
||||||
|
import com.falsepattern.zigbrains.lsp.utils.DocumentUtils;
|
||||||
|
import com.falsepattern.zigbrains.lsp.utils.FileUtils;
|
||||||
|
import com.intellij.codeInsight.hints.declarative.InlayHintsCollector;
|
||||||
|
import com.intellij.codeInsight.hints.declarative.InlayHintsProvider;
|
||||||
|
import com.intellij.codeInsight.hints.declarative.InlayTreeSink;
|
||||||
|
import com.intellij.codeInsight.hints.declarative.InlineInlayPosition;
|
||||||
|
import com.intellij.codeInsight.hints.declarative.OwnBypassCollector;
|
||||||
|
import com.intellij.codeInsight.hints.declarative.impl.DeclarativeInlayHintsPassFactory;
|
||||||
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
import com.intellij.psi.PsiFile;
|
||||||
|
import com.vladsch.flexmark.html.HtmlRenderer;
|
||||||
|
import com.vladsch.flexmark.parser.Parser;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class LSPInlayHintProvider implements InlayHintsProvider {
|
||||||
|
protected static Logger LOG = Logger.getInstance(LSPInlayHintProvider.class);
|
||||||
|
private static final LSPInlayHintsCollector DEFAULT_COLLECTOR = new LSPInlayHintsCollector();
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public InlayHintsCollector createCollector(@NotNull PsiFile psiFile, @NotNull Editor editor) {
|
||||||
|
if (FileUtils.isFileSupported(psiFile.getVirtualFile())) {
|
||||||
|
return getCollector();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LSPInlayHintsCollector getCollector() {
|
||||||
|
return DEFAULT_COLLECTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LSPInlayHintsCollector implements OwnBypassCollector {
|
||||||
|
@Override
|
||||||
|
public void collectHintsForFile(@NotNull PsiFile psiFile, @NotNull InlayTreeSink inlayTreeSink) {
|
||||||
|
var editor = FileUtils.editorFromPsiFile(psiFile);
|
||||||
|
if (editor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var manager = EditorEventManagerBase.forEditor(editor);
|
||||||
|
if (manager == null || manager.editor != editor) {
|
||||||
|
EditorEventManagerBase.runWhenManagerGetsRegistered(editor,
|
||||||
|
() -> {
|
||||||
|
if (editor.isDisposed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var project = editor.getProject();
|
||||||
|
if (project == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DeclarativeInlayHintsPassFactory.Companion.scheduleRecompute(editor, project);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var res = manager.inlayHint();
|
||||||
|
if (res == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var hint: res) {
|
||||||
|
var pos = DocumentUtils.LSPPosToOffset(editor, hint.getPosition());
|
||||||
|
var inlayPos = new InlineInlayPosition(pos, false, 0);
|
||||||
|
var tt = hint.getTooltip();
|
||||||
|
String tooltipText;
|
||||||
|
if (tt.isLeft()) {
|
||||||
|
tooltipText = tt.getLeft();
|
||||||
|
} else {
|
||||||
|
var markup = tt.getRight();
|
||||||
|
tooltipText = switch (markup.getKind()) {
|
||||||
|
case "markdown" -> {
|
||||||
|
var markedContent = markup.getValue();
|
||||||
|
if (markedContent.isEmpty()) {
|
||||||
|
yield "";
|
||||||
|
}
|
||||||
|
Parser parser = Parser.builder().build();
|
||||||
|
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
||||||
|
yield "<html>" + renderer.render(parser.parse(markedContent)) + "</html>";
|
||||||
|
}
|
||||||
|
default -> markup.getValue();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
inlayTreeSink.addPresentation(inlayPos, Collections.emptyList(), tooltipText, true, (builder) -> {
|
||||||
|
var label = hint.getLabel();
|
||||||
|
StringBuilder text = new StringBuilder();
|
||||||
|
if (label.isLeft()) {
|
||||||
|
text.append(label.getLeft());
|
||||||
|
} else if (label.isRight()) {
|
||||||
|
var parts = label.getRight();
|
||||||
|
for (var part: parts) {
|
||||||
|
text.append(part.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (text.length() == 0) {
|
||||||
|
text.append(" ");
|
||||||
|
}
|
||||||
|
builder.text(text.toString(), null);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ import com.falsepattern.zigbrains.lsp.requests.HoverHandler;
|
||||||
import com.falsepattern.zigbrains.lsp.requests.Timeout;
|
import com.falsepattern.zigbrains.lsp.requests.Timeout;
|
||||||
import com.falsepattern.zigbrains.lsp.requests.Timeouts;
|
import com.falsepattern.zigbrains.lsp.requests.Timeouts;
|
||||||
import com.falsepattern.zigbrains.lsp.requests.WorkspaceEditHandler;
|
import com.falsepattern.zigbrains.lsp.requests.WorkspaceEditHandler;
|
||||||
|
import com.falsepattern.zigbrains.lsp.utils.ApplicationUtils;
|
||||||
import com.intellij.codeInsight.completion.InsertionContext;
|
import com.intellij.codeInsight.completion.InsertionContext;
|
||||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||||
import com.intellij.codeInsight.hint.HintManager;
|
import com.intellij.codeInsight.hint.HintManager;
|
||||||
|
@ -1307,6 +1308,32 @@ public class EditorEventManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<InlayHint> inlayHint() {
|
||||||
|
var range = ApplicationUtils.computableReadAction(() -> {
|
||||||
|
var start = DocumentUtils.offsetToLSPPos(editor, 0);
|
||||||
|
var end = DocumentUtils.offsetToLSPPos(editor, editor.getDocument().getTextLength());
|
||||||
|
return new Range(start, end);
|
||||||
|
});
|
||||||
|
var promise = getRequestManager().inlayHint(new InlayHintParams(FileUtils.editorToLSPIdentifier(editor), range));
|
||||||
|
if (promise == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var res = promise.get(Timeout.getTimeout(Timeouts.INLAY_HINTS), TimeUnit.MILLISECONDS);
|
||||||
|
wrapper.notifySuccess(Timeouts.INLAY_HINTS);
|
||||||
|
if (res != null) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
LOG.warn(e);
|
||||||
|
wrapper.notifyFailure(Timeouts.CODEACTION);
|
||||||
|
} catch (InterruptedException | JsonRpcException | ExecutionException e) {
|
||||||
|
LOG.warn(e);
|
||||||
|
wrapper.crashed(e);
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the server supports willSaveWaitUntil, the LSPVetoer will check if a save is needed
|
* If the server supports willSaveWaitUntil, the LSPVetoer will check if a save is needed
|
||||||
* (needSave will basically alternate between true or false, so the document will always be saved)
|
* (needSave will basically alternate between true or false, so the document will always be saved)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.falsepattern.zigbrains.lsp.editor;
|
package com.falsepattern.zigbrains.lsp.editor;
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.lsp.utils.ApplicationUtils;
|
||||||
import com.intellij.openapi.editor.Editor;
|
import com.intellij.openapi.editor.Editor;
|
||||||
import org.eclipse.lsp4j.Diagnostic;
|
import org.eclipse.lsp4j.Diagnostic;
|
||||||
import com.falsepattern.zigbrains.lsp.utils.FileUtils;
|
import com.falsepattern.zigbrains.lsp.utils.FileUtils;
|
||||||
|
@ -22,11 +23,13 @@ import com.falsepattern.zigbrains.lsp.utils.OSUtils;
|
||||||
|
|
||||||
import java.awt.KeyboardFocusManager;
|
import java.awt.KeyboardFocusManager;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class EditorEventManagerBase {
|
public class EditorEventManagerBase {
|
||||||
|
@ -112,6 +115,8 @@ public class EditorEventManagerBase {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final WeakHashMap<Editor, List<Runnable>> runOnRegistry = new WeakHashMap<>();
|
||||||
|
|
||||||
public static void registerManager(EditorEventManager manager) {
|
public static void registerManager(EditorEventManager manager) {
|
||||||
String uri = FileUtils.editorToURIString(manager.editor);
|
String uri = FileUtils.editorToURIString(manager.editor);
|
||||||
synchronized (uriToManagers) {
|
synchronized (uriToManagers) {
|
||||||
|
@ -124,7 +129,29 @@ public class EditorEventManagerBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
editorToManager.put(manager.editor, manager);
|
|
||||||
|
synchronized (runOnRegistry) {
|
||||||
|
editorToManager.put(manager.editor, manager);
|
||||||
|
if (runOnRegistry.containsKey(manager.editor)) {
|
||||||
|
var tasks = runOnRegistry.remove(manager.editor);
|
||||||
|
for (var task: tasks) {
|
||||||
|
ApplicationUtils.invokeLater(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runWhenManagerGetsRegistered(Editor editor, Runnable... runnables) {
|
||||||
|
synchronized (runOnRegistry) {
|
||||||
|
var manager = forEditor(editor);
|
||||||
|
if (manager != null) {
|
||||||
|
for (var task: runnables) {
|
||||||
|
ApplicationUtils.invokeLater(task);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runOnRegistry.computeIfAbsent(editor, (ignored) -> new ArrayList<>()).addAll(List.of(runnables));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unregisterManager(EditorEventManager manager) {
|
public static void unregisterManager(EditorEventManager manager) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ package com.falsepattern.zigbrains.lsp.requests;
|
||||||
public enum Timeouts {
|
public enum Timeouts {
|
||||||
CODEACTION(2000), CODELENS(2000), COMPLETION(1000), DEFINITION(2000), DOC_HIGHLIGHT(1000), EXECUTE_COMMAND(
|
CODEACTION(2000), CODELENS(2000), COMPLETION(1000), DEFINITION(2000), DOC_HIGHLIGHT(1000), EXECUTE_COMMAND(
|
||||||
2000), FORMATTING(2000), HOVER(2000), INIT(10000), REFERENCES(2000), SIGNATURE(1000), SHUTDOWN(
|
2000), FORMATTING(2000), HOVER(2000), INIT(10000), REFERENCES(2000), SIGNATURE(1000), SHUTDOWN(
|
||||||
5000), SYMBOLS(2000), WILLSAVE(2000), FOLDING(1000), HIGHLIGHTING(1000);
|
5000), SYMBOLS(2000), WILLSAVE(2000), FOLDING(1000), HIGHLIGHTING(1000), INLAY_HINTS(2000);
|
||||||
|
|
||||||
private final int defaultTimeout;
|
private final int defaultTimeout;
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
<vendor>FalsePattern</vendor>
|
<vendor>FalsePattern</vendor>
|
||||||
|
|
||||||
<depends>com.intellij.modules.platform</depends>
|
<depends>com.intellij.modules.platform</depends>
|
||||||
|
<resource-bundle>zigbrains.Bundle</resource-bundle>
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<!-- region Zig -->
|
<!-- region Zig -->
|
||||||
|
|
||||||
<!-- region LSP4IntelliJ -->
|
<!-- region LSP -->
|
||||||
|
|
||||||
<!-- register a listener on editor events, required for lsp file sync -->
|
<!-- register a listener on editor events, required for lsp file sync -->
|
||||||
<editorFactoryListener implementation="com.falsepattern.zigbrains.lsp.listeners.LSPEditorListener"/>
|
<editorFactoryListener implementation="com.falsepattern.zigbrains.lsp.listeners.LSPEditorListener"/>
|
||||||
|
@ -58,7 +58,16 @@
|
||||||
<!-- needed for documentation -->
|
<!-- needed for documentation -->
|
||||||
<platform.backend.documentation.targetProvider implementation="com.falsepattern.zigbrains.lsp.contributors.LSPDocumentationTargetProvider"/>
|
<platform.backend.documentation.targetProvider implementation="com.falsepattern.zigbrains.lsp.contributors.LSPDocumentationTargetProvider"/>
|
||||||
|
|
||||||
<!-- endregion LSP4IntelliJ -->
|
<!-- needed for inlay hints -->
|
||||||
|
<codeInsight.declarativeInlayProvider implementationClass="com.falsepattern.zigbrains.lsp.contributors.LSPInlayHintProvider"
|
||||||
|
bundle="zigbrains.Bundle"
|
||||||
|
nameKey="inlayprovider"
|
||||||
|
providerId="ZigBrains"
|
||||||
|
isEnabledByDefault="true"
|
||||||
|
group="PARAMETERS_GROUP"
|
||||||
|
language="Zig"/>
|
||||||
|
|
||||||
|
<!-- endregion LSP -->
|
||||||
|
|
||||||
<fileType name="Zig File"
|
<fileType name="Zig File"
|
||||||
implementationClass="com.falsepattern.zigbrains.zig.ZigFileType"
|
implementationClass="com.falsepattern.zigbrains.zig.ZigFileType"
|
||||||
|
@ -125,7 +134,7 @@
|
||||||
<actions>
|
<actions>
|
||||||
<!-- region Zig -->
|
<!-- region Zig -->
|
||||||
|
|
||||||
<!-- region LSP4IntelliJ -->
|
<!-- region LSP -->
|
||||||
|
|
||||||
<!-- needed for find references -->
|
<!-- needed for find references -->
|
||||||
<action class="com.falsepattern.zigbrains.lsp.actions.LSPReferencesAction"
|
<action class="com.falsepattern.zigbrains.lsp.actions.LSPReferencesAction"
|
||||||
|
@ -134,13 +143,13 @@
|
||||||
keymap="$default"/>
|
keymap="$default"/>
|
||||||
</action>
|
</action>
|
||||||
|
|
||||||
<!-- endregion LSP4IntelliJ -->
|
<!-- endregion LSP -->
|
||||||
|
|
||||||
<!-- endregion Zig -->
|
<!-- endregion Zig -->
|
||||||
</actions>
|
</actions>
|
||||||
|
|
||||||
<applicationListeners>
|
<applicationListeners>
|
||||||
<!-- region LSP4IntelliJ -->
|
<!-- region LSP -->
|
||||||
|
|
||||||
<!-- required for lsp file sync -->
|
<!-- required for lsp file sync -->
|
||||||
<listener class="com.falsepattern.zigbrains.lsp.listeners.VFSListener"
|
<listener class="com.falsepattern.zigbrains.lsp.listeners.VFSListener"
|
||||||
|
@ -148,7 +157,7 @@
|
||||||
<listener class="com.falsepattern.zigbrains.lsp.listeners.LSPProjectManagerListener"
|
<listener class="com.falsepattern.zigbrains.lsp.listeners.LSPProjectManagerListener"
|
||||||
topic="com.intellij.openapi.project.ProjectManagerListener"/>
|
topic="com.intellij.openapi.project.ProjectManagerListener"/>
|
||||||
|
|
||||||
<!-- endregion LSP4IntelliJ -->
|
<!-- endregion LSP -->
|
||||||
</applicationListeners>
|
</applicationListeners>
|
||||||
|
|
||||||
|
|
||||||
|
|
1
src/main/resources/zigbrains/Bundle.properties
Normal file
1
src/main/resources/zigbrains/Bundle.properties
Normal file
|
@ -0,0 +1 @@
|
||||||
|
inlayprovider=ZLS Inlay Provider
|
Loading…
Add table
Reference in a new issue