From 4d7a66b33ccfccfe80c7809da5de152a087163c8 Mon Sep 17 00:00:00 2001 From: Nikolas Komonen Date: Thu, 11 Oct 2018 12:18:57 -0400 Subject: [PATCH] Prolog completion works for partial 'xml' name, all possible closing brackets Signed-off-by: Nikolas Komonen --- .../lsp4xml/services/XMLCompletions.java | 93 ++++++++++++++----- .../lsp4xml/services/XMLCompletionTest.java | 26 +++++- 2 files changed, 91 insertions(+), 28 deletions(-) diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/XMLCompletions.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/XMLCompletions.java index 7f7d3ee606..cefea199c8 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/XMLCompletions.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/XMLCompletions.java @@ -207,11 +207,27 @@ public CompletionList doComplete(XMLDocument xmlDocument, Position position, Com break; case StartPrologOrPI: { try { - boolean isFirstNode; - isFirstNode = xmlDocument.positionAt(scanner.getTokenOffset()).getLine() == 0; + + boolean isFirstNode = xmlDocument.positionAt(scanner.getTokenOffset()).getLine() == 0; if (isFirstNode && offset <= scanner.getTokenEnd()) { + collectPrologSuggestion(scanner.getTokenEnd(), "", completionRequest, + completionResponse); + return completionResponse; + } + } catch (BadLocationException e) { + LOGGER.log(Level.SEVERE, "In XMLCompletions, StartPrologOrPI position error", e); + } + break; + } + case PIName: { + try { + + String tagName = scanner.getTokenText(); + boolean isFirstNode = xmlDocument.positionAt(scanner.getTokenOffset()).getLine() == 0; + String substringXML = "xml".substring(0, scanner.getTokenText().length()); + if (isFirstNode && offset <= scanner.getTokenEnd() && scanner.getTokenText().equals(substringXML)) { collectPrologSuggestion(scanner.getTokenEnd(), scanner.getTokenText(), completionRequest, - completionResponse, false); + completionResponse, true); return completionResponse; } } catch (BadLocationException e) { @@ -221,17 +237,16 @@ public CompletionList doComplete(XMLDocument xmlDocument, Position position, Com } case PrologName: { try { - boolean isFirstNode; - isFirstNode = xmlDocument.positionAt(scanner.getTokenOffset()).getLine() == 0; + boolean isFirstNode = xmlDocument.positionAt(scanner.getTokenOffset()).getLine() == 0; if (isFirstNode && offset <= scanner.getTokenEnd()) { collectPrologSuggestion(scanner.getTokenEnd(), scanner.getTokenText(), completionRequest, - completionResponse, true); + completionResponse); return completionResponse; } } catch (BadLocationException e) { LOGGER.log(Level.SEVERE, "In XMLCompletions, PrologName position error", e); - } - break; + } + break; } default: if (offset <= scanner.getTokenEnd()) { @@ -318,6 +333,7 @@ private void collectOpenTagSuggestions(boolean hasOpenBracket, Range replaceRang int tagNameEnd = document.offsetAt(replaceRange.getEnd()); int newOffset = getOffsetFollowedBy(text, tagNameEnd, ScannerState.WithinEndTag, TokenType.EndTagClose); if (newOffset != -1) { + newOffset++; replaceRange.setEnd(document.positionAt(newOffset)); } @@ -380,34 +396,56 @@ private void collectOpenTagSuggestions(boolean hasOpenBracket, Range replaceRang /** * Collect xml prolog completions. * - * @param tagNameEnd + * @param startOffset * @param tag * @param request * @param response */ - private void collectPrologSuggestion(int tagNameEnd, String tag, CompletionRequest request, - CompletionResponse response, boolean includesXML) { - - - String prologName = includesXML ? "" : "xml"; + private void collectPrologSuggestion(int startOffset, String tag, CompletionRequest request, + CompletionResponse response) { + collectPrologSuggestion(startOffset, tag, request, response, false); + } + + private void collectPrologSuggestion(int tokenEndOffset, String tag, CompletionRequest request, + CompletionResponse response, boolean inPIState) { XMLDocument document = request.getXMLDocument(); CompletionItem item = new CompletionItem(); item.setLabel(""); item.setKind(CompletionItemKind.Property); - item.setFilterText(prologName + " version=\"1.0\" encoding=\"UTF-8\"?>"); + item.setFilterText("xml version=\"1.0\" encoding=\"UTF-8\"?>"); item.setInsertTextFormat(InsertTextFormat.Snippet); - int closingBracketOffset = getOffsetFollowedBy(document.getText(), tagNameEnd, ScannerState.WithinTag, - TokenType.StartTagClose); - int end = closingBracketOffset != -1 ? closingBracketOffset - 1 : tagNameEnd; - String closeTag = closingBracketOffset != -1 ? "" : ">"; + int closingBracketOffset; + if(inPIState) { + closingBracketOffset= getOffsetFollowedBy(document.getText(), tokenEndOffset, ScannerState.WithinPI, + TokenType.PIEnd); + } + else {//prolog state + closingBracketOffset = getOffsetFollowedBy(document.getText(), tokenEndOffset, ScannerState.WithinTag, + TokenType.PrologEnd); + } + + if(closingBracketOffset != -1) { + //Include '?>' + closingBracketOffset += 2; + } + else { + closingBracketOffset = getOffsetFollowedBy(document.getText(), tokenEndOffset, ScannerState.WithinTag, + TokenType.StartTagClose); + if(closingBracketOffset == -1) { + closingBracketOffset = tokenEndOffset; + } + else { + closingBracketOffset ++; + } + } + int startOffset = tokenEndOffset - tag.length(); try { - Range editRange = getReplaceRange(tagNameEnd, end, request); - item.setTextEdit(new TextEdit(editRange, prologName + " version=\"1.0\" encoding=\"UTF-8\"?" + closeTag + "$0")); + Range editRange = getReplaceRange(startOffset, closingBracketOffset, request); + item.setTextEdit(new TextEdit(editRange, "xml version=\"1.0\" encoding=\"UTF-8\"?>" + "$0")); } catch (BadLocationException e) { LOGGER.log(Level.SEVERE, "While performing getReplaceRange for prolog completion.", e); } response.addCompletionItem(item); - } private void collectCloseTagSuggestions(int afterOpenBracket, boolean inOpenTag, int tagNameEnd, @@ -657,13 +695,22 @@ private static boolean isFollowedBy(String s, int offset, ScannerState intialSta return getOffsetFollowedBy(s, offset, intialState, expectedToken) != -1; } + /** + * Returns starting offset of 'expectedToken' if it the next non whitespace token after + * 'initialState' + * @param s + * @param offset + * @param intialState + * @param expectedToken + * @return + */ private static int getOffsetFollowedBy(String s, int offset, ScannerState intialState, TokenType expectedToken) { Scanner scanner = XMLScanner.createScanner(s, offset, intialState); TokenType token = scanner.scan(); while (token == TokenType.Whitespace) { token = scanner.scan(); } - return (token == expectedToken) ? scanner.getTokenOffset() + 1 : -1; + return (token == expectedToken) ? scanner.getTokenOffset() : -1; } private static int getWordStart(String s, int offset, int limit) { diff --git a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/XMLCompletionTest.java b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/XMLCompletionTest.java index 0b2e24f2f6..4dbc444907 100644 --- a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/XMLCompletionTest.java +++ b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/XMLCompletionTest.java @@ -146,10 +146,12 @@ public void testAutoCloseEnabledDisabled() throws BadLocationException { @Test public void testAutoCompletionPrologWithXML() throws BadLocationException { //With 'xml' label - testCompletionFor("", " version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 5, 0, 5), - " version=\"1.0\" encoding=\"UTF-8\"?>")); - testCompletionFor("", true, c("", " version=\"1.0\" encoding=\"UTF-8\"?$0", r(0, 5, 0, 5), - " version=\"1.0\" encoding=\"UTF-8\"?>")); + testCompletionFor("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 5), + "xml version=\"1.0\" encoding=\"UTF-8\"?>")); + testCompletionFor("", true, c("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 6), + "xml version=\"1.0\" encoding=\"UTF-8\"?>")); + testCompletionFor("", true, c("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 7), + "xml version=\"1.0\" encoding=\"UTF-8\"?>")); } @Test @@ -157,7 +159,21 @@ public void testAutoCompletionPrologWithoutXML() throws BadLocationException { //No 'xml' label testCompletionFor("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 2), "xml version=\"1.0\" encoding=\"UTF-8\"?>")); - testCompletionFor("", true, c("", "xml version=\"1.0\" encoding=\"UTF-8\"?$0", r(0, 2, 0, 2), + testCompletionFor("", true, c("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 3), + "xml version=\"1.0\" encoding=\"UTF-8\"?>")); + testCompletionFor("", true, c("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 4), + "xml version=\"1.0\" encoding=\"UTF-8\"?>")); + } + + @Test + public void testAutoCompletionPrologWithPartialXML() throws BadLocationException { + testCompletionFor("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 3), + "xml version=\"1.0\" encoding=\"UTF-8\"?>")); + testCompletionFor("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 4), + "xml version=\"1.0\" encoding=\"UTF-8\"?>")); + testCompletionFor("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 3), + "xml version=\"1.0\" encoding=\"UTF-8\"?>")); + testCompletionFor("", false, c("", "xml version=\"1.0\" encoding=\"UTF-8\"?>$0", r(0, 2, 0, 6), "xml version=\"1.0\" encoding=\"UTF-8\"?>")); }