Skip to content
This repository has been archived by the owner on Mar 1, 2024. It is now read-only.

Commit

Permalink
Merge pull request #78 from eclipse/master
Browse files Browse the repository at this point in the history
Extension completion should use node text range
  • Loading branch information
enxio authored Sep 3, 2020
2 parents 5a3d97e + d2d5bb7 commit 65f63d1
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.dom.DOMElement;
import org.eclipse.lemminx.dom.DOMNode;
import org.eclipse.lemminx.dom.DOMText;
import org.eclipse.lemminx.dom.DTDDeclParameter;
import org.eclipse.lemminx.dom.parser.Scanner;
import org.eclipse.lemminx.dom.parser.ScannerState;
Expand All @@ -53,6 +54,7 @@
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.w3c.dom.Node;

/**
* XML completions support.
Expand Down Expand Up @@ -135,12 +137,11 @@ public CompletionList doComplete(DOMDocument xmlDocument, Position position, Sha

if (DOMNode.isIncluded(systemId, offset)) {
/**
* Completion invoked within systemId parameter
* ie, completion offset is at | like so:
* <!DOCTYPE foo SYSTEM "./|">
* Completion invoked within systemId parameter ie, completion offset is at |
* like so: <!DOCTYPE foo SYSTEM "./|">
*/
collectDTDSystemIdSuggestions(systemId.getStart(), systemId.getEnd(),
completionRequest, completionResponse);
collectDTDSystemIdSuggestions(systemId.getStart(), systemId.getEnd(), completionRequest,
completionResponse);
return completionResponse;
}
break;
Expand Down Expand Up @@ -346,16 +347,16 @@ private static Integer getSuffixIndex(String text, String suffix, final int init
// There is one of character of the suffix
offset++;
if (suffixIndex == suffix.length()) {
// the suffix index is the last character of the suffix
// the suffix index is the last character of the suffix
return offset;
}
// Try to eat the most characters of the suffix
for (; offset < text.length(); offset++) {
for (; offset < text.length(); offset++) {
suffixIndex++;
if (suffixIndex == suffix.length()) {
// the suffix index is the last character of the suffix
// the suffix index is the last character of the suffix
return offset;
}
}
ch = text.charAt(offset);
if (suffix.charAt(suffixIndex) != ch) {
return offset;
Expand Down Expand Up @@ -752,6 +753,11 @@ private void collectInsideContent(CompletionRequest request, CompletionResponse
collectOpenTagSuggestions(false, tagNameRange, request, response);
collectCloseTagSuggestions(tagNameRange, true, true, false, request, response);
}
// Adjust the range for covering the text node.
Range textRange = getTextRangeInsideContent(request.getNode());
if (textRange != null) {
request.setReplaceRange(textRange);
}
// Participant completion on XML content
for (ICompletionParticipant participant : getCompletionParticipants()) {
try {
Expand All @@ -763,6 +769,29 @@ private void collectInsideContent(CompletionRequest request, CompletionResponse
collectionRegionProposals(request, response);
}

private static Range getTextRangeInsideContent(DOMNode node) {
switch (node.getNodeType()) {
case Node.ELEMENT_NODE:
Node firstChild = node.getFirstChild();
if (firstChild == null) {
// ex : <root>|</root>
DOMElement element = (DOMElement) node;
return XMLPositionUtility.createRange(element.getStartTagCloseOffset() + 1,
element.getStartTagCloseOffset() + 1, element.getOwnerDocument());
}
if (firstChild.getNodeType() == Node.TEXT_NODE) {
// ex : <root>abcd|</root>
return XMLPositionUtility.selectText((DOMText) firstChild);
}
return null;
case Node.TEXT_NODE:
// ex : <root> | </root>
return XMLPositionUtility.selectText((DOMText) node);
}
// should never occur
return null;
}

private void collectionRegionProposals(ICompletionRequest request, ICompletionResponse response) {
// Completion for #region
try {
Expand Down Expand Up @@ -884,8 +913,10 @@ private void collectAttributeValueSuggestions(int valueStart, int valueEnd, Comp
/**
* Collect completion items for DTD systemId
*
* @param valueStart the start offset of the systemId value, including quote
* @param valueEnd the end offset of the systemId value, including quote
* @param valueStart the start offset of the systemId value, including
* quote
* @param valueEnd the end offset of the systemId value, including
* quote
* @param completionRequest the completion request
* @param completionResponse the completion response
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
package org.eclipse.lemminx.services.extensions;

import static org.eclipse.lemminx.XMLAssert.c;
import static org.eclipse.lemminx.XMLAssert.r;

import org.eclipse.lemminx.XMLAssert;
import org.eclipse.lemminx.commons.BadLocationException;
import org.eclipse.lemminx.services.XMLLanguageService;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemKind;
import org.eclipse.lsp4j.InsertTextFormat;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
Expand Down Expand Up @@ -120,6 +122,20 @@ public void testHTMLAttributeValueCompletion() throws BadLocationException {
c("checkbox", "\"checkbox\"" /* "<input type=\"checkbox\"" */));
}

@Test
public void testHTMLOnXMLContentCompletion() throws BadLocationException {
testCompletionFor("<input>|</input>", //
c("Test replace range", "replacement text", r(0, 7, 0, 7), null));
testCompletionFor("<input> |</input>", //
c("Test replace range", "replacement text", r(0, 7, 0, 8), null));
testCompletionFor("<input>| </input>", //
c("Test replace range", "replacement text", r(0, 7, 0, 8), null));
testCompletionFor("<input>some extisti|ng text</input>", //
c("Test replace range", "replacement text", r(0, 7, 0, 26), null));
testCompletionFor("<input>some extisti|ng <br/>text</input>", //
c("Test replace range", "replacement text", r(0, 7, 0, 22), null));
}

public static void testCompletionFor(String value, CompletionItem... expectedItems) throws BadLocationException {
XMLAssert.testCompletionFor(new HTMLLanguageService(), value, (String) null, null, null, null, true,
expectedItems);
Expand Down Expand Up @@ -180,8 +196,8 @@ public void onAttributeName(boolean generateValue, ICompletionRequest completion
}

@Override
public void onAttributeValue(String valuePrefix,
ICompletionRequest completionRequest, ICompletionResponse completionResponse) {
public void onAttributeValue(String valuePrefix, ICompletionRequest completionRequest,
ICompletionResponse completionResponse) {
String tag = completionRequest.getCurrentTag();
String attributeName = completionRequest.getCurrentAttributeName();
HTMLTag htmlTag = HTMLTag.getHTMLTag(tag);
Expand All @@ -201,7 +217,7 @@ public void onAttributeValue(String valuePrefix,
String[] values = HTMLTag.getAttributeValues(attrType);
for (String value : values) {
String insertText = completionRequest.getInsertAttrValue(value);

CompletionItem item = new CompletionItem();
item.setLabel(value);
item.setFilterText(insertText);
Expand All @@ -216,6 +232,16 @@ public void onAttributeValue(String valuePrefix,
}
}
}

@Override
public void onXMLContent(ICompletionRequest request, ICompletionResponse response) {
CompletionItem completion = new CompletionItem("Test replace range");
TextEdit edit = new TextEdit();
edit.setNewText("replacement text");
edit.setRange(request.getReplaceRange());
completion.setTextEdit(edit);
response.addCompletionItem(completion);
}
}
}
}

0 comments on commit 65f63d1

Please sign in to comment.