GH-1163: added basic content-assist to easily add common spring namespaces

This commit is contained in:
Martin Lippert
2024-01-17 14:13:39 +01:00
parent 9c5e4ea29f
commit 35a3f64649
5 changed files with 657 additions and 24 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2023 Pivotal, Inc.
* Copyright (c) 2016, 2024 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -57,6 +57,7 @@ import org.springframework.ide.vscode.commons.protocol.HighlightParams;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.util.Unicodes;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -452,7 +453,13 @@ public class Editor {
public void apply(CompletionItem completion) throws Exception {
completion = harness.resolveCompletionItem(completion);
Either<TextEdit,InsertReplaceEdit> edit = completion.getTextEdit();
String docText = doc.getText();
TextDocument original = new TextDocument(doc.getUri(), doc.getLanguageId());
original.setText(doc.getText());
int insertPosition = 0;
int insertLength = 0;
if (edit != null) {
if (edit.isLeft()) {
String replaceWith = edit.getLeft().getNewText();
@@ -480,16 +487,24 @@ public class Editor {
}
Range rng = edit.getLeft().getRange();
int start = doc.toOffset(rng.getStart());
int end = doc.toOffset(rng.getEnd());
int start = original.toOffset(rng.getStart());
int end = original.toOffset(rng.getEnd());
replaceText(start, end, replaceWith);
insertPosition = start;
insertLength = replaceWith.length() - (end - start);
selectionStart = selectionEnd = start+cursorReplaceOffset;
} else {
throw new UnsupportedOperationException("InsertReplaceEdit edits not supported");
}
} else {
String insertText = getInsertText(completion);
String newText = docText.substring(0, selectionStart) + insertText + docText.substring(selectionStart);
String newText = original.get().substring(0, selectionStart) + insertText + original.get().substring(selectionStart);
insertPosition = selectionStart;
insertLength = insertText.length();
selectionStart+= insertText.length();
selectionEnd += insertText.length();
@@ -501,10 +516,19 @@ public class Editor {
for (TextEdit te : completion.getAdditionalTextEdits()) {
String replaceWith = te.getNewText();
Range rng = te.getRange();
int start = doc.toOffset(rng.getStart());
int end = doc.toOffset(rng.getEnd());
int start = original.toOffset(rng.getStart());
int end = original.toOffset(rng.getEnd());
// adjust start/end, if the completion insert text was positioned before the additional text edits
if (start > insertPosition) {
start += insertLength;
end += insertLength;
}
else {
selectionStart = selectionEnd = selectionStart - (end - start) + replaceWith.length();
}
replaceText(start, end, replaceWith);
selectionStart = selectionEnd = selectionStart - (end - start) + replaceWith.length();
}
}

View File

@@ -62,6 +62,7 @@ import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.boot.xml.completions.BeanRefCompletionProposalProvider;
import org.springframework.ide.vscode.boot.xml.completions.ConstructorArgNameCompletionProposalProvider;
import org.springframework.ide.vscode.boot.xml.completions.GenericXMLCompletionProposal;
import org.springframework.ide.vscode.boot.xml.completions.NamespaceCompletionProvider;
import org.springframework.ide.vscode.boot.xml.completions.PropertyNameCompletionProposalProvider;
import org.springframework.ide.vscode.boot.xml.completions.TypeCompletionProposalProvider;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
@@ -85,7 +86,7 @@ public class SpringXMLCompletionEngine implements ICompletionEngine, LanguageSpe
private final Map<XMLElementKey, XMLCompletionProvider> completionProviders;
private final BootJavaConfig config;
public SpringXMLCompletionEngine(
SimpleLanguageServer server,
JavaProjectFinder projectFinder,
@@ -180,6 +181,22 @@ public class SpringXMLCompletionEngine implements ICompletionEngine, LanguageSpe
}
}
break;
case AttributeName:
if (scanner.getTokenOffset() <= offset && offset < scanner.getTokenEnd()) {
if (node.getParentNode() != null && node.getParentNode() instanceof DOMDocument
&& namespace.equals("http://www.springframework.org/schema/beans") && node.getNodeName().equals("beans")) {
return NamespaceCompletionProvider.createNamespaceCompletionProposals(doc, offset, token, node);
}
}
break;
case Whitespace:
if (scanner.getTokenOffset() <= offset && offset < scanner.getTokenEnd()) {
if (node.getParentNode() != null && node.getParentNode() instanceof DOMDocument
&& namespace.equals("http://www.springframework.org/schema/beans") && node.getNodeName().equals("beans")) {
return NamespaceCompletionProvider.createNamespaceCompletionProposals(doc, offset, token, node);
}
}
break;
default:
break;
}
@@ -229,7 +246,7 @@ public class SpringXMLCompletionEngine implements ICompletionEngine, LanguageSpe
return completions;
}
@Override
public Collection<LanguageId> supportedLanguages() {
return ImmutableList.of(LanguageId.XML);

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2020 Pivotal, Inc.
* Copyright (c) 2019, 2024 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,9 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.xml.completions;
import java.util.Optional;
import java.util.function.Supplier;
import org.eclipse.lsp4j.CompletionItemKind;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
@@ -26,8 +29,14 @@ public class GenericXMLCompletionProposal extends ScoreableProposal {
private final String detail;
private final Renderable documentation;
private final double score;
private final String filterText;
private final DocumentEdits additionalEdits;
public GenericXMLCompletionProposal(String label, CompletionItemKind kind, DocumentEdits edits, String detail, Renderable documentation, double score) {
this(label, kind, edits, detail, documentation, score, label, null);
}
public GenericXMLCompletionProposal(String label, CompletionItemKind kind, DocumentEdits edits, String detail, Renderable documentation, double score, String filterText, DocumentEdits additionalEdits) {
super();
this.label = label;
this.kind = kind;
@@ -35,6 +44,8 @@ public class GenericXMLCompletionProposal extends ScoreableProposal {
this.detail = detail;
this.documentation = documentation;
this.score = score;
this.filterText = filterText;
this.additionalEdits = additionalEdits;
}
@Override
@@ -66,5 +77,20 @@ public class GenericXMLCompletionProposal extends ScoreableProposal {
public double getBaseScore() {
return this.score;
}
@Override
public String getFilterText() {
return this.filterText;
}
@Override
public Optional<Supplier<DocumentEdits>> getAdditionalEdit() {
if (this.additionalEdits != null) {
return Optional.of(() -> additionalEdits);
}
else {
return Optional.empty();
}
}
}

View File

@@ -0,0 +1,218 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.xml.completions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.eclipse.lemminx.dom.DOMAttr;
import org.eclipse.lemminx.dom.DOMNode;
import org.eclipse.lemminx.dom.DOMRange;
import org.eclipse.lemminx.dom.parser.TokenType;
import org.eclipse.lsp4j.CompletionItemKind;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.completion.IndentUtil;
import org.springframework.ide.vscode.commons.languageserver.util.PrefixFinder;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.Renderables;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class NamespaceCompletionProvider {
private static PrefixFinder PREFIX_FINDER = new PrefixFinder() {
@Override
protected boolean isPrefixChar(char c) {
return Character.isAlphabetic(c) || c == ':';
}
};
public static Collection<ICompletionProposal> createNamespaceCompletionProposals(TextDocument doc, int offset, TokenType token, DOMNode node) {
String prefix = PREFIX_FINDER.getPrefix(doc, offset);
if (prefix != null) {
Collection<ICompletionProposal> result = new ArrayList<>();
NamespaceInformation[] namespaces = getNamespaces();
for (NamespaceInformation namespace : namespaces) {
if (namespace.getNamespaceURI().startsWith(prefix)) {
result.add(createCompletionProposal(namespace, prefix, doc, offset, token, node));
}
}
return result;
}
else {
return Collections.emptyList();
}
}
private static ICompletionProposal createCompletionProposal(NamespaceInformation namespace, String prefix, TextDocument doc, int offset, TokenType token, DOMNode node) {
IndentUtil indentUtil = new IndentUtil(doc);
// main edit (inserts the namespace attribute itself)
DocumentEdits edits = new DocumentEdits(doc, false);
String startIndent = indentUtil.getReferenceIndent(offset, doc);
edits.replace(offset - prefix.length(), offset, namespace.getNamespaceURI() + "\n" + startIndent);
// additional edit (inserts the namespace location to an existing xsi:schemaLocation attribute)
DocumentEdits additionalEdits = null;
DOMAttr attributeNode = node.getAttributeNode("xsi:schemaLocation");
if (attributeNode != null) {
DOMRange range = attributeNode.getNodeAttrValue();
String locationIndent = indentUtil.getReferenceIndent(range.getEnd(), doc);
String locationIndentAtStart = indentUtil.getReferenceIndent(range.getStart(), doc);
if (locationIndent.length() == locationIndentAtStart.length()) {
locationIndent = locationIndent + locationIndent;
}
String additionalInsertText = "\n"
+ locationIndent
+ namespace.getNamespaceLocation();
additionalEdits = new DocumentEdits(doc, false);
additionalEdits.insert(range.getEnd() - 1, additionalInsertText);
}
Renderable documentation = Renderables.text(namespace.getDetails());
return new GenericXMLCompletionProposal(namespace.getLabel(), CompletionItemKind.Text, edits, namespace.getDetails(), documentation, 1.0d, namespace.getNamespaceURI(), additionalEdits);
}
public static NamespaceInformation[] getNamespaces() {
return NAMESPACES;
}
public static class NamespaceInformation {
private final String label;
private final String details;
private final String namespaceURI;
private final String namespaceLocation;
public NamespaceInformation(String label, String details, String namespaceURI,
String namespaceLocation) {
this.label = label;
this.details = details;
this.namespaceURI = namespaceURI;
this.namespaceLocation = namespaceLocation;
}
public String getLabel() {
return label;
}
public String getDetails() {
return details;
}
public String getNamespaceURI() {
return namespaceURI;
}
public String getNamespaceLocation() {
return namespaceLocation;
}
}
private static final NamespaceInformation[] NAMESPACES = {
// core framework
new NamespaceInformation(
"http://www.springframework.org/schema/beans",
"http://www.springframework.org/schema/beans",
"xmlns:beans=\"http://www.springframework.org/schema/beans\"",
"http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/context",
"http://www.springframework.org/schema/context",
"xmlns:context=\"http://www.springframework.org/schema/context\"",
"http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/tx",
"http://www.springframework.org/schema/tx",
"xmlns:tx=\"http://www.springframework.org/schema/tx\"",
"http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/aop",
"http://www.springframework.org/schema/aop",
"xmlns:aop=\"http://www.springframework.org/schema/aop\"",
"http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/oxm",
"http://www.springframework.org/schema/oxm",
"xmlns:oxm=\"http://www.springframework.org/schema/oxm\"",
"http://www.springframework.org/schema/oxm https://www.springframework.org/schema/oxm/spring-oxm.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/jms",
"http://www.springframework.org/schema/jms",
"xmlns:jms=\"http://www.springframework.org/schema/jms\"",
"http://www.springframework.org/schema/jms https://www.springframework.org/schema/jms/spring-jms.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/jdbc",
"http://www.springframework.org/schema/jdbc",
"xmlns:jdbc=\"http://www.springframework.org/schema/jdbc\"",
"http://www.springframework.org/schema/jdbc https://www.springframework.org/schema/jdbc/spring-jdbc.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/tool",
"http://www.springframework.org/schema/tool",
"xmlns:tool=\"http://www.springframework.org/schema/tool\"",
"http://www.springframework.org/schema/tool https://www.springframework.org/schema/tool/spring-tool.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/util",
"http://www.springframework.org/schema/util",
"xmlns:util=\"http://www.springframework.org/schema/util\"",
"http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/mvc",
"http://www.springframework.org/schema/mvc",
"xmlns:mvc=\"http://www.springframework.org/schema/mvc\"",
"http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/jee",
"http://www.springframework.org/schema/jee",
"xmlns:jee=\"http://www.springframework.org/schema/jee\"",
"http://www.springframework.org/schema/jee https://www.springframework.org/schema/jee/spring-jee.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/lang",
"http://www.springframework.org/schema/lang",
"xmlns:lang=\"http://www.springframework.org/schema/lang\"",
"http://www.springframework.org/schema/lang https://www.springframework.org/schema/lang/spring-lang.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/task",
"http://www.springframework.org/schema/task",
"xmlns:task=\"http://www.springframework.org/schema/task\"",
"http://www.springframework.org/schema/task https://www.springframework.org/schema/task/spring-task.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/cache",
"http://www.springframework.org/schema/cache",
"xmlns:cache=\"http://www.springframework.org/schema/cache\"",
"http://www.springframework.org/schema/cache https://www.springframework.org/schema/cache/spring-cache.xsd"),
new NamespaceInformation(
"http://www.springframework.org/schema/websocket",
"http://www.springframework.org/schema/websocket",
"xmlns:websocket=\"http://www.springframework.org/schema/websocket\"",
"http://www.springframework.org/schema/websocket https://www.springframework.org/schema/websocket/spring-websocket.xsd"),
// security
new NamespaceInformation(
"http://www.springframework.org/schema/security",
"http://www.springframework.org/schema/security",
"xmlns:security=\"http://www.springframework.org/schema/security\"",
"http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd"),
};
}

View File

@@ -1,19 +1,18 @@
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* Copyright (c) 2024 Broadcom
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
* Broadcom - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.xml.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -33,9 +32,9 @@ import org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp;
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.boot.bootiful.XmlBeansTestConf;
import org.springframework.ide.vscode.boot.java.utils.test.MockProjectObserver;
import org.springframework.ide.vscode.boot.xml.completions.NamespaceCompletionProvider;
import org.springframework.ide.vscode.commons.languageserver.util.Settings;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.commons.util.UriUtil;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.languageserver.starter.LanguageServerAutoConf;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
@@ -71,6 +70,7 @@ public class XMLContentAssistTest {
private MavenJavaProject project;
private Level originalLevel;
private int ALL_NAMESPACE_COMPLETIONS = NamespaceCompletionProvider.getNamespaces().length;
@BeforeEach
public void setup() throws Exception {
@@ -112,10 +112,7 @@ public class XMLContentAssistTest {
@Test
void testEmptyXMLFileCompletions() throws Exception {
Path xmlFilePath = Paths.get(project.getLocationUri()).resolve("beans.xml");
Editor editor = harness.newEditor(LanguageId.XML, "",
UriUtil.toUri(xmlFilePath.toFile()).toString()
);
Editor editor = new Editor(harness, "<*>", LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(1, completions.size());
@@ -124,13 +121,364 @@ public class XMLContentAssistTest {
@Test
void testNoSkeletonSnippetForNonEmptyXMLFile() throws Exception {
Path xmlFilePath = Paths.get(project.getLocationUri()).resolve("beans.xml");
Editor editor = harness.newEditor(LanguageId.XML, "<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\\n",
UriUtil.toUri(xmlFilePath.toFile()).toString()
);
Editor editor = new Editor(harness, "<*><?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\\n", LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(0, completions.size());
}
@Test
void testAddNamespaceCompletion1() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<*>xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(ALL_NAMESPACE_COMPLETIONS, completions.size());
CompletionItem contextItem = getContextCompletionItem(completions);
assertNotNull(contextItem);
editor.apply(contextItem);
String editorContent = editor.getText();
assertEquals("""
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
<*>xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
editorContent);
}
@Test
void testAddNamespaceCompletion2() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<*>
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(ALL_NAMESPACE_COMPLETIONS, completions.size());
CompletionItem contextItem = getContextCompletionItem(completions);
assertNotNull(contextItem);
editor.apply(contextItem);
String editorContent = editor.getText();
assertEquals("""
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
<*>
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
editorContent);
}
@Test
void testAddNamespaceCompletion3() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:<*>
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(ALL_NAMESPACE_COMPLETIONS, completions.size());
CompletionItem contextItem = getContextCompletionItem(completions);
assertNotNull(contextItem);
editor.apply(contextItem);
String editorContent = editor.getText();
assertEquals("""
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
<*>
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
editorContent);
}
@Test
void testAddNamespaceCompletion4() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns<*>
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(ALL_NAMESPACE_COMPLETIONS, completions.size());
CompletionItem contextItem = getContextCompletionItem(completions);
assertNotNull(contextItem);
editor.apply(contextItem);
String editorContent = editor.getText();
assertEquals("""
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
<*>
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
editorContent);
}
@Test
void testAddNamespaceCompletion5() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xm<*>
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(ALL_NAMESPACE_COMPLETIONS, completions.size());
CompletionItem contextItem = getContextCompletionItem(completions);
assertNotNull(contextItem);
editor.apply(contextItem);
String editorContent = editor.getText();
assertEquals("""
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
<*>
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
editorContent);
}
@Test
void testNoNamespaceCompletionOutsideOfMainElement1() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
<*>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(0, completions.size());
}
@Test
void testNoNamespaceCompletionOutsideOfMainElement2() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<*><bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(0, completions.size());
}
@Test
void testNoNamespaceCompletionOutsideOfMainElement3() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<<*>bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(0, completions.size());
}
@Test
void testNoNamespaceCompletionOutsideOfMainElement4() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean <*>id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(0, completions.size());
}
@Test
void testNoNamespaceCompletionOutsideOfMainElement5() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"><<*>/bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(0, completions.size());
}
@Test
void testNoNamespaceCompletionOutsideOfMainElement6() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"><<*>/bean>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(0, completions.size());
}
@Test
void testNoNamespaceCompletionOutsideOfMainElement7() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></be<*>an>
</beans>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(0, completions.size());
}
@Test
void testNoNamespaceCompletionOutsideOfMainElement8() throws Exception {
Editor editor = new Editor(harness, """
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="simpleObj" class="u.t.r.SimpleObj"></bean>
</beans<*>>
""",
LanguageId.XML);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(0, completions.size());
}
private CompletionItem getContextCompletionItem(List<CompletionItem> completions) {
for (CompletionItem completionItem : completions) {
if (completionItem.getLabel().contains("/schema/context")) {
return completionItem;
}
}
return null;
}
}