From 8545800fc18ecc13b7c1336c3182a23ba630999d Mon Sep 17 00:00:00 2001 From: azerr Date: Tue, 13 Jun 2023 08:00:30 +0200 Subject: [PATCH] Improve completion --- .../lsp4ij/internal/SupportedFeatures.java | 24 +-- .../completion/LSPCompletionConfidence.java | 15 ++ .../intellij/qute/lang/QuteLexer.java | 152 ++++++++++++------ .../intellij/qute/lang/QuteTokenType.java | 26 +++ src/main/resources/META-INF/lsp4ij-qute.xml | 1 + 5 files changed, 161 insertions(+), 57 deletions(-) create mode 100644 src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSPCompletionConfidence.java create mode 100644 src/main/java/com/redhat/devtools/intellij/qute/lang/QuteTokenType.java diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/internal/SupportedFeatures.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/internal/SupportedFeatures.java index deea74ff8..24fa8c63e 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/internal/SupportedFeatures.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/internal/SupportedFeatures.java @@ -78,11 +78,11 @@ public class SupportedFeatures { textDocumentClientCapabilities.setInlayHint(new InlayHintCapabilities()); // TODO : support textDocument/colorPresentation // textDocumentClientCapabilities.setColorProvider(new ColorProviderCapabilities()); - final var completionItemCapabilities = new CompletionItemCapabilities(Boolean.TRUE); + final var completionItemCapabilities = new CompletionItemCapabilities(Boolean.FALSE); completionItemCapabilities .setDocumentationFormat(Arrays.asList(MarkupKind.MARKDOWN, MarkupKind.PLAINTEXT)); - completionItemCapabilities.setInsertTextModeSupport(new CompletionItemInsertTextModeSupportCapabilities(List.of(InsertTextMode.AsIs, InsertTextMode.AdjustIndentation))); - completionItemCapabilities.setResolveSupport(new CompletionItemResolveSupportCapabilities(List.of("documentation", "detail", "additionalTextEdits"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + // completionItemCapabilities.setInsertTextModeSupport(new CompletionItemInsertTextModeSupportCapabilities(List.of(InsertTextMode.AsIs, InsertTextMode.AdjustIndentation))); + // completionItemCapabilities.setResolveSupport(new CompletionItemResolveSupportCapabilities(List.of("documentation", "detail", "additionalTextEdits"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ textDocumentClientCapabilities.setCompletion(new CompletionCapabilities(completionItemCapabilities)); final var definitionCapabilities = new DefinitionCapabilities(); definitionCapabilities.setLinkSupport(Boolean.TRUE); @@ -115,11 +115,13 @@ public class SupportedFeatures { textDocumentClientCapabilities.setOnTypeFormatting(null); // TODO // TODO : support textDocument/rangeFormatting // textDocumentClientCapabilities.setRangeFormatting(new RangeFormattingCapabilities()); - textDocumentClientCapabilities.setReferences(new ReferencesCapabilities()); - final var renameCapabilities = new RenameCapabilities(); - renameCapabilities.setPrepareSupport(true); - textDocumentClientCapabilities.setRename(renameCapabilities); - // TODO + // TODO : support textDocument/references + // textDocumentClientCapabilities.setReferences(new ReferencesCapabilities()); + // TODO : support textDocument/rename + //final var renameCapabilities = new RenameCapabilities(); + //renameCapabilities.setPrepareSupport(true); + //textDocumentClientCapabilities.setRename(renameCapabilities); + // TODO : support textDocument/signatureHelp // textDocumentClientCapabilities.setSignatureHelp(new SignatureHelpCapabilities()); textDocumentClientCapabilities .setSynchronization(new SynchronizationCapabilities(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE)); @@ -151,9 +153,9 @@ public class SupportedFeatures { public static WindowClientCapabilities getWindowClientCapabilities() { final var windowClientCapabilities = new WindowClientCapabilities(); - windowClientCapabilities.setShowDocument(new ShowDocumentCapabilities(true)); - windowClientCapabilities.setWorkDoneProgress(true); - windowClientCapabilities.setShowMessage(new WindowShowMessageRequestCapabilities()); + //windowClientCapabilities.setShowDocument(new ShowDocumentCapabilities(true)); + //windowClientCapabilities.setWorkDoneProgress(true); + //windowClientCapabilities.setShowMessage(new WindowShowMessageRequestCapabilities()); return windowClientCapabilities; } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSPCompletionConfidence.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSPCompletionConfidence.java new file mode 100644 index 000000000..81307a0b9 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSPCompletionConfidence.java @@ -0,0 +1,15 @@ +package com.redhat.devtools.intellij.lsp4ij.operations.completion; + +import com.intellij.codeInsight.completion.CompletionConfidence; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.ThreeState; +import org.jetbrains.annotations.NotNull; + +public class LSPCompletionConfidence extends CompletionConfidence { + + @Override + public @NotNull ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) { + return ThreeState.NO; + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteLexer.java b/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteLexer.java index a5e19e233..f5db7b82e 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteLexer.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteLexer.java @@ -10,89 +10,149 @@ ******************************************************************************/ package com.redhat.devtools.intellij.qute.lang; -import com.intellij.lexer.Lexer; -import com.intellij.lexer.LexerPosition; +import com.intellij.lexer.LexerBase; +import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.psi.tree.IElementType; -import com.redhat.qute.parser.template.Node; -import com.redhat.qute.parser.template.Template; -import com.redhat.qute.parser.template.TemplateParser; +import com.redhat.qute.parser.template.scanner.ScannerState; +import com.redhat.qute.parser.template.scanner.TemplateScanner; +import com.redhat.qute.parser.template.scanner.TokenType; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -public class QuteLexer extends Lexer { - Template template; - private CharSequence buffer; - private int endOffset; +public class QuteLexer extends LexerBase { - private int index; + private IElementType myTokenType; + private CharSequence myText; + + private int myTokenStart; + private int myTokenEnd; + + private int myBufferEnd; + private int myState; + + private boolean myFailed; + + + private TemplateScanner scanner; @Override public void start(@NotNull CharSequence buffer, int startOffset, int endOffset, int initialState) { - this.buffer = buffer; - this.endOffset = endOffset; - template = TemplateParser.parse(buffer.subSequence(startOffset, endOffset).toString(), ""); - this.index = initialState; + myText = buffer; + myTokenStart = myTokenEnd = startOffset; + myBufferEnd = endOffset; + //myFlex.reset(myText, startOffset, endOffset, initialState); + scanner = (TemplateScanner) TemplateScanner.createScanner(buffer.subSequence(startOffset,endOffset).toString(), 0); + myTokenType = null; } + @Override public int getState() { - return index; + locateToken(); + return myState; } - private Node getToken() { - return index< template.getChildCount()?template.getChild(index):null; - } @Override - public @Nullable IElementType getTokenType() { - Node node = getToken(); - return node!=null?QuteElementTypes.fromNode(node):null; + public IElementType getTokenType() { + locateToken(); + return myTokenType; } @Override public int getTokenStart() { - Node node = getToken(); - return node!=null?node.getStart():-1; + locateToken(); + return myTokenStart; } @Override public int getTokenEnd() { - Node node = getToken(); - return node!=null?node.getEnd():-1; - + locateToken(); + return myTokenEnd; } @Override public void advance() { - ++index; + locateToken(); + myTokenType = null; } + @NotNull @Override - public @NotNull LexerPosition getCurrentPosition() { - return new LexerPosition() { - @Override - public int getOffset() { - return getTokenStart(); - } + public CharSequence getBufferSequence() { + return myText; + } - @Override - public int getState() { - return getState(); + @Override + public int getBufferEnd() { + return myBufferEnd; + } + + protected void locateToken() { + if (myTokenType != null) return; + + myTokenStart = myTokenEnd; + if (myFailed) return; + + try { + TokenType tokenType = scanner.scan(); + while(tokenType != TokenType.EOS) { + IElementType elementType = getTokenType(tokenType); + if(elementType != null) { + myState = getStateAsInt(scanner.getScannerState()); + myTokenType = elementType; + myTokenEnd = scanner.getTokenEnd(); + break; + } + tokenType = scanner.scan(); } - }; + } + catch (ProcessCanceledException e) { + throw e; + } + catch (Throwable e) { + myFailed = true; + myTokenType = com.intellij.psi.TokenType.BAD_CHARACTER; + myTokenEnd = myBufferEnd; + //LOG.warn(myFlex.getClass().getName(), e); + } } - @Override - public void restore(@NotNull LexerPosition position) { - index = position.getState(); + private static IElementType getTokenType(TokenType tokenType) { + switch(tokenType) { + case StartParameterDeclaration: + return QuteTokenType.QUTE_START_PARAMETER_DECLARATION; + case EndParameterDeclaration: + return QuteTokenType.QUTE_END_PARAMETER_DECLARATION; + case StartExpression: + return QuteTokenType.QUTE_START_EXPRESSION; + case EndExpression: + return QuteTokenType.QUTE_END_EXPRESSION; + case StartTagOpen: + return QuteTokenType.QUTE_START_TAG_OPEN; + case StartTag: + return QuteTokenType.QUTE_START_TAG; + case EndTag: + return QuteTokenType.QUTE_END_TAG; + case EndTagSelfClose: + return QuteTokenType.QUTE_END_TAG_SELF_CLOSE; + case EndTagOpen: + return QuteTokenType.QUTE_END_TAG_OPEN; + case EndTagClose: + return QuteTokenType.QUTE_END_TAG_CLOSE; + case Whitespace: + return QuteTokenType.QUTE_WHITESPACE; + case ParameterTag: + return QuteTokenType.QUTE_PARAMETER_TAG; + } + return QuteElementTypes.QUTE_CONTENT; } - @Override - public @NotNull CharSequence getBufferSequence() { - return buffer; + private static int getStateAsInt(ScannerState state) { + return state.ordinal(); } @Override - public int getBufferEnd() { - return endOffset; + public String toString() { + return "QuteLexer for " + scanner.getClass().getName(); } + } diff --git a/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteTokenType.java b/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteTokenType.java new file mode 100644 index 000000000..935bfa92f --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteTokenType.java @@ -0,0 +1,26 @@ +package com.redhat.devtools.intellij.qute.lang; + +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.xml.IXmlLeafElementType; + +public interface QuteTokenType { + + IElementType QUTE_CONTENT = new IXmlLeafElementType("QUTE_CONTENT"); + + IElementType QUTE_START_PARAMETER_DECLARATION = new QuteElementType("QUTE_START_PARAMETER_DECLARATION"); + + IElementType QUTE_END_PARAMETER_DECLARATION = new QuteElementType("QUTE_END_PARAMETER_DECLARATION"); + + IElementType QUTE_START_EXPRESSION = new QuteElementType("QUTE_START_EXPRESSION"); + + IElementType QUTE_END_EXPRESSION = new QuteElementType("QUTE_END_EXPRESSION"); + + IElementType QUTE_START_TAG = new QuteElementType("QUTE_START_TAG"); + IElementType QUTE_END_TAG = new QuteElementType("QUTE_END_TAG"); + IElementType QUTE_END_TAG_SELF_CLOSE = new QuteElementType("QUTE_END_TAG_SELF_CLOSE"); + IElementType QUTE_END_TAG_OPEN = new QuteElementType("QUTE_END_TAG_OPEN"); + IElementType QUTE_END_TAG_CLOSE = new QuteElementType("QUTE_END_TAG_CLOSE"); + IElementType QUTE_START_TAG_OPEN = new QuteElementType("QUTE_START_TAG_OPEN"); + IElementType QUTE_WHITESPACE = new QuteElementType("QUTE_WHITESPACE"); + IElementType QUTE_PARAMETER_TAG = new QuteElementType("QUTE_PARAMETER_TAG"); +} diff --git a/src/main/resources/META-INF/lsp4ij-qute.xml b/src/main/resources/META-INF/lsp4ij-qute.xml index 926de215b..8dd6166ac 100644 --- a/src/main/resources/META-INF/lsp4ij-qute.xml +++ b/src/main/resources/META-INF/lsp4ij-qute.xml @@ -42,6 +42,7 @@ implementationClass="com.redhat.devtools.intellij.lsp4ij.operations.diagnostics.LSPDiagnosticAnnotator"/> +