resolved = resolveDocumentation(doc, caretOffset);
- if (resolved != null) {
- resultSet.setDocumentation(new CompletionDocumentation() {
- @Override
- public String getText() {
- String[] both = resolved.get();
- String detail = both[0];
- String content = both[1];
-
- StringBuilder documentation = new StringBuilder();
- documentation.append("\n");
- if (detail != null) {
- documentation.append("").append(CompletionProviderImpl.escape(detail)).append("");
- documentation.append("\n");
- }
- if (content != null) {
- documentation.append(content);
- }
- return documentation.toString();
- }
-
- @Override
- public URL getURL() {
- return null;
- }
-
- @Override
- public CompletionDocumentation resolveLink(String link) {
- return null;
- }
-
- @Override
- public Action getGotoSourceAction() {
- return null;
- }
- });
- }
- resultSet.finish();
- }
- });
- }
-
- @Override
- public CompletionTask createToolTipTask() {
- return null;
- }
-
- @Override
- public boolean instantSubstitution(JTextComponent jtc) {
- return false;
- }
-
- @Override
- public int getSortPriority() {
- return 100;
- }
-
- @Override
- public CharSequence getSortText() {
- return sortText;
- }
-
- @Override
- public CharSequence getInsertPrefix() {
- return insert;
- }
-}
diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/CompletionProviderImpl.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/CompletionProviderImpl.java
index 8a6066485cb6..d4eb07445fc7 100644
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/CompletionProviderImpl.java
+++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/CompletionProviderImpl.java
@@ -18,38 +18,56 @@
*/
package org.netbeans.modules.lsp.client.bindings;
+import com.vladsch.flexmark.html.HtmlRenderer;
+import com.vladsch.flexmark.parser.Parser;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.event.KeyEvent;
+import java.net.URL;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
+import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JToolTip;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
+import javax.swing.text.StyledDocument;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemKind;
import org.eclipse.lsp4j.CompletionList;
import org.eclipse.lsp4j.CompletionOptions;
import org.eclipse.lsp4j.CompletionParams;
import org.eclipse.lsp4j.InitializeResult;
+import org.eclipse.lsp4j.InsertReplaceEdit;
+import org.eclipse.lsp4j.MarkupContent;
import org.eclipse.lsp4j.ParameterInformation;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.SignatureHelp;
import org.eclipse.lsp4j.SignatureHelpParams;
import org.eclipse.lsp4j.SignatureInformation;
import org.eclipse.lsp4j.TextDocumentIdentifier;
+import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
+import org.netbeans.api.editor.completion.Completion;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.editor.BaseDocument;
+import org.netbeans.editor.Utilities;
import org.netbeans.modules.editor.NbEditorUtilities;
import org.netbeans.modules.lsp.client.LSPBindings;
import org.netbeans.modules.lsp.client.Utils;
+import org.netbeans.spi.editor.completion.CompletionDocumentation;
import org.netbeans.spi.editor.completion.CompletionProvider;
import org.netbeans.spi.editor.completion.CompletionResultSet;
import org.netbeans.spi.editor.completion.CompletionTask;
import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery;
import org.netbeans.spi.editor.completion.support.AsyncCompletionTask;
+import org.netbeans.spi.editor.completion.support.CompletionUtilities;
import org.openide.filesystems.FileObject;
+import org.openide.text.NbDocument;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.xml.XMLUtil;
@@ -166,9 +184,172 @@ protected void query(CompletionResultSet resultSet, Document doc, int caretOffse
CompletionItemKind kind = i.getKind();
Icon ic = Icons.getCompletionIcon(kind);
ImageIcon icon = new ImageIcon(ImageUtilities.icon2Image(ic));
- resultSet.addItem(new LspCompletionItem(i, doc, caretOffset, server, leftLabel, rightLabel, icon, sortText, insert, this, org.netbeans.modules.lsp.client.bindings.CompletionProviderImpl.this));
+ resultSet.addItem(new org.netbeans.spi.editor.completion.CompletionItem() {
+ @Override
+ public void defaultAction(JTextComponent jtc) {
+ commit("");
+ }
+ private void commit(String appendText) {
+ Either edit = i.getTextEdit();
+ if (edit != null && edit.isRight()) {
+ //TODO: the NetBeans client does not current support InsertReplaceEdits, should not happen
+ Completion.get().hideDocumentation();
+ Completion.get().hideCompletion();
+ return ;
+ }
+ TextEdit te = edit != null ? edit.getLeft() : null;
+ NbDocument.runAtomic((StyledDocument) doc, () -> {
+ try {
+ int endPos;
+ if (te != null) {
+ int start = Utils.getOffset(doc, te.getRange().getStart());
+ int end = Utils.getOffset(doc, te.getRange().getEnd());
+ doc.remove(start, end - start);
+ doc.insertString(start, te.getNewText(), null);
+ endPos = start + te.getNewText().length();
+ } else {
+ String toAdd = i.getInsertText();
+ if (toAdd == null) {
+ toAdd = i.getLabel();
+ }
+ int[] identSpan = Utilities.getIdentifierBlock((BaseDocument) doc, caretOffset);
+ if (identSpan != null) {
+ doc.remove(identSpan[0], identSpan[1] - identSpan[0]);
+ doc.insertString(identSpan[0], toAdd, null);
+ endPos = identSpan[0] + toAdd.length();
+ } else {
+ doc.insertString(caretOffset, toAdd, null);
+ endPos = caretOffset + toAdd.length();
+ }
+ }
+ doc.insertString(endPos, appendText, null);
+ } catch (BadLocationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ });
+ Completion.get().hideDocumentation();
+ Completion.get().hideCompletion();
+ }
+
+ @Override
+ public void processKeyEvent(KeyEvent ke) {
+ if (ke.getID() == KeyEvent.KEY_TYPED) {
+ String commitText = String.valueOf(ke.getKeyChar());
+ List commitCharacters = i.getCommitCharacters();
+
+ if (commitCharacters != null && commitCharacters.contains(commitText)) {
+ commit(commitText);
+ ke.consume();
+ if (isTriggerCharacter(server, commitText)) {
+ Completion.get().showCompletion();
+ }
+ }
+ }
+ }
+
+ @Override
+ public int getPreferredWidth(Graphics grphcs, Font font) {
+ return CompletionUtilities.getPreferredWidth(leftLabel, rightLabel, grphcs, font);
+ }
+
+ @Override
+ public void render(Graphics grphcs, Font font, Color color, Color color1, int i, int i1, boolean bln) {
+ CompletionUtilities.renderHtml(icon, leftLabel, rightLabel, grphcs, font, color, i, i1, bln);
+ }
+
+ @Override
+ public CompletionTask createDocumentationTask() {
+ return new AsyncCompletionTask(new AsyncCompletionQuery() {
+ @Override
+ protected void query(CompletionResultSet resultSet, Document doc, int caretOffset) {
+ CompletionItem resolved;
+ if ((i.getDetail() == null || i.getDocumentation() == null) && hasCompletionResolve(server)) {
+ CompletionItem temp;
+ try {
+ temp = server.getTextDocumentService().resolveCompletionItem(i).get();
+ } catch (InterruptedException | ExecutionException ex) {
+ Exceptions.printStackTrace(ex);
+ temp = i;
+ }
+ resolved = temp;
+ } else {
+ resolved = i;
+ }
+ if (resolved.getDocumentation() != null || resolved.getDetail() != null) {
+ resultSet.setDocumentation(new CompletionDocumentation() {
+ @Override
+ public String getText() {
+ StringBuilder documentation = new StringBuilder();
+ documentation.append("\n");
+ if (resolved.getDetail() != null) {
+ documentation.append("").append(escape(resolved.getDetail())).append("");
+ documentation.append("\n");
+ }
+ if (resolved.getDocumentation() != null) {
+ MarkupContent content;
+ if (resolved.getDocumentation().isLeft()) {
+ content = new MarkupContent();
+ content.setKind("plaintext");
+ content.setValue(resolved.getDocumentation().getLeft());
+ } else {
+ content = resolved.getDocumentation().getRight();
+ }
+ switch (content.getKind()) {
+ default:
+ case "plaintext": documentation.append("
\n").append(content.getValue()).append("\n
"); break;
+ case "markdown": documentation.append(HtmlRenderer.builder().build().render(Parser.builder().build().parse(content.getValue()))); break;
+ }
+ }
+ return documentation.toString();
+ }
+ @Override
+ public URL getURL() {
+ return null;
+ }
+ @Override
+ public CompletionDocumentation resolveLink(String link) {
+ return null;
+ }
+ @Override
+ public Action getGotoSourceAction() {
+ return null;
+ }
+ });
+ }
+ resultSet.finish();
+ }
+ });
+ }
+
+ @Override
+ public CompletionTask createToolTipTask() {
+ return null;
+ }
+
+ @Override
+ public boolean instantSubstitution(JTextComponent jtc) {
+ return false;
+ }
+
+ @Override
+ public int getSortPriority() {
+ return 100;
+ }
+
+ @Override
+ public CharSequence getSortText() {
+ return sortText;
+ }
+
+ @Override
+ public CharSequence getInsertPrefix() {
+ return insert;
+ }
+ });
}
- } catch (BadLocationException | InterruptedException | ExecutionException ex) {
+ } catch (BadLocationException | InterruptedException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (ExecutionException ex) {
Exceptions.printStackTrace(ex);
} finally {
resultSet.finish();
@@ -176,19 +357,17 @@ protected void query(CompletionResultSet resultSet, Document doc, int caretOffse
}
}, component);
}
-
- final boolean hasCompletionResolve(LSPBindings server) {
+
+ private boolean hasCompletionResolve(LSPBindings server) {
ServerCapabilities capabilities = server.getInitResult().getCapabilities();
- if (capabilities == null) {
- return false;
- }
+ if (capabilities == null) return false;
CompletionOptions completionProvider = capabilities.getCompletionProvider();
if (completionProvider == null) return false;
Boolean resolveProvider = completionProvider.getResolveProvider();
return resolveProvider != null && resolveProvider;
}
- static String escape(String s) {
+ private static String escape(String s) {
if (s != null) {
try {
return XMLUtil.toAttributeValue(s);
@@ -214,8 +393,8 @@ public int getAutoQueryTypes(JTextComponent component, String typedText) {
}
return isTriggerCharacter(server, typedText) ? COMPLETION_QUERY_TYPE : 0;
}
-
- boolean isTriggerCharacter(LSPBindings server, String text) {
+
+ private boolean isTriggerCharacter(LSPBindings server, String text) {
InitializeResult init = server.getInitResult();
if (init == null) return false;
ServerCapabilities capabilities = init.getCapabilities();
diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/ErrorProviderBridge.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/ErrorProviderBridge.java
deleted file mode 100644
index cf6778f073d1..000000000000
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/ErrorProviderBridge.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.netbeans.modules.lsp.client.bindings;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import javax.swing.text.Document;
-import org.netbeans.api.lsp.Diagnostic;
-import org.netbeans.spi.editor.hints.ErrorDescription;
-import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
-import org.netbeans.spi.editor.hints.HintsController;
-import org.netbeans.spi.editor.hints.Severity;
-import org.netbeans.spi.lsp.ErrorProvider;
-import org.openide.filesystems.FileObject;
-import org.openide.util.RequestProcessor;
-import org.openide.util.WeakListeners;
-
-class ErrorProviderBridge implements Runnable, DocumentListener {
-
- private final FileObject file;
- private final RequestProcessor.Task task;
- private final Collection extends ErrorProvider> errorProviders;
- private final DocumentListener listener;
-
- ErrorProviderBridge(Document doc, FileObject file, Collection extends ErrorProvider> errorProviders, RequestProcessor rp) {
- this.file = file;
- this.errorProviders = errorProviders;
- this.task = rp.create(this);
- this.listener = WeakListeners.create(DocumentListener.class, this, doc);
- doc.addDocumentListener(listener);
- }
-
- final void start() {
- task.schedule(0);
- }
-
- final void waitFinished() {
- task.waitFinished();
- }
-
- @Override
- public final void run() {
- for (ErrorProvider p : errorProviders) {
- computeHints(ErrorProvider.Kind.ERRORS, p, "lsp:errors");
- computeHints(ErrorProvider.Kind.HINTS, p, "lsp:hints");
- }
- }
-
- private void computeHints(final ErrorProvider.Kind type, ErrorProvider p, final String prefix) {
- List arr = new ArrayList<>();
- ErrorProvider.Context errorCtx = new ErrorProvider.Context(file, type);
- List extends Diagnostic> errors = p.computeErrors(errorCtx);
- if (errors != null) {
- for (Diagnostic e : errors) {
- final Severity s;
- switch(e.getSeverity()) {
- case Error:
- s = Severity.ERROR; break;
- case Warning:
- s = Severity.WARNING; break;
- case Information:
- case Hint:
- default:
- s = Severity.HINT; break;
- }
- ErrorDescription descr = ErrorDescriptionFactory.createErrorDescription(s,
- e.getDescription(),
- file,
- e.getStartPosition().getOffset(),
- e.getEndPosition().getOffset()
- );
- arr.add(descr);
- }
- applyHints(prefix, p, arr);
- }
- }
-
- protected void applyHints(final String prefix, ErrorProvider p, List arr) {
- HintsController.setErrors(file, prefix + ":" + p.getClass().getName(), arr);
- }
-
- @Override
- public final void insertUpdate(DocumentEvent e) {
- start();
- }
-
- @Override
- public final void removeUpdate(DocumentEvent e) {
- start();
- }
-
- @Override
- public final void changedUpdate(DocumentEvent e) {
- start();
- }
-}
diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/Icons.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/Icons.java
index ef7e909403c8..68e68c5176a9 100644
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/Icons.java
+++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/Icons.java
@@ -41,7 +41,7 @@ public final class Icons {
private Icons() {
}
- public static Icon getCompletionIcon(Enum> completionKind) {
+ public static Icon getCompletionIcon(CompletionItemKind completionKind) {
Image img = null;
if (completionKind != null) {
diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LspCompletionItem.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LspCompletionItem.java
deleted file mode 100644
index 606d413faab5..000000000000
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LspCompletionItem.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.netbeans.modules.lsp.client.bindings;
-
-import com.vladsch.flexmark.html.HtmlRenderer;
-import com.vladsch.flexmark.parser.Parser;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.function.Supplier;
-import javax.swing.ImageIcon;
-import javax.swing.text.Document;
-import org.eclipse.lsp4j.InsertReplaceEdit;
-import org.eclipse.lsp4j.MarkupContent;
-import org.eclipse.lsp4j.TextEdit;
-import org.eclipse.lsp4j.jsonrpc.messages.Either;
-import org.netbeans.modules.lsp.client.LSPBindings;
-import org.netbeans.modules.lsp.client.Utils;
-import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery;
-import org.openide.util.Exceptions;
-
-final class LspCompletionItem extends AbstractCompletionItem> {
- private final org.eclipse.lsp4j.CompletionItem i;
- private final LSPBindings server;
- private final AsyncCompletionQuery outer;
- private final CompletionProviderImpl cp;
-
- public LspCompletionItem(
- org.eclipse.lsp4j.CompletionItem i,
- Document doc, int caretOffset, LSPBindings server,
- String leftLabel, String rightLabel, ImageIcon icon, String sortText,
- String insert,
- AsyncCompletionQuery outer, CompletionProviderImpl cp
- ) {
- super(doc, caretOffset, leftLabel, rightLabel, icon, sortText, insert);
- this.cp = cp;
- this.outer = outer;
- this.i = i;
- this.server = server;
- }
-
- @Override
- Either findEdit(boolean[] hideImmediately) {
- Either edit = i.getTextEdit();
- if (edit != null && edit.isRight()) {
- //TODO: the NetBeans client does not currently support InsertReplaceEdits, should not happen
- hideImmediately[0] = true;
- return null;
- }
- return edit;
- }
-
- @Override
- boolean isTextEdit(Either edit) {
- return edit != null && edit.getLeft() != null;
- }
-
- @Override
- int findStart(Document doc, Either te) {
- return Utils.getOffset(doc, te.getLeft().getRange().getStart());
- }
-
- @Override
- int findEnd(Document doc, Either te) {
- return Utils.getOffset(doc, te.getLeft().getRange().getEnd());
- }
-
- @Override
- String findNewText(Either te) {
- return te.getLeft().getNewText();
- }
-
- @Override
- List getCommitCharacters() {
- return i.getCommitCharacters();
- }
-
- @Override
- boolean isTriggerCharacter(String commitText) {
- return cp.isTriggerCharacter(server, commitText);
- }
-
- @Override
- Supplier resolveDocumentation(Document doc, int caretOffset) {
- org.eclipse.lsp4j.CompletionItem resolved;
- if ((i.getDetail() == null || i.getDocumentation() == null) && cp.hasCompletionResolve(server)) {
- org.eclipse.lsp4j.CompletionItem temp;
- try {
- temp = server.getTextDocumentService().resolveCompletionItem(i).get();
- } catch (InterruptedException | ExecutionException ex) {
- Exceptions.printStackTrace(ex);
- temp = i;
- }
- resolved = temp;
- } else {
- resolved = i;
- }
- if (resolved.getDocumentation() != null || resolved.getDetail() != null) {
- return () -> {
- String txt;
- if (resolved.getDocumentation() != null) {
- MarkupContent content;
- if (resolved.getDocumentation().isLeft()) {
- content = new MarkupContent();
- content.setKind("plaintext");
- content.setValue(resolved.getDocumentation().getLeft());
- } else {
- content = resolved.getDocumentation().getRight();
- }
- switch (content.getKind()) {
- case "markdown":
- txt = HtmlRenderer.builder().build().render(Parser.builder().build().parse(content.getValue()));
- break;
- default:
- txt = "\n" + content.getValue() + "\n
";
- break;
- }
- } else {
- txt = null;
- }
- return new String[] { resolved.getDetail(), txt };
- };
- } else {
- return null;
- }
- }
-}
diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LspCompletionProviderImpl.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LspCompletionProviderImpl.java
deleted file mode 100644
index 36444e3d5f19..000000000000
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LspCompletionProviderImpl.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.netbeans.modules.lsp.client.bindings;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import javax.swing.Icon;
-import javax.swing.ImageIcon;
-import javax.swing.text.Document;
-import javax.swing.text.JTextComponent;
-import org.netbeans.api.editor.mimelookup.MimeLookup;
-import org.netbeans.api.editor.mimelookup.MimeRegistration;
-import org.netbeans.api.lsp.TextEdit;
-import org.netbeans.modules.editor.NbEditorUtilities;
-import org.netbeans.spi.editor.completion.CompletionProvider;
-import org.netbeans.spi.editor.completion.CompletionResultSet;
-import org.netbeans.spi.editor.completion.CompletionTask;
-import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery;
-import org.netbeans.spi.editor.completion.support.AsyncCompletionTask;
-import org.netbeans.spi.lsp.CompletionCollector;
-import org.openide.filesystems.FileObject;
-import org.openide.util.ImageUtilities;
-import org.openide.util.Lookup;
-
-@MimeRegistration(mimeType = "", service = CompletionProvider.class)
-public class LspCompletionProviderImpl implements CompletionProvider {
-
- @Override
- public CompletionTask createTask(int queryType, JTextComponent component) {
- return new AsyncCompletionTask(new AsyncCompletionQuery() {
- @Override
- protected void query(CompletionResultSet resultSet, Document doc, int caretOffset) {
- FileObject file = NbEditorUtilities.getFileObject(doc);
- if (file == null) {
- //TODO: beep
- resultSet.finish();
- return;
- }
- final String mime = file.getMIMEType();
- for (Lookup.Item item : MimeLookup.getLookup(mime).lookupResult(CompletionProvider.class).allItems()) {
- String id = item.getId();
- if (id.startsWith("Editors/"+ mime)) {
- // found real CompletionProvider - don't bridge LSP API
- resultSet.finish();
- return;
- }
- }
- Consumer consumer = (i) -> {
- String insert = i.getInsertText() != null ? i.getInsertText() : i.getLabel();
- String leftLabel = encode(i.getLabel());
- String rightLabel = null;
- try {
- if (i.getDetail() != null) {
- rightLabel = encode(i.getDetail().get());
- }
- } catch (InterruptedException | ExecutionException interruptedException) {
- // leave null
- }
- String sortText = i.getSortText() != null ? i.getSortText() : i.getLabel();
- org.netbeans.api.lsp.Completion.Kind kind = i.getKind();
- Icon ic = Icons.getCompletionIcon(kind);
- ImageIcon icon = new ImageIcon(ImageUtilities.icon2Image(ic));
- resultSet.addItem(new LspApiCompletionItem(i, doc, caretOffset, leftLabel, rightLabel, icon, sortText, insert));
- };
- org.netbeans.api.lsp.Completion.Context context = new org.netbeans.api.lsp.Completion.Context(org.netbeans.api.lsp.Completion.TriggerKind.Invoked, null);
- for (CompletionCollector cc : MimeLookup.getLookup(mime).lookupAll(CompletionCollector.class)) {
- cc.collectCompletions(doc, caretOffset, context, consumer);
- }
- resultSet.finish();
- }
- }, component);
- }
-
- private String encode(String str) {
- return str.replace("&", "&")
- .replace("<", "<");
- }
-
- @Override
- public int getAutoQueryTypes(JTextComponent component, String typedText) {
- FileObject file = NbEditorUtilities.getFileObject(component.getDocument());
- if (file == null) {
- return 0;
- }
- return 0;
- }
-
- private static class LspApiCompletionItem extends AbstractCompletionItem {
-
- private final org.netbeans.api.lsp.Completion i;
-
- public LspApiCompletionItem(org.netbeans.api.lsp.Completion i, Document doc, int caretOffset, String leftLabel, String rightLabel, ImageIcon icon, String sortText, String insert) {
- super(doc, caretOffset, leftLabel, rightLabel, icon, sortText, insert);
- this.i = i;
- }
-
- @Override
- TextEdit findEdit(boolean[] hideNow) {
- return i.getTextEdit();
- }
-
- @Override
- boolean isTextEdit(TextEdit te) {
- return te != null;
- }
-
- @Override
- int findStart(Document doc, TextEdit te) {
- return te.getStartOffset();
- }
-
- @Override
- int findEnd(Document doc, TextEdit te) {
- return te.getEndOffset();
- }
-
- @Override
- String findNewText(TextEdit te) {
- return te.getNewText();
- }
-
- @Override
- List getCommitCharacters() {
- return i.getCommitCharacters().stream().map(String::valueOf).collect(Collectors.toList());
- }
-
- @Override
- boolean isTriggerCharacter(String commitText) {
- return false;
- }
-
- @Override
- Supplier resolveDocumentation(Document doc, int caretOffset) {
- if (i.getDetail() == null && i.getDocumentation() == null) {
- return null;
- } else {
- return () -> {
- String detail = null;
- String documentation = null;
- try {
- if (i.getDetail() != null) {
- detail = i.getDetail().get();
- }
- } catch (InterruptedException | ExecutionException interruptedException) {
- // leave null
- }
- try {
- if (i.getDocumentation() != null) {
- documentation = i.getDocumentation().get();
- }
- } catch (InterruptedException | ExecutionException interruptedException) {
- // leave null
- }
- return new String[]{detail, documentation};
- };
- }
- }
- }
-}
diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/NavigatorPanelImpl.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/NavigatorPanelImpl.java
index c03162f7fbd9..bde41feae455 100644
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/NavigatorPanelImpl.java
+++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/NavigatorPanelImpl.java
@@ -18,13 +18,19 @@
*/
package org.netbeans.modules.lsp.client.bindings;
+import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.DocumentSymbolParams;
import org.eclipse.lsp4j.Range;
@@ -34,10 +40,17 @@
import org.netbeans.modules.lsp.client.LSPBindings;
import org.netbeans.modules.lsp.client.LSPBindings.BackgroundTask;
import org.netbeans.modules.lsp.client.Utils;
+import org.netbeans.spi.navigator.NavigatorPanel;
+import org.openide.explorer.ExplorerManager;
+import org.openide.explorer.view.BeanTreeView;
import org.openide.filesystems.FileObject;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
+import org.openide.util.Lookup;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.NbBundle.Messages;
/**
*
diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/TextDocumentSyncServerCapabilityHandler.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/TextDocumentSyncServerCapabilityHandler.java
index 496828357f67..2659afddcf67 100644
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/TextDocumentSyncServerCapabilityHandler.java
+++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/TextDocumentSyncServerCapabilityHandler.java
@@ -20,7 +20,6 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
@@ -48,24 +47,16 @@
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.netbeans.api.editor.EditorRegistry;
-import org.netbeans.api.editor.mimelookup.MimeLookup;
-import org.netbeans.api.lsp.Diagnostic;
import org.netbeans.editor.BaseDocumentEvent;
import org.netbeans.lib.editor.util.swing.DocumentUtilities;
import org.netbeans.modules.editor.*;
import org.netbeans.modules.lsp.client.LSPBindings;
import org.netbeans.modules.lsp.client.Utils;
-import org.netbeans.spi.editor.hints.ErrorDescription;
-import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
-import org.netbeans.spi.editor.hints.HintsController;
-import org.netbeans.spi.editor.hints.Severity;
-import org.netbeans.spi.lsp.ErrorProvider;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.modules.OnStart;
import org.openide.text.NbDocument;
import org.openide.util.Exceptions;
-import org.openide.util.Lookup;
import org.openide.util.RequestProcessor;
/**
@@ -331,16 +322,8 @@ private void registerBackgroundTasks(JTextComponent c) {
LSPBindings server = LSPBindings.getBindings(file);
- if (server == null) {
- Lookup lkp = MimeLookup.getLookup(file.getMIMEType());
- Collection extends ErrorProvider> errorProviders = lkp.lookupAll(ErrorProvider.class);
- if (!errorProviders.isEmpty()) {
- ErrorProviderBridge b = new ErrorProviderBridge(doc, file, errorProviders, WORKER);
- b.start();
- c.putClientProperty(ErrorProviderBridge.class, b);
- }
- return;
- }
+ if (server == null)
+ return ; //ignore
SwingUtilities.invokeLater(() -> {
if (c.getClientProperty(MarkOccurrences.class) == null) {
diff --git a/ide/lsp.client/test/unit/src/org/netbeans/modules/lsp/client/bindings/ErrorProviderBridgeTest.java b/ide/lsp.client/test/unit/src/org/netbeans/modules/lsp/client/bindings/ErrorProviderBridgeTest.java
deleted file mode 100644
index 287ed3dde392..000000000000
--- a/ide/lsp.client/test/unit/src/org/netbeans/modules/lsp/client/bindings/ErrorProviderBridgeTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.netbeans.modules.lsp.client.bindings;
-
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import javax.swing.JTextArea;
-import javax.swing.text.BadLocationException;
-import javax.swing.text.Document;
-import javax.swing.text.JTextComponent;
-import org.junit.Test;
-import static org.junit.Assert.*;
-import org.netbeans.api.lsp.Diagnostic;
-import org.netbeans.junit.NbTestCase;
-import org.netbeans.spi.editor.hints.ErrorDescription;
-import org.netbeans.spi.lsp.ErrorProvider;
-import org.openide.filesystems.FileObject;
-import org.openide.filesystems.FileUtil;
-import org.openide.util.RequestProcessor;
-
-public class ErrorProviderBridgeTest {
-
- public ErrorProviderBridgeTest() {
- }
-
- @Test
- public void testListeningAndLifecycle() throws Exception {
- JTextComponent c = new JTextArea();
- FileObject file = FileUtil.createMemoryFileSystem().getRoot().createData("c.txt");
- RequestProcessor rp = new RequestProcessor("ErrorProviderBridgeTest");
- MockErrorProvider mp = new MockErrorProvider(c);
-
- List> appliedDescriptions = new ArrayList<>();
- ErrorProviderBridge b = new ErrorProviderBridge(c.getDocument(), file, Collections.singleton(mp), rp) {
- @Override
- protected void applyHints(String prefix, org.netbeans.spi.lsp.ErrorProvider p, List arr) {
- if (prefix.equals("lsp:errors")) {
- appliedDescriptions.add(arr);
- }
- }
- };
-
- b.start();
- b.waitFinished();
-
- assertEquals("One set of errors reported", 1, appliedDescriptions.size());
- assertTrue("It is empty so far", appliedDescriptions.remove(0).isEmpty());
-
- c.getDocument().insertString(0, "Ahoj\nERR\nOK", null);
- b.waitFinished();
-
- {
- assertEquals("Another set of errors reported", 1, appliedDescriptions.size());
- final List errors = appliedDescriptions.remove(0);
- assertEquals("There is one error", 1, errors.size());
- ErrorDescription descr = errors.get(0);
- assertEquals("Starts right", 5, descr.getRange().getBegin().getOffset());
- assertEquals("Ends right", 8, descr.getRange().getEnd().getOffset());
- }
-
- c.getDocument().remove(0, 5);
- b.waitFinished();
-
- {
- assertEquals("Yet another set of errors reported", 1, appliedDescriptions.size());
- final List errors = appliedDescriptions.remove(0);
- assertEquals("There is one error", 1, errors.size());
- ErrorDescription descr = errors.get(0);
- assertEquals("Starts right", 0, descr.getRange().getBegin().getOffset());
- assertEquals("Ends right", 3, descr.getRange().getEnd().getOffset());
- }
-
- Reference