backport: 13.1.0

ci: 13.1.0

feat: Grammar error recovery

(cherry picked from commit 1ff76b15a7)

fix: Update to latest zig grammar

(cherry picked from commit 4b2e9b44f6)

fix: NPE in executeCommands

(cherry picked from commit 99a0e7811d)

fix: Autocomplete wasn't being done by intellij

(cherry picked from commit 7754e8f2c8)

fix: LSP id collision

(cherry picked from commit b8aa355392)

docs: Update changelog

(cherry picked from commit 6cb8ebebb7)

feat: Integrated parameter info popup

(cherry picked from commit 868a83326a)

fix: Better indenting logic

(cherry picked from commit a266ff94c3)
This commit is contained in:
FalsePattern 2024-03-15 17:28:50 +01:00
parent 4bbe8751b0
commit b164d9f263
Signed by: falsepattern
GPG key ID: E930CDEC50C50E23
7 changed files with 220 additions and 130 deletions

View file

@ -18,6 +18,24 @@ Changelog structure reference:
## [Unreleased] ## [Unreleased]
## [13.1.0]
### Added
- Zig
- Parameter info (CTRL + P) is now properly integrated
- Parser error recovery (completion will still work even with missing semicolons in a statement)
### Fixed
- LSP
- The registry IDs of some of the LSP handlers were colliding with the Rust intellij plugin
- Autocompletion insertion is now fully handled by intellij, this should fix some of the weirdness
- Zig
- Indent support for function parameters and struct initializers
- Updated to latest grammar spec (https://github.com/ziglang/zig-spec/commit/78c2e2e5cfa7090965deaf631cb8ca6f405b7c42)
## [13.0.1] ## [13.0.1]
### HOTFIX CHANGES ### HOTFIX CHANGES

View file

@ -35,7 +35,6 @@ import com.falsepattern.zigbrains.lsp.utils.FileUtils;
import com.falsepattern.zigbrains.lsp.utils.GUIUtils; import com.falsepattern.zigbrains.lsp.utils.GUIUtils;
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.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.codeInsight.lookup.LookupElementBuilder;
@ -96,7 +95,6 @@ import org.eclipse.lsp4j.InsertReplaceEdit;
import org.eclipse.lsp4j.InsertTextFormat; import org.eclipse.lsp4j.InsertTextFormat;
import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.LocationLink; import org.eclipse.lsp4j.LocationLink;
import org.eclipse.lsp4j.MarkupContent;
import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.ReferenceContext; import org.eclipse.lsp4j.ReferenceContext;
@ -144,7 +142,6 @@ import static com.falsepattern.zigbrains.common.util.ApplicationUtil.invokeLater
import static com.falsepattern.zigbrains.common.util.ApplicationUtil.pool; import static com.falsepattern.zigbrains.common.util.ApplicationUtil.pool;
import static com.falsepattern.zigbrains.common.util.ApplicationUtil.writeAction; import static com.falsepattern.zigbrains.common.util.ApplicationUtil.writeAction;
import static com.falsepattern.zigbrains.lsp.utils.DocumentUtils.toEither; import static com.falsepattern.zigbrains.lsp.utils.DocumentUtils.toEither;
import static com.falsepattern.zigbrains.lsp.utils.GUIUtils.createAndShowEditorHint;
/** /**
* Class handling events related to an Editor (a Document) * Class handling events related to an Editor (a Document)
@ -236,17 +233,6 @@ public class EditorEventManager {
return identifier; return identifier;
} }
/**
* Calls onTypeFormatting or signatureHelp if the character typed was a trigger character
*
* @param c The character just typed
*/
public void characterTyped(char c) {
if (signatureTriggers.contains(Character.toString(c))) {
signatureHelp();
}
}
private boolean isSupportedLanguageFile(PsiFile file) { private boolean isSupportedLanguageFile(PsiFile file) {
return file.getLanguage().isKindOf(PlainTextLanguage.INSTANCE) return file.getLanguage().isKindOf(PlainTextLanguage.INSTANCE)
|| FileUtils.isFileSupported(file.getVirtualFile()); || FileUtils.isFileSupported(file.getVirtualFile());
@ -518,70 +504,40 @@ public class EditorEventManager {
return null; return null;
} }
/** public CompletableFuture<SignatureHelp> getSignatureHelp(int offset) {
* Calls signatureHelp at the current editor caret position
*/
@SuppressWarnings("WeakerAccess")
public void signatureHelp() {
if (editor.isDisposed()) { if (editor.isDisposed()) {
return; return CompletableFuture.failedFuture(new RuntimeException("Editor is disposed"));
} }
LogicalPosition lPos = editor.getCaretModel().getCurrentCaret().getLogicalPosition(); SignatureHelpParams params = new SignatureHelpParams(identifier, DocumentUtils.offsetToLSPPos(editor, offset));
Point point = editor.logicalPositionToXY(lPos); val result = new CompletableFuture<SignatureHelp>();
SignatureHelpParams params = new SignatureHelpParams(identifier, DocumentUtils.logicalToLSPPos(lPos, editor));
pool(() -> { pool(() -> {
CompletableFuture<SignatureHelp> future = wrapper.getRequestManager().signatureHelp(params); val future = wrapper.getRequestManager().signatureHelp(params);
if (future == null) { if (future == null) {
result.complete(null);
return; return;
} }
try { try {
SignatureHelp signatureResp = future.get(Timeout.getTimeout(Timeouts.SIGNATURE), TimeUnit.MILLISECONDS); val signatureResp = future.get(Timeout.getTimeout(Timeouts.SIGNATURE), TimeUnit.MILLISECONDS);
wrapper.notifySuccess(Timeouts.SIGNATURE); wrapper.notifySuccess(Timeouts.SIGNATURE);
if (signatureResp == null) { if (signatureResp == null) {
result.complete(null);
return; return;
} }
List<SignatureInformation> signatures = signatureResp.getSignatures(); result.complete(signatureResp);
if (signatures == null || signatures.isEmpty()) {
return;
}
int activeSignatureIndex = signatureResp.getActiveSignature();
int activeParameterIndex = signatureResp.getActiveParameter();
String activeParameter = signatures.get(activeSignatureIndex).getParameters().size() > activeParameterIndex ?
extractLabel(signatures.get(activeSignatureIndex), signatures.get(activeSignatureIndex).getParameters().get(activeParameterIndex).getLabel()) : "";
Either<String, MarkupContent> signatureDescription = signatures.get(activeSignatureIndex).getDocumentation();
StringBuilder builder = new StringBuilder();
builder.append("<html>");
if (signatureDescription == null) {
builder.append("<b>").append(signatures.get(activeSignatureIndex).getLabel().
replace(" " + activeParameter, String.format("<font color=\"orange\"> %s</font>",
activeParameter))).append("</b>");
} else if (signatureDescription.isLeft()) {
// Todo - Add parameter Documentation
String descriptionLeft = signatureDescription.getLeft().replace(System.lineSeparator(), "<br />");
builder.append("<b>").append(signatures.get(activeSignatureIndex).getLabel()
.replace(" " + activeParameter, String.format("<font color=\"orange\"> %s</font>",
activeParameter))).append("</b>");
builder.append("<div>").append(descriptionLeft).append("</div>");
} else if (signatureDescription.isRight()) {
// Todo - Add marked content parsing
builder.append("<b>").append(signatures.get(activeSignatureIndex).getLabel()).append("</b>");
}
builder.append("</html>");
invokeLater(() -> currentHint = createAndShowEditorHint(editor, builder.toString(), point, HintManager.UNDER, HintManager.HIDE_BY_OTHER_HINT));
} catch (TimeoutException e) { } catch (TimeoutException e) {
LOG.warn(e); LOG.warn(e);
wrapper.notifyFailure(Timeouts.SIGNATURE); wrapper.notifyFailure(Timeouts.SIGNATURE);
result.completeExceptionally(e);
} catch (JsonRpcException | ExecutionException | InterruptedException e) { } catch (JsonRpcException | ExecutionException | InterruptedException e) {
LOG.warn(e); LOG.warn(e);
wrapper.crashed(e); wrapper.crashed(e);
result.completeExceptionally(e);
} catch (Exception e) { } catch (Exception e) {
LOG.warn("Internal error occurred when processing signature help"); LOG.warn("Internal error occurred when processing signature help");
result.completeExceptionally(e);
} }
}); });
return result;
} }
private String extractLabel(SignatureInformation signatureInformation, Either<String, Tuple.Two<Integer, Integer>> label) { private String extractLabel(SignatureInformation signatureInformation, Either<String, Tuple.Two<Integer, Integer>> label) {
@ -808,8 +764,6 @@ public class EditorEventManager {
if (addTextEdits != null) { if (addTextEdits != null) {
builder = builder.withInsertHandler((InsertionContext context, LookupElement lookupElement) -> invokeLater(() -> { builder = builder.withInsertHandler((InsertionContext context, LookupElement lookupElement) -> invokeLater(() -> {
applyInitialTextEdit(item, context, lookupString);
if (format == InsertTextFormat.Snippet) { if (format == InsertTextFormat.Snippet) {
context.commitDocument(); context.commitDocument();
prepareAndRunSnippet(lookupString); prepareAndRunSnippet(lookupString);
@ -823,8 +777,6 @@ public class EditorEventManager {
})); }));
} else if (command != null) { } else if (command != null) {
builder = builder.withInsertHandler((InsertionContext context, LookupElement lookupElement) -> { builder = builder.withInsertHandler((InsertionContext context, LookupElement lookupElement) -> {
applyInitialTextEdit(item, context, lookupString);
if (format == InsertTextFormat.Snippet) { if (format == InsertTextFormat.Snippet) {
context.commitDocument(); context.commitDocument();
prepareAndRunSnippet(lookupString); prepareAndRunSnippet(lookupString);
@ -834,8 +786,6 @@ public class EditorEventManager {
}); });
} else { } else {
builder = builder.withInsertHandler((InsertionContext context, LookupElement lookupElement) -> { builder = builder.withInsertHandler((InsertionContext context, LookupElement lookupElement) -> {
applyInitialTextEdit(item, context, lookupString);
if (format == InsertTextFormat.Snippet) { if (format == InsertTextFormat.Snippet) {
context.commitDocument(); context.commitDocument();
prepareAndRunSnippet(lookupString); prepareAndRunSnippet(lookupString);
@ -846,37 +796,6 @@ public class EditorEventManager {
return builder; return builder;
} }
private void applyInitialTextEdit(CompletionItem item, InsertionContext context, String lookupString) {
if (item.getTextEdit() != null) {
// remove intellij edit, server is controlling insertion
writeAction(() -> {
Runnable runnable = () -> this.editor.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
CommandProcessor.getInstance()
.executeCommand(project, runnable, "Removing Intellij Completion", "LSPPlugin", editor.getDocument());
});
context.commitDocument();
if(item.getTextEdit().isLeft()) {
item.getTextEdit().getLeft().setNewText(getLookupStringWithoutPlaceholders(item, lookupString));
}
applyEdit(Integer.MAX_VALUE, Collections.singletonList(item.getTextEdit()), "text edit", false, true);
} else {
// client handles insertion, determine a prefix (to allow completions of partially matching items)
int prefixLength = getCompletionPrefixLength(context.getStartOffset());
writeAction(() -> {
Runnable runnable = () -> this.editor.getDocument().deleteString(context.getStartOffset() - prefixLength, context.getStartOffset());
CommandProcessor.getInstance()
.executeCommand(project, runnable, "Removing Prefix", "LSPPlugin", editor.getDocument());
});
context.commitDocument();
}
}
private int getCompletionPrefixLength(int offset) { private int getCompletionPrefixLength(int offset) {
return getCompletionPrefix(this.editor, offset).length(); return getCompletionPrefix(this.editor, offset).length();
} }
@ -1107,6 +1026,8 @@ public class EditorEventManager {
return; return;
} }
commands.stream().map(c -> { commands.stream().map(c -> {
if (c == null)
return null;
ExecuteCommandParams params = new ExecuteCommandParams(); ExecuteCommandParams params = new ExecuteCommandParams();
params.setArguments(c.getArguments()); params.setArguments(c.getArguments());
params.setCommand(c.getCommand()); params.setCommand(c.getCommand());

View file

@ -29,22 +29,8 @@ import org.jetbrains.annotations.NotNull;
* This class notifies an EditorEventManager that a character has been typed in the editor * This class notifies an EditorEventManager that a character has been typed in the editor
*/ */
public class LSPTypedHandler extends TypedHandlerDelegate { public class LSPTypedHandler extends TypedHandlerDelegate {
@Override @Override
public Result charTyped(char c, Project project, @NotNull Editor editor, @NotNull PsiFile file) { public @NotNull Result checkAutoPopup(char charTyped, @NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
if (!FileUtils.isFileSupported(file.getVirtualFile())) {
return Result.CONTINUE;
}
EditorEventManager eventManager = EditorEventManagerBase.forEditor(editor);
if (eventManager != null) {
eventManager.characterTyped(c);
}
return Result.CONTINUE;
}
@Override
public Result checkAutoPopup(char charTyped, @NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
if (!FileUtils.isFileSupported(file.getVirtualFile())) { if (!FileUtils.isFileSupported(file.getVirtualFile())) {
return Result.CONTINUE; return Result.CONTINUE;
} }

View file

@ -188,13 +188,11 @@ VarDeclProto ::= (KEYWORD_CONST | KEYWORD_VAR) IDENTIFIER (COLON TypeExpr)? Byte
GlobalVarDecl ::= VarDeclProto (EQUAL Expr)? SEMICOLON GlobalVarDecl ::= VarDeclProto (EQUAL Expr)? SEMICOLON
ContainerField ContainerField ::= DOC_COMMENT? KEYWORD_COMPTUME? !KEYWORD_FN (IDENTIFIER COLON)? TypeExpr ByteAlign? (EQUAL Expr)?
::= DOC_COMMENT? KEYWORD_COMPTIME? IDENTIFIER (COLON (KEYWORD_ANYTYPE | TypeExpr) ByteAlign?)? (EQUAL Expr)?
| DOC_COMMENT? KEYWORD_COMPTIME? (IDENTIFIER COLON)? !KEYWORD_FN TypeExpr ByteAlign? (EQUAL Expr)?
// *** Block Level *** // *** Block Level ***
Statement Statement
::= KEYWORD_COMPTIME? ComptimeStatement ::= KEYWORD_COMPTIME ComptimeStatement
| KEYWORD_NOSUSPEND BlockExprStatement | KEYWORD_NOSUSPEND BlockExprStatement
| KEYWORD_DEFER BlockExprStatement | KEYWORD_DEFER BlockExprStatement
| KEYWORD_ERRDEFER Payload? BlockExprStatement | KEYWORD_ERRDEFER Payload? BlockExprStatement
@ -274,7 +272,9 @@ PrimaryExpr
IfExpr ::= IfPrefix Expr (KEYWORD_ELSE Payload? Expr)? IfExpr ::= IfPrefix Expr (KEYWORD_ELSE Payload? Expr)?
Block ::= LBRACE Statement* RBRACE Block ::= LBRACE ZB_Block_Statement* RBRACE {pin(".*")=1}
private ZB_Block_Statement ::= Statement {recoverWhile="#auto"}
LoopExpr ::= KEYWORD_INLINE? (ForExpr | WhileExpr) LoopExpr ::= KEYWORD_INLINE? (ForExpr | WhileExpr)
@ -285,9 +285,12 @@ WhileExpr ::= WhilePrefix Expr (KEYWORD_ELSE Payload? Expr)?
CurlySuffixExpr ::= TypeExpr InitList? CurlySuffixExpr ::= TypeExpr InitList?
InitList InitList
::= LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE ::= LBRACE FieldInit (COMMA ZB_InitList_FieldInit)* COMMA? RBRACE
| LBRACE Expr (COMMA Expr)* COMMA? RBRACE | LBRACE Expr (COMMA ZB_InitList_Expr)* COMMA? RBRACE
| LBRACE RBRACE | LBRACE RBRACE {pin=1}
private ZB_InitList_FieldInit ::= FieldInit {recoverWhile="#auto"}
private ZB_InitList_Expr ::= Expr {recoverWhile="#auto"}
TypeExpr ::= PrefixTypeOp* ErrorUnionExpr TypeExpr ::= PrefixTypeOp* ErrorUnionExpr

View file

@ -0,0 +1,147 @@
/*
* Copyright 2023-2024 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.zig.completion;
import com.falsepattern.zigbrains.lsp.editor.EditorEventManagerBase;
import com.falsepattern.zigbrains.lsp.utils.FileUtils;
import com.falsepattern.zigbrains.zig.psi.ZigExprList;
import com.intellij.lang.parameterInfo.CreateParameterInfoContext;
import com.intellij.lang.parameterInfo.ParameterInfoHandler;
import com.intellij.lang.parameterInfo.ParameterInfoUIContext;
import com.intellij.lang.parameterInfo.UpdateParameterInfoContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import lombok.val;
import org.eclipse.lsp4j.ParameterInformation;
import org.eclipse.lsp4j.SignatureHelp;
import org.eclipse.lsp4j.SignatureInformation;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.WeakHashMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class ZigParameterInfoHandler implements ParameterInfoHandler<PsiElement, ZigParameterInfoHandler.IndexedSignatureInformation> {
private final WeakHashMap<PsiElement, CompletableFuture<SignatureHelp>> requests = new WeakHashMap<>();
private final Logger LOG = Logger.getInstance(ZigParameterInfoHandler.class);
public record IndexedSignatureInformation(SignatureInformation information, boolean active) {}
private @Nullable PsiElement fetchQuery(@NotNull PsiFile file, int offset) {
val sourceElem = file.findElementAt(offset);
if (sourceElem == null)
return null;
PsiElement element = PsiTreeUtil.getParentOfType(sourceElem, ZigExprList.class);
if (element == null) {
element = sourceElem.getPrevSibling();
while (element instanceof PsiWhiteSpace)
element = element.getPrevSibling();
if (!(element instanceof ZigExprList))
return null;
}
val editor = FileUtils.editorFromPsiFile(file);
if (editor == null)
return null;
val manager = EditorEventManagerBase.forEditor(editor);
if (manager == null)
return null;
val request = manager.getSignatureHelp(offset);
requests.put(element, request);
return element;
}
private @Nullable SignatureHelp getResponse(PsiElement element) {
val request = requests.get(element);
if (request == null)
return null;
final SignatureHelp response;
try {
response = request.get();
} catch (InterruptedException | ExecutionException e) {
LOG.warn(e);
return null;
}
return response;
}
@Override
public @Nullable PsiElement findElementForParameterInfo(@NotNull CreateParameterInfoContext context) {
return fetchQuery(context.getFile(), context.getOffset());
}
@Override
public void showParameterInfo(@NotNull PsiElement element, @NotNull CreateParameterInfoContext context) {
val response = getResponse(element);
if (response == null)
return;
val signatures = response.getSignatures();
val indexedSignatures = new IndexedSignatureInformation[signatures.size()];
val active = response.getActiveSignature();
for (int i = 0; i < indexedSignatures.length; i++) {
indexedSignatures[i] = new IndexedSignatureInformation(signatures.get(i), i == active);
}
context.setItemsToShow(indexedSignatures);
context.showHint(element, 0, this);
}
@Override
public @Nullable PsiElement findElementForUpdatingParameterInfo(@NotNull UpdateParameterInfoContext context) {
return fetchQuery(context.getFile(), context.getOffset());
}
@Override
public void updateParameterInfo(@NotNull PsiElement psiElement, @NotNull UpdateParameterInfoContext context) {
val response = getResponse(psiElement);
if (response == null)
return;
context.setCurrentParameter(response.getActiveParameter());
}
@Override
public void updateUI(IndexedSignatureInformation p, @NotNull ParameterInfoUIContext context) {
if (p == null) {
context.setUIComponentEnabled(false);
return;
}
val txt = new StringBuilder();
int hStart = 0;
int hEnd = 0;
List<ParameterInformation> parameters = p.information.getParameters();
val active = context.getCurrentParameterIndex();
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
var param = parameters.get(i);
if (i != 0) {
txt.append(", ");
}
if (i == active) {
hStart = txt.length();
}
txt.append(param.getLabel().getLeft());
if (i == active) {
hEnd = txt.length();
}
}
context.setupUIComponentPresentation(txt.toString(), hStart, hEnd, !p.active, false, true, context.getDefaultParameterColor());
}
}

View file

@ -26,12 +26,18 @@ import com.intellij.formatting.Wrap;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.TokenType; import com.intellij.psi.TokenType;
import com.intellij.psi.formatter.common.AbstractBlock; import com.intellij.psi.formatter.common.AbstractBlock;
import com.intellij.psi.tree.IElementType;
import lombok.val;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static com.falsepattern.zigbrains.zig.psi.ZigTypes.BLOCK;
import static com.falsepattern.zigbrains.zig.psi.ZigTypes.EXPR_LIST;
import static com.falsepattern.zigbrains.zig.psi.ZigTypes.INIT_LIST;
public class ZigBlock extends AbstractBlock { public class ZigBlock extends AbstractBlock {
private final SpacingBuilder spacingBuilder; private final SpacingBuilder spacingBuilder;
@ -69,16 +75,22 @@ public class ZigBlock extends AbstractBlock {
@Override @Override
protected @Nullable Indent getChildIndent() { protected @Nullable Indent getChildIndent() {
if (myNode.getElementType() == ZigTypes.BLOCK) { return getIndentBasedOnParentType(getNode().getElementType());
return Indent.getNormalIndent();
}
return Indent.getNoneIndent();
} }
@Override @Override
public Indent getIndent() { public Indent getIndent() {
if (myNode.getElementType() == ZigTypes.STATEMENT) { val parent = getNode().getTreeParent();
if (parent != null) {
return getIndentBasedOnParentType(parent.getElementType());
}
return Indent.getNoneIndent();
}
private static Indent getIndentBasedOnParentType(IElementType elementType) {
if (elementType == BLOCK ||
elementType == INIT_LIST ||
elementType == EXPR_LIST) {
return Indent.getNormalIndent(); return Indent.getNormalIndent();
} }

View file

@ -38,29 +38,29 @@
language="any"/> language="any"/>
<!-- needed for completion as well as signature help --> <!-- needed for completion as well as signature help -->
<typedHandler implementation="com.falsepattern.zigbrains.lsp.listeners.LSPTypedHandler" <typedHandler implementation="com.falsepattern.zigbrains.lsp.listeners.LSPTypedHandler"
id="LSPTypedHandler"/> id="ZBLSPTypedHandler"/>
<!-- needed for code diagnostics --> <!-- needed for code diagnostics -->
<externalAnnotator id="LSPAnnotator" <externalAnnotator id="ZBLSPAnnotator"
language="Zig" language="Zig"
implementationClass="com.falsepattern.zigbrains.lsp.contributors.annotator.LSPAnnotator"/> implementationClass="com.falsepattern.zigbrains.lsp.contributors.annotator.LSPAnnotator"/>
<!-- needed for Workspace Symbols --> <!-- needed for Workspace Symbols -->
<gotoSymbolContributor implementation="com.falsepattern.zigbrains.lsp.contributors.symbol.LSPSymbolContributor" <gotoSymbolContributor implementation="com.falsepattern.zigbrains.lsp.contributors.symbol.LSPSymbolContributor"
id="LSPSymbolContributor"/> id="ZBLSPSymbolContributor"/>
<!-- needed for renaming --> <!-- needed for renaming -->
<renameHandler implementation="com.falsepattern.zigbrains.lsp.contributors.rename.LSPRenameHandler" <renameHandler implementation="com.falsepattern.zigbrains.lsp.contributors.rename.LSPRenameHandler"
id="LSPRenameHandler" id="ZBLSPRenameHandler"
order="first"/> order="first"/>
<renamePsiElementProcessor implementation="com.falsepattern.zigbrains.lsp.contributors.rename.LSPRenameProcessor" <renamePsiElementProcessor implementation="com.falsepattern.zigbrains.lsp.contributors.rename.LSPRenameProcessor"
id="LSPRenameProcessor" id="ZBLSPRenameProcessor"
order="first"/> order="first"/>
<!-- needed for folding support --> <!-- needed for folding support -->
<lang.foldingBuilder language="Zig" <lang.foldingBuilder language="Zig"
implementationClass="com.falsepattern.zigbrains.zig.ide.ZigFoldingRangeProvider" implementationClass="com.falsepattern.zigbrains.zig.ide.ZigFoldingRangeProvider"
id="LSPFoldingRangeProvider" id="ZBLSPFoldingRangeProvider"
order="first"/> order="first"/>
<!-- needed for documentation --> <!-- needed for documentation -->
@ -109,6 +109,9 @@
key="notif-zls" key="notif-zls"
id="ZigBrains.ZLS"/> id="ZigBrains.ZLS"/>
<codeInsight.parameterInfo language="Zig"
implementationClass="com.falsepattern.zigbrains.zig.completion.ZigParameterInfoHandler"/>
<platform.backend.documentation.linkHandler implementation="com.falsepattern.zigbrains.lsp.contributors.LSPDocumentationLinkHandler"/> <platform.backend.documentation.linkHandler implementation="com.falsepattern.zigbrains.lsp.contributors.LSPDocumentationLinkHandler"/>
</extensions> </extensions>
@ -123,7 +126,7 @@
<!-- needed for find references --> <!-- needed for find references -->
<action class="com.falsepattern.zigbrains.lsp.actions.LSPReferencesAction" <action class="com.falsepattern.zigbrains.lsp.actions.LSPReferencesAction"
id="LSPFindUsages"> id="ZBLSPFindUsages">
<keyboard-shortcut first-keystroke="shift alt F7" <keyboard-shortcut first-keystroke="shift alt F7"
keymap="$default"/> keymap="$default"/>
</action> </action>