Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: HTML completion / autoclose is broken when offset is inside a Qute section #954

Merged
merged 1 commit into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ public int getPrefixCompletionStart(Document document, int completionOffset) {
@NotNull
@Override
public String getLookupString() {
String lookup = StringUtils.isNotBlank(item.getSortText())?item.getSortText():item.getLabel();
String lookup = StringUtils.isNotBlank(item.getFilterText())?item.getFilterText():item.getLabel();
if (lookup.charAt(0) == '@') {
return lookup.substring(1);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
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;

/**
* Provides the capability to open completion anywhere.
*/
public class LSPCompletionConfidence extends CompletionConfidence {

@Override
public @NotNull ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) {
return ThreeState.NO;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.lsp4ij.operations.highlight;

import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.PsiElementBase;
import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils;
import org.eclipse.lsp4j.DocumentHighlight;
import org.eclipse.lsp4j.DocumentHighlightKind;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Implement a fake {@link PsiElement} which stores the required text edit (coming from Language server) to highlight.
*
* This class provides the capability to highlight part of code by using Language server TextEdit and not by using the PsiElement.
*/
public class LSPHighlightPsiElement extends PsiElementBase {

private final TextRange textRange;
private final DocumentHighlightKind kind;

public LSPHighlightPsiElement(TextRange textRange, DocumentHighlightKind kind) {
this.textRange = textRange;
this.kind = kind;
}

public DocumentHighlightKind getKind() {
return kind;
}

@Override
public @NotNull Language getLanguage() {
return null;
}

@Override
public PsiElement @NotNull [] getChildren() {
return new PsiElement[0];
}

@Override
public PsiElement getParent() {
return null;
}

@Override
public TextRange getTextRange() {
return textRange;
}

@Override
public int getStartOffsetInParent() {
return 0;
}

@Override
public int getTextLength() {
return 0;
}

@Override
public @Nullable PsiElement findElementAt(int offset) {
return null;
}

@Override
public int getTextOffset() {
return 0;
}

@Override
public @NlsSafe String getText() {
return null;
}

@Override
public char @NotNull [] textToCharArray() {
return new char[0];
}

@Override
public ASTNode getNode() {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,41 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.Consumer;
import org.eclipse.lsp4j.DocumentHighlightKind;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.logging.Logger;

public class LSPHighlightUsagesHandler extends HighlightUsagesHandlerBase<PsiElement> {
public class LSPHighlightUsagesHandler extends HighlightUsagesHandlerBase<LSPHighlightPsiElement> {
private static final Logger LOGGER = Logger.getLogger(LSPHighlightUsagesHandler.class.getName());
private final List<PsiElement> targets;
private final List<LSPHighlightPsiElement> targets;

public LSPHighlightUsagesHandler(Editor editor, PsiFile file, List<PsiElement> targets) {
public LSPHighlightUsagesHandler(Editor editor, PsiFile file, List<LSPHighlightPsiElement> targets) {
super(editor, file);
this.targets = targets;
}

@Override
public @NotNull List<PsiElement> getTargets() {
public @NotNull List<LSPHighlightPsiElement> getTargets() {
return targets;
}

@Override
protected void selectTargets(@NotNull List<? extends PsiElement> targets,
@NotNull Consumer<? super List<? extends PsiElement>> selectionConsumer) {
protected void selectTargets(@NotNull List<? extends LSPHighlightPsiElement> targets,
@NotNull Consumer<? super List<? extends LSPHighlightPsiElement>> selectionConsumer) {
selectionConsumer.consume(targets);
}

@Override
public void computeUsages(@NotNull List<? extends PsiElement> targets) {
targets.forEach(target -> myReadUsages.add(target.getTextRange()));
public void computeUsages(@NotNull List<? extends LSPHighlightPsiElement> targets) {
targets.forEach(target ->
{
if (target.getKind() == DocumentHighlightKind.Read) {
myReadUsages.add(target.getTextRange());
} else {
myWriteUsages.add(target.getTextRange());
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactory;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils;
Expand Down Expand Up @@ -43,12 +45,12 @@ public class LSPHighlightUsagesHandlerFactory implements HighlightUsagesHandlerF

@Override
public @Nullable HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile file) {
List<PsiElement> targets = getTargets(editor, file);
List<LSPHighlightPsiElement> targets = getTargets(editor, file);
return targets.isEmpty()?null:new LSPHighlightUsagesHandler(editor, file, targets);
}

private List<PsiElement> getTargets(Editor editor, PsiFile file) {
List<PsiElement> elements = new ArrayList<>();
private List<LSPHighlightPsiElement> getTargets(Editor editor, PsiFile file) {
List<LSPHighlightPsiElement> elements = new ArrayList<>();
try {
int offset = TargetElementUtil.adjustOffset(file, editor.getDocument(), editor.getCaretModel().getOffset());
Document document = editor.getDocument();
Expand Down Expand Up @@ -76,13 +78,14 @@ private List<PsiElement> getTargets(Editor editor, PsiFile file) {
ProgressManager.checkCanceled();
DocumentHighlight highlight = highlights.poll(25, TimeUnit.MILLISECONDS);
if (highlight != null) {
int highlightOffset = LSPIJUtils.toOffset(highlight.getRange().getStart(), document);
PsiElement element = file.findElementAt(highlightOffset);
if (element != null) {
elements.add(element);
TextRange textRange = LSPIJUtils.toTextRange(highlight.getRange(), document);
if (textRange != null) {
elements.add(new LSPHighlightPsiElement(textRange, highlight.getKind()));
}
}
}
} catch (ProcessCanceledException cancellation){
throw cancellation;
} catch (InterruptedException e) {
LOGGER.log(Level.WARNING, e, e::getLocalizedMessage);
}
Expand Down
45 changes: 45 additions & 0 deletions src/main/java/com/redhat/devtools/intellij/qute/QuteBundle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.qute;

import com.intellij.DynamicBundle;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;

import java.util.function.Supplier;

/**
* Qute messages bundle.
*/
public final class QuteBundle extends DynamicBundle {

@NonNls public static final String BUNDLE = "messages.QuteBundle";
private static final QuteBundle INSTANCE = new QuteBundle();

private QuteBundle() {
super(BUNDLE);
}

@NotNull
public static @Nls String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) {
return INSTANCE.getMessage(key, params);
}

@NotNull
public static Supplier<@Nls String> messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) {
return INSTANCE.getLazyMessage(key, params);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.qute.lang;

import com.intellij.lang.ASTFactory;
import com.intellij.psi.impl.source.tree.LeafElement;
import com.intellij.psi.templateLanguages.OuterLanguageElementImpl;
import com.intellij.psi.tree.IElementType;
import com.redhat.devtools.intellij.qute.lang.psi.QuteToken;
import com.redhat.devtools.intellij.qute.lang.psi.QuteElementTypes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Qute AST factory.
*/
public class QuteASTFactory extends ASTFactory {

@Override
public @Nullable LeafElement createLeaf(@NotNull IElementType type, @NotNull CharSequence text) {
if (type == QuteElementTypes.QUTE_OUTER_ELEMENT_TYPE) {
// HTML, YAML, etc content
return new OuterLanguageElementImpl(type, text);
}
// Qute content
return new QuteToken(type, text);
}
}
Loading