diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/CompletionResponse.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/CompletionResponse.java index 4f237a698..9f7f138ca 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/CompletionResponse.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/CompletionResponse.java @@ -23,7 +23,7 @@ * Completion response implementation. * */ -class CompletionResponse extends CompletionList implements ICompletionResponse { +public class CompletionResponse extends CompletionList implements ICompletionResponse { private transient List seenAttributes; private transient boolean hasSomeItemFromGrammar; diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLCompletions.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLCompletions.java index 8f643093a..f8a85bb0a 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLCompletions.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/services/XMLCompletions.java @@ -48,6 +48,7 @@ import org.eclipse.lemminx.services.snippets.IXMLSnippetContext; import org.eclipse.lemminx.settings.SharedSettings; import org.eclipse.lemminx.settings.XMLCompletionSettings; +import org.eclipse.lemminx.utils.CompletionItemDefaultsUtils; import org.eclipse.lemminx.utils.StringUtils; import org.eclipse.lemminx.utils.XMLPositionUtility; import org.eclipse.lsp4j.CompletionItem; @@ -288,6 +289,8 @@ public CompletionList doComplete(DOMDocument xmlDocument, Position position, Sha return completionResponse; } finally { collectSnippetSuggestions(completionRequest, completionResponse); + // Manage itemDefaults + CompletionItemDefaultsUtils.process(completionResponse, settings); } } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/settings/XMLCompletionSettings.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/settings/XMLCompletionSettings.java index d225dd1fe..42b73ff73 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/settings/XMLCompletionSettings.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/settings/XMLCompletionSettings.java @@ -113,6 +113,21 @@ public boolean isCompletionResolveSupported(CompletionResolveSupportProperty pro .contains(property.name()); } + /** + * Returns true if the client support completion list itemDefaults given the field and + * false otherwise. + * + * @param field the completionList itemDefaults field + * + * @return true if the client support completion list itemDefaults given the field and + * false otherwise. + */ + public boolean isCompletionListItemDefaultsSupport(String field) { + return completionCapabilities != null && completionCapabilities.getCompletionList() != null + && completionCapabilities.getCompletionList().getItemDefaults() != null + && completionCapabilities.getCompletionList().getItemDefaults().contains(field); + } + /** * Merge only the given completion settings (and not the capability) in the * settings. diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/CompletionItemDefaultsUtils.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/CompletionItemDefaultsUtils.java new file mode 100644 index 000000000..f6c9766b6 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/CompletionItemDefaultsUtils.java @@ -0,0 +1,115 @@ +/******************************************************************************* +* Copyright (c) 2023 Red Hat Inc. and others. +* All rights reserved. This program and the accompanying materials +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.utils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.lemminx.services.CompletionResponse; +import org.eclipse.lemminx.settings.SharedSettings; +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemDefaults; +import org.eclipse.lsp4j.InsertTextFormat; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.jsonrpc.messages.Either; + +/** + * CompletionItemDefaultsUtils for implementing itemDefaults in completion list + */ +public class CompletionItemDefaultsUtils { + + private static final String ITEM_DEFAULTS_EDIT_RANGE = "editRange"; + + private static final String ITEM_DEFAULTS_INSERT_TEXT_FORMAT = "insertTextFormat"; + + public static void process(CompletionResponse completionResponse, SharedSettings sharedSettings) { + CompletionItemDefaults itemDefaults = new CompletionItemDefaults(); + List completionList = completionResponse.getItems(); + if (sharedSettings.getCompletionSettings().isCompletionListItemDefaultsSupport(ITEM_DEFAULTS_EDIT_RANGE)) { + Range editRange = findMostCommonEditRange(completionList); + itemDefaults.setEditRange(Either.forLeft(editRange)); + for (CompletionItem item : completionList) { + if (item.getTextEdit().isLeft() && item.getTextEdit().getLeft().getRange().equals(editRange)) { + item.setTextEditText(item.getTextEdit().getLeft().getNewText()); + item.setTextEdit(null); + } + } + completionResponse.setItemDefaults(itemDefaults); + } + if (sharedSettings.getCompletionSettings() + .isCompletionListItemDefaultsSupport(ITEM_DEFAULTS_INSERT_TEXT_FORMAT)) { + itemDefaults.setInsertTextFormat(findMostCommonInsertTextFormat(completionResponse.getItems())); + for (CompletionItem item : completionList) { + if (item.getInsertTextFormat() == itemDefaults.getInsertTextFormat()) { + item.setInsertTextFormat(null); + } + } + completionResponse.setItemDefaults(itemDefaults); + } + } + + /** + * Returns the most common editRange in the completion list. + * + * @param completionList the completion response + * @return the most common editRange in the completion list + */ + private static Range findMostCommonEditRange(List completionList) { + Map countMapEditRange = new HashMap<>(); + + for (CompletionItem item : completionList) { + if (item.getTextEdit().getLeft() != null) { + countMapEditRange.put(item.getTextEdit().getLeft().getRange(), + countMapEditRange.getOrDefault(item.getTextEdit().getLeft().getRange(), 0) + 1); + } + } + + Range mostCommonRange = null; + int maxCount = 0; + for (Map.Entry entry : countMapEditRange.entrySet()) { + if (entry.getValue() > maxCount) { + mostCommonRange = entry.getKey(); + maxCount = entry.getValue(); + } + } + return mostCommonRange; + } + + /** + * Returns the most common insertTextFormat in the completion list. + * + * @param completionList the completion response + * @return the most common insertTextFormat in the completion list + */ + private static InsertTextFormat findMostCommonInsertTextFormat(List completionList) { + Map countMapInsertTextFormat = new HashMap<>(); + + for (CompletionItem item : completionList) { + if (item.getInsertTextFormat() != null) { + countMapInsertTextFormat.put(item.getInsertTextFormat(), + countMapInsertTextFormat.getOrDefault(item.getInsertTextFormat(), 0) + 1); + } + } + + InsertTextFormat mostCommonInsertTextFormat = null; + int maxCount = 0; + for (Map.Entry entry : countMapInsertTextFormat.entrySet()) { + if (entry.getValue() > maxCount) { + mostCommonInsertTextFormat = entry.getKey(); + maxCount = entry.getValue(); + } + } + return mostCommonInsertTextFormat; + } + +} diff --git a/org.eclipse.lemminx/src/main/resources/META-INF/native-image/reflect-config.json b/org.eclipse.lemminx/src/main/resources/META-INF/native-image/reflect-config.json index f6f453503..daecd3a5a 100644 --- a/org.eclipse.lemminx/src/main/resources/META-INF/native-image/reflect-config.json +++ b/org.eclipse.lemminx/src/main/resources/META-INF/native-image/reflect-config.json @@ -721,6 +721,14 @@ "parameterTypes": [] }] }, + { + "name": "org.eclipse.lsp4j.CompletionItemDefaults", + "allDeclaredFields": true, + "methods": [{ + "name": "", + "parameterTypes": [] + }] + }, { "name": "org.eclipse.lsp4j.CompletionItemKind", "fields": [{ diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/XMLAssert.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/XMLAssert.java index c5398e81a..eb6656e97 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/XMLAssert.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/XMLAssert.java @@ -76,6 +76,7 @@ import org.eclipse.lsp4j.CompletionItemCapabilities; import org.eclipse.lsp4j.CompletionItemResolveSupportCapabilities; import org.eclipse.lsp4j.CompletionList; +import org.eclipse.lsp4j.CompletionListCapabilities; import org.eclipse.lsp4j.CreateFile; import org.eclipse.lsp4j.CreateFileOptions; import org.eclipse.lsp4j.Diagnostic; @@ -180,6 +181,14 @@ public static CompletionList testCompletionFor(String value, int expectedCount, return testCompletionFor(value, null, null, expectedCount, expectedItems); } + public static CompletionList testCompletionFor(String value, Integer expectedCount, boolean enableItemDefaults, + CompletionItem... expectedItems) + throws BadLocationException { + SharedSettings settings = new SharedSettings(); + return testCompletionFor(new XMLLanguageService(), value, null, null, null, expectedCount, settings, + enableItemDefaults, expectedItems); + } + public static CompletionList testCompletionFor(String value, String catalogPath, String fileURI, Integer expectedCount, CompletionItem... expectedItems) throws BadLocationException { @@ -193,21 +202,49 @@ public static CompletionList testCompletionFor(String value, boolean autoCloseTa } public static CompletionList testCompletionFor(XMLLanguageService xmlLanguageService, String value, - String catalogPath, - Consumer customConfiguration, String fileURI, Integer expectedCount, + String catalogPath, Consumer customConfiguration, String fileURI, Integer expectedCount, boolean autoCloseTags, CompletionItem... expectedItems) throws BadLocationException { + return testCompletionFor(xmlLanguageService, value, + catalogPath, customConfiguration, fileURI, expectedCount, + autoCloseTags, false, expectedItems); + } + + public static CompletionList testCompletionFor(XMLLanguageService xmlLanguageService, String value, + String catalogPath, Consumer customConfiguration, String fileURI, Integer expectedCount, + boolean autoCloseTags, boolean enableItemDefaults, CompletionItem... expectedItems) + throws BadLocationException { SharedSettings settings = new SharedSettings(); settings.getCompletionSettings().setAutoCloseTags(autoCloseTags); return testCompletionFor(xmlLanguageService, value, catalogPath, customConfiguration, fileURI, expectedCount, - settings, - expectedItems); + settings, enableItemDefaults, expectedItems); + } + + public static CompletionList testCompletionFor(XMLLanguageService xmlLanguageService, String value, + String catalogPath, Consumer customConfiguration, String fileURI, Integer expectedCount, + SharedSettings sharedSettings, CompletionItem... expectedItems) throws BadLocationException { + return testCompletionFor(xmlLanguageService, value, catalogPath, customConfiguration, fileURI, expectedCount, + sharedSettings, false, expectedItems); } public static CompletionList testCompletionFor(XMLLanguageService xmlLanguageService, String value, String catalogPath, Consumer customConfiguration, String fileURI, Integer expectedCount, - SharedSettings sharedSettings, CompletionItem... expectedItems) throws BadLocationException { + SharedSettings sharedSettings, boolean enableItemDefaults, CompletionItem... expectedItems) + throws BadLocationException { + if (enableItemDefaults) { + if (sharedSettings.getCompletionSettings().getCompletionCapabilities() == null) { + CompletionCapabilities completionCapabilities = new CompletionCapabilities(); + sharedSettings.getCompletionSettings().setCapabilities(completionCapabilities); + } + if (sharedSettings.getCompletionSettings().getCompletionCapabilities().getCompletionList() == null) { + CompletionListCapabilities completionListCapabilities = new CompletionListCapabilities(); + sharedSettings.getCompletionSettings().getCompletionCapabilities() + .setCompletionList(completionListCapabilities); + } + sharedSettings.getCompletionSettings().getCompletionCapabilities().getCompletionList() + .setItemDefaults(Arrays.asList("insertTextFormat", "editRange")); + } int offset = value.indexOf('|'); value = value.substring(0, offset) + value.substring(offset + 1); @@ -248,13 +285,18 @@ public static CompletionList testCompletionFor(XMLLanguageService xmlLanguageSer } if (expectedItems != null) { for (CompletionItem item : expectedItems) { - assertCompletion(list, item, expectedCount); + assertCompletion(list, item, enableItemDefaults, expectedCount); } } return list; } public static void assertCompletion(CompletionList completions, CompletionItem expected, Integer expectedCount) { + assertCompletion(completions, expected, false, expectedCount); + } + + public static void assertCompletion(CompletionList completions, CompletionItem expected, boolean enableItemDefaults, + Integer expectedCount) { List matches = completions.getItems().stream().filter(completion -> { return expected.getLabel().equals(completion.getLabel()); }).collect(Collectors.toList()); @@ -271,8 +313,8 @@ public static void assertCompletion(CompletionList completions, CompletionItem e }); } - CompletionItem match = getCompletionMatch(matches, expected); - if (expected.getTextEdit() != null && match.getTextEdit() != null) { + CompletionItem match = getCompletionMatch(matches, enableItemDefaults, expected); + if (!enableItemDefaults && expected.getTextEdit() != null && match.getTextEdit() != null) { if (expected.getTextEdit().getLeft().getNewText() != null) { assertEquals(expected.getTextEdit().getLeft().getNewText(), match.getTextEdit().getLeft().getNewText()); } @@ -290,6 +332,17 @@ public static void assertCompletion(CompletionList completions, CompletionItem e assertArrayEquals(expected.getAdditionalTextEdits().toArray(), matchedAdditionalTextEdits.toArray()); } + } else { + assertNull(match.getTextEdit()); + assertNull(match.getInsertTextFormat()); + if (match.getTextEditText() != null) { + assertEquals(expected.getTextEdit().getLeft().getNewText(), match.getTextEditText()); + } + Range r = expected.getTextEdit().getLeft().getRange(); + if (r != null && r.getStart() != null && r.getEnd() != null) { + assertEquals(expected.getTextEdit().getLeft().getRange(), + completions.getItemDefaults().getEditRange().getLeft()); + } } if (expected.getFilterText() != null && match.getFilterText() != null) { assertEquals(expected.getFilterText(), match.getFilterText()); @@ -330,8 +383,16 @@ public static void assertAdditionalTextEdit(List matches, TextEdit exp } private static CompletionItem getCompletionMatch(List matches, CompletionItem expected) { + return getCompletionMatch(matches, false, expected); + } + + private static CompletionItem getCompletionMatch(List matches, boolean enableItemDefaults, + CompletionItem expected) { for (CompletionItem item : matches) { - if (expected.getTextEdit().getLeft().getNewText().equals(item.getTextEdit().getLeft().getNewText())) { + if (!enableItemDefaults && expected.getTextEdit().getLeft().getNewText() + .equals(item.getTextEdit().getLeft().getNewText())) { + return item; + } else if (expected.getTextEdit().getLeft().getNewText().equals(item.getTextEditText())) { return item; } } @@ -912,15 +973,19 @@ public static List testCodeActionsFor(String xml, Diagnostic diagnos public static List testCodeActionsFor(String xml, Diagnostic diagnostic, String catalogPath, SharedSettings sharedSettings, XMLLanguageService xmlLanguageService, CodeAction... expected) throws BadLocationException { - return testCodeActionsFor(xml, diagnostic, null, catalogPath, null, sharedSettings, xmlLanguageService, -1, expected); + return testCodeActionsFor(xml, diagnostic, null, catalogPath, null, sharedSettings, xmlLanguageService, -1, + expected); } public static List testCodeActionsFor(String xml, Range range, String catalogPath, SharedSettings sharedSettings, XMLLanguageService xmlLanguageService, CodeAction... expected) throws BadLocationException { - return testCodeActionsFor(xml, null, range, catalogPath, null, sharedSettings, xmlLanguageService, -1, expected); + return testCodeActionsFor(xml, null, range, catalogPath, null, sharedSettings, xmlLanguageService, -1, + expected); } - public static List testCodeActionsFor(String xml, Diagnostic diagnostic, Range range, String catalogPath, + + public static List testCodeActionsFor(String xml, Diagnostic diagnostic, Range range, + String catalogPath, String fileURI, SharedSettings sharedSettings, XMLLanguageService xmlLanguageService, int index, CodeAction... expected) throws BadLocationException { int offset = xml.indexOf('|'); @@ -936,7 +1001,7 @@ public static List testCodeActionsFor(String xml, Diagnostic diagnos } else if (range == null && diagnostic != null) { range = diagnostic.getRange(); } - + // Otherwise, range is to be specified in parameters assertNotNull(range, "Range cannot be null"); @@ -1124,7 +1189,7 @@ public static Either teOp(String uri, int s } public static Either teOp(String uri, TextEdit... te) { - return Either.forLeft(new TextDocumentEdit(new VersionedTextDocumentIdentifier(uri, 0), Arrays.asList(te))); + return Either.forLeft(new TextDocumentEdit(new VersionedTextDocumentIdentifier(uri, 0), Arrays.asList(te))); } // ------------------- Hover assert @@ -1791,8 +1856,8 @@ public static void assertRename(XMLLanguageService languageService, String value .stream().filter(Either::isLeft) .filter(e -> uri.equals(e.getLeft().getTextDocument().getUri())) .map(Either::getLeft).findFirst(); - List actualEdits = documentChange.isPresent() ? - documentChange.get().getEdits() : Collections.emptyList(); + List actualEdits = documentChange.isPresent() ? documentChange.get().getEdits() + : Collections.emptyList(); assertArrayEquals(expectedEdits.toArray(), actualEdits.toArray()); } @@ -1836,7 +1901,7 @@ public static void assertLinkedEditing(LinkedEditingRanges actual, LinkedEditing } public static LinkedEditingRanges le(Range... ranges) { - return new LinkedEditingRanges(Arrays.asList(ranges), "[^\\s>]+"); + return new LinkedEditingRanges(Arrays.asList(ranges), "[^\\s>]+"); } public static LinkedEditingRanges le(String wordPattern, Range... ranges) { diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDCompletionExtensionsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDCompletionExtensionsTest.java index a84acd5a5..310505ec1 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDCompletionExtensionsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDCompletionExtensionsTest.java @@ -172,6 +172,31 @@ public void externalDTDCompletionAllDecls() throws BadLocationException { te(3, 1, 3, 1, ""), "\r\n" + // + "\r\n" + // + " |\r\n" + // + "]>\r\n" + // + "\r\n" + // + " " + // + ""; + testCompletionFor(xml, true, true, // + DTDNODE_SNIPPETS /* DTD node snippets */ + // + COMMENT_SNIPPETS /* Comment snippets */ , "catalog.xml", // + c("Insert DTD Element Declaration", te(3, 1, 3, 1, ""), + ""), ""), + ""), "$0"), "\r\n" + // + "\r\n" + // + "\r\n" + // + " \r\n" + // + "\r\n" + // + " <|"; + testCompletionFor(xml, true, true, null, + c("delegatePublic", te(6, 4, 6, 5, "$0"), + "$0"), "\r\n" + // @@ -77,6 +93,11 @@ private static void testCompletionFor(String xml, CompletionItem... expectedItem private static void testCompletionFor(String xml, boolean isSnippetsSupported, Integer expectedCount, CompletionItem... expectedItems) throws BadLocationException { + testCompletionFor(xml, isSnippetsSupported, false, expectedCount, expectedItems); + } + + private static void testCompletionFor(String xml, boolean isSnippetsSupported, boolean enableItemDefaults, + Integer expectedCount, CompletionItem... expectedItems) throws BadLocationException { CompletionCapabilities completionCapabilities = new CompletionCapabilities(); CompletionItemCapabilities completionItem = new CompletionItemCapabilities(isSnippetsSupported); // activate // snippets @@ -85,7 +106,7 @@ private static void testCompletionFor(String xml, boolean isSnippetsSupported, I SharedSettings sharedSettings = new SharedSettings(); sharedSettings.getCompletionSettings().setCapabilities(completionCapabilities); XMLAssert.testCompletionFor(new XMLLanguageService(), xml, "src/test/resources/catalogs/catalog.xml", null, - null, expectedCount, sharedSettings, expectedItems); + null, expectedCount, sharedSettings, enableItemDefaults, expectedItems); } } diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaCompletionExtensionsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaCompletionExtensionsTest.java index 661cce12b..7564faf20 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaCompletionExtensionsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSchemaCompletionExtensionsTest.java @@ -108,6 +108,19 @@ public void completionInRootWithCloseBracket() throws BadLocationException { c("parent", "", "\r\n" + + // + " <| >" + // here last '<' is replaced with + ""; + testCompletionWithCatalogFor(xml, + c("modelVersion", te(3, 1, 3, 5, ""), "", "\r\n" + // + "\r\n" + // + " \r\n" + // + "]>\r\n" + // + "\r\n" + // + " &foo_b|\r\n" + // <- here completion shows mdash entity + ""; + testCompletionFor(xml, 2 + // + 2 /* CDATA and Comments */ + // + PredefinedEntity.values().length /* predefined entities */, true, + c("&foo_bar;", "&foo_bar;", r(6, 2, 6, 8), "&foo_bar;"), // + c("&foo_baz;", "&foo_baz;", r(6, 2, 6, 8), "&foo_baz;")); + } + @Test public void insideWithAmp() throws BadLocationException { // &m|d;blablabla diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/prolog/PrologCompletionExtensionsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/prolog/PrologCompletionExtensionsTest.java index 5cb6ecf0d..31c7cf20b 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/prolog/PrologCompletionExtensionsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/prolog/PrologCompletionExtensionsTest.java @@ -96,6 +96,18 @@ public void completionVersionValue() throws BadLocationException { "\"" + PrologModel.VERSION_1_1 + "\"")); } + @Test + public void completionVersionValueItemDefaults() throws BadLocationException { + // completion on | + String xml = "\r\n" + // + ""; + testCompletionFor(true, xml, + c(PrologModel.VERSION_1, te(0, 14, 0, 14, "\"" + PrologModel.VERSION_1 + "\""), + "\"" + PrologModel.VERSION_1 + "\""), + c(PrologModel.VERSION_1_1, te(0, 14, 0, 14, "\"" + PrologModel.VERSION_1_1 + "\""), + "\"" + PrologModel.VERSION_1_1 + "\"")); + } + @Test public void completionVersionNoSpaceAfterEquals() throws BadLocationException { // completion on | @@ -330,6 +342,10 @@ public void testAutoCompletionPrologDTFFileWithPartialXML() throws BadLocationEx ""), "\r\n" + // + " <|\r\n" + // + ""; + testCompletionFor(xml, true, // + 4 + CDATA_SNIPPETS + COMMENT_SNIPPETS, // + c("include", te(1, 2, 1, 3, ""), ""), ""), ""), " xs:complexType/@name, xs:simpleType/@name + String xml = "\r\n" + // + "\r\n" + + // + " \r\n" + // + " \r\n" + // + " \r\n" + // + ""; + testCompletionFor(xml, true, c("xs:aComplexType", te(2, 30, 2, 30, "xs:aComplexType"), "xs:aComplexType"), + c("xs:aSimpleType", te(2, 30, 2, 30, "xs:aSimpleType"), "xs:aSimpleType"), + c("xs:string", te(2, 30, 2, 30, "xs:string"), "xs:string")); + } + @Test public void completionOnAttributeType() throws BadLocationException { // completion on | xs:attribute/@type -> xs:simpleType/@name @@ -171,6 +186,10 @@ public void complectionWithXSInclude() throws BadLocationException { c("TypeFromC", te(6, 20, 6, 20, "TypeFromC"), "TypeFromC")); } + private void testCompletionFor(String xml, boolean enableItemDefaults, CompletionItem... expectedItems) throws BadLocationException { + XMLAssert.testCompletionFor(xml, null, enableItemDefaults, expectedItems); + } + private void testCompletionFor(String xml, CompletionItem... expectedItems) throws BadLocationException { XMLAssert.testCompletionFor(xml, null, expectedItems); } diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/xsi/XSICompletionExtensionsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/xsi/XSICompletionExtensionsTest.java index db63aaa14..722020a00 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/xsi/XSICompletionExtensionsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/xsi/XSICompletionExtensionsTest.java @@ -42,6 +42,16 @@ public void completion() throws BadLocationException { c("false", te(1, 71, 1, 71, "\"false\""), "\"false\"")); } + @Test + public void completionItemDefaults() throws BadLocationException { + // completion on | + String xml = "\r\n" + // + ""; + testCompletionFor(xml, true, + c("true", te(1, 71, 1, 71, "\"true\""), "\"true\""), + c("false", te(1, 71, 1, 71, "\"false\""), "\"false\"")); + } + @Test public void completion2() throws BadLocationException { // completion on | @@ -157,4 +167,8 @@ private void testCompletionFor(String xml, CompletionItem... expectedItems) thro private void testCompletionFor(String xml, SharedSettings sharedSettings, CompletionItem... expectedItems) throws BadLocationException { XMLAssert.testCompletionFor(new XMLLanguageService(), xml, null, null, null, null, sharedSettings, expectedItems); } + + private void testCompletionFor(String xml, boolean enableItemDefaults, CompletionItem... expectedItems) throws BadLocationException { + XMLAssert.testCompletionFor(xml, null, enableItemDefaults, expectedItems); + } } diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/xsl/XSLCompletionExtensionsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/xsl/XSLCompletionExtensionsTest.java index cc92fd719..f94f73ffd 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/xsl/XSLCompletionExtensionsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/xsl/XSLCompletionExtensionsTest.java @@ -39,7 +39,23 @@ public void completion() throws BadLocationException { c("xsl:import", te(2, 0, 2, 0, ""), "xsl:import")); // coming from stylesheet children } + @Test + public void completionItemDefaults() throws BadLocationException { + // completion on | + String xml = "\r\n" + // + "\r\n" + // + "|"; + testCompletionFor(xml, true, + c("xsl:template", te(2, 0, 2, 0, ""), "xsl:template"), // <-- coming from substition group of xsl:declaration + c("xsl:output", te(2, 0, 2, 0, ""), "xsl:output"), // <-- coming from substition group of xsl:declaration + c("xsl:import", te(2, 0, 2, 0, ""), "xsl:import")); // coming from stylesheet children + } + private void testCompletionFor(String xml, CompletionItem... expectedItems) throws BadLocationException { XMLAssert.testCompletionFor(xml, null, expectedItems); } + + private void testCompletionFor(String xml, boolean enableItemDefaults, CompletionItem... expectedItems) throws BadLocationException { + XMLAssert.testCompletionFor(xml, null, enableItemDefaults, expectedItems); + } } diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/XMLCompletionSnippetsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/XMLCompletionSnippetsTest.java index 616ae9900..a17241fa4 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/XMLCompletionSnippetsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/services/XMLCompletionSnippetsTest.java @@ -234,6 +234,209 @@ public void emptyXMLContent() throws BadLocationException { } + @Test + public void emptyXMLContentItemDefaults() throws BadLocationException { + testCompletionFor("|", // + REGION_SNIPPETS /* #region */ + // + NEW_XML_SNIPPETS /* DOCTYPE snippets */ + // + XML_DECLARATION_SNIPPETS /* XML Declaration snippets */ + // + PROCESSING_INSTRUCTION_SNIPPETS /* Processing Instruction snippets */ + // + COMMENT_SNIPPETS /* Comment snippets */ + // + CATALOG_SNIPPETS /* Catalog snippets */ , // + true, + c("New XML with SYSTEM DOCTYPE", // + "" + lineSeparator() + // + "" + lineSeparator() + // + "", // + r(0, 0, 0, 0), "", // + r(0, 0, 0, 0), "", // + r(0, 0, 0, 0), "", // + r(0, 0, 0, 0), "" + lineSeparator() + // + " " + lineSeparator() + // + "", // + r(0, 0, 0, 0), "schemaLocation"), + c("New XML bound with xsi:noNamespaceSchemaLocation", // + "" + lineSeparator() + // + " " + lineSeparator() + // + "", // + r(0, 0, 0, 0), "noNamespaceSchemaLocation"), + c("New XML bound with RelaxNG", // + "" + lineSeparator() + // + "" + + lineSeparator() + // + "" + lineSeparator() + // + " " + lineSeparator() + // + "", // + r(0, 0, 0, 0), "relaxng"), + c("New catalog bound using DTD", // + "" + + lineSeparator() + // + "" + + lineSeparator() + // + "\t" + lineSeparator() + // + "", // + r(0, 0, 0, 0), "" + lineSeparator() + // + "\t" + lineSeparator() + // + "", // + r(0, 0, 0, 0), "" + lineSeparator() + // + "\t" + lineSeparator() + // + "", + r(0, 0, 0, 0), "", // + r(0, 0, 0, 0), "", // + r(0, 0, 0, 1), "", // + r(0, 0, 0, 2), "", // + r(0, 0, 0, 2), "|", //