Skip to content

Commit

Permalink
Improved namespace renaming for XML/XSD documents
Browse files Browse the repository at this point in the history
Fixes eclipse-lemminx#366

Can rename namespace declaration and all will change, renaming element with namespace does not wipe
namespace, attribute values referencing a namespace will update if necessary

Signed-off-by: Nikolas <nikolaskomonen@gmail.com>
  • Loading branch information
angelozerr authored and NikolasKomonen committed May 29, 2019
1 parent 1097abe commit 25d9b55
Show file tree
Hide file tree
Showing 16 changed files with 491 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ public String getName() {
return name;
}

@Override
public String getLocalName() {
int colonIndex = name.indexOf(":");
if(colonIndex > 0) {
return name.substring(colonIndex + 1);
}
return name;
}

/*
* (non-Javadoc)
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ public interface CMDocument {
*/
CMElementDeclaration findCMElement(DOMElement element, String namespace);

String getURI();

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*/
package org.eclipse.lsp4xml.extensions.contentmodel.participants;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;

import org.eclipse.lsp4j.CompletionItem;
Expand All @@ -31,6 +33,7 @@
import org.eclipse.lsp4xml.services.extensions.ICompletionResponse;
import org.eclipse.lsp4xml.settings.SharedSettings;
import org.eclipse.lsp4xml.uriresolver.CacheResourceDownloadingException;
import org.eclipse.lsp4xml.utils.StringUtils;

/**
* Extension to support XML completion based on content model (XML Schema
Expand All @@ -42,26 +45,34 @@ public class ContentModelCompletionParticipant extends CompletionParticipantAdap
public void onTagOpen(ICompletionRequest request, ICompletionResponse response) throws Exception {
try {
DOMDocument document = request.getXMLDocument();
String schemaURI;
String fileURI;
ContentModelManager contentModelManager = request.getComponent(ContentModelManager.class);
DOMElement parentElement = request.getParentElement();
CMDocument cmDocument;
if (parentElement == null) {
// XML is empty, in case of XML file associations, a XMl Schema/DTD can be bound
// check if it's root element (in the case of XML file associations, the link to
// XML Schema is done with pattern and not with XML root element)
CMDocument cmDocument = contentModelManager.findCMDocument(document, null);
cmDocument = contentModelManager.findCMDocument(document, null);
if (cmDocument != null) {
fillWithChildrenElementDeclaration(null, cmDocument.getElements(), null, false, request, response);
schemaURI = cmDocument.getURI();
fillWithChildrenElementDeclaration(null, cmDocument.getElements(), null, false, request, response, schemaURI);
}
return;
}
// Try to retrieve XML Schema/DTD element declaration for the parent element
// where completion was triggered.
cmDocument = contentModelManager.findCMDocument(parentElement, parentElement.getNamespaceURI());

schemaURI = cmDocument != null ? cmDocument.getURI() : null;
CMElementDeclaration cmElement = contentModelManager.findCMElement(parentElement);
String defaultPrefix = null;

if (cmElement != null) {
defaultPrefix = parentElement.getPrefix();
fillWithChildrenElementDeclaration(parentElement, cmElement.getElements(), defaultPrefix, false,
request, response);
request, response, schemaURI);
}
if (parentElement.isDocumentElement()) {
// root document element
Expand All @@ -71,10 +82,10 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response)
continue;
}
String namespaceURI = parentElement.getNamespaceURI(prefix);
CMDocument cmDocument = contentModelManager.findCMDocument(parentElement, namespaceURI);
cmDocument = contentModelManager.findCMDocument(parentElement, namespaceURI);
if (cmDocument != null) {
fillWithChildrenElementDeclaration(parentElement, cmDocument.getElements(), prefix, true,
request, response);
request, response, cmDocument.getURI());
}
}
}
Expand All @@ -84,15 +95,15 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response)
if (cmInternalElement != null) {
defaultPrefix = parentElement.getPrefix();
fillWithChildrenElementDeclaration(parentElement, cmInternalElement.getElements(), defaultPrefix, false,
request, response);
request, response, schemaURI);
}
} catch (CacheResourceDownloadingException e) {
// XML Schema, DTD is loading, ignore this error
}
}

private void fillWithChildrenElementDeclaration(DOMElement element, Collection<CMElementDeclaration> cmElements,
String p, boolean forceUseOfPrefix, ICompletionRequest request, ICompletionResponse response)
String p, boolean forceUseOfPrefix, ICompletionRequest request, ICompletionResponse response, String schemaURI)
throws BadLocationException {
XMLGenerator generator = request.getXMLGenerator();
for (CMElementDeclaration child : cmElements) {
Expand All @@ -101,9 +112,26 @@ private void fillWithChildrenElementDeclaration(DOMElement element, Collection<C
CompletionItem item = new CompletionItem(label);
item.setFilterText(request.getFilterForStartTagName(label));
item.setKind(CompletionItemKind.Property);
String documentation = child.getDocumentation();
if (documentation != null) {
item.setDetail(documentation);
StringBuilder sb = new StringBuilder();
String tempDoc = child.getDocumentation();
boolean tempDocHasContent = !StringUtils.isEmpty(tempDoc);
if(tempDocHasContent) {
sb.append(tempDoc);
}

if(schemaURI != null) {
if(tempDocHasContent) {
String lineSeparator = System.getProperty("line.separator");
sb.append(lineSeparator);
sb.append(lineSeparator);
}
Path schemaPath = Paths.get(schemaURI);
sb.append("Source: ");
sb.append(schemaPath.getFileName().toString());
}
String detail = sb.toString();
if (!detail.isEmpty()) {
item.setDetail(detail);
}
String xml = generator.generate(child, prefix);
item.setTextEdit(new TextEdit(request.getReplaceRange(), xml));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public String getSystemId(DOMDocument xmlDocument, String namespaceURI) {
@Override
public CMDocument createCMDocument(String key) {
try {
CMDTDDocument document = new CMDTDDocument();
CMDTDDocument document = new CMDTDDocument(key);
document.setEntityResolver(resolverExtensionManager);
Grammar grammar = document.loadGrammar(new XMLInputSource(null, key, null));
if (grammar != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ public class CMDTDDocument extends XMLDTDLoader implements CMDocument {
private List<CMElementDeclaration> elements;
private DTDGrammar grammar;
private Set<String> hierarchies;
private String uri;

public CMDTDDocument() {}

public CMDTDDocument(String uri) {
this.uri = uri;
}

@Override
public Collection<CMElementDeclaration> getElements() {
Expand All @@ -60,6 +67,16 @@ public Collection<CMElementDeclaration> getElements() {
return elements;
}


/**
* Returns the URI of this document, is none was provided this
* returns null.
*/
@Override
public String getURI() {
return uri;
}

@Override
public CMElementDeclaration findCMElement(DOMElement element, String namespace) {
List<DOMElement> paths = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public CMDocument createCMDocument(String key) {
XSModel model = getLoader().loadURI(key);
if (model != null) {
// XML Schema can be loaded
return new CMXSDDocument(model);
return new CMXSDDocument(model, key);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,23 @@ public class CMXSDDocument implements CMDocument {

private Collection<CMElementDeclaration> elements;

private String uri;

public CMXSDDocument(XSModel model) {
this.model = model;
this.elementMappings = new HashMap<>();
}

public CMXSDDocument(XSModel model, String uri) {
this(model);
this.uri = uri;
}

@Override
public String getURI() {
return uri;
}

@Override
public Collection<CMElementDeclaration> getElements() {
if (elements == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ public List<DocumentHighlight> findDocumentHighlights(DOMDocument xmlDocument, P
return Collections.emptyList();
}

private static boolean doesTagCoverPosition(Range startTagRange, Range endTagRange, Position position) {
public static boolean doesTagCoverPosition(Range startTagRange, Range endTagRange, Position position) {
return startTagRange != null && covers(startTagRange, position)
|| endTagRange != null && covers(endTagRange, position);
}

private static List<DocumentHighlight> getHighlightsList(Range startTagRange, Range endTagRange) {
public static List<DocumentHighlight> getHighlightsList(Range startTagRange, Range endTagRange) {

List<DocumentHighlight> result = new ArrayList<>(2);
if (startTagRange != null) {
Expand All @@ -113,11 +113,11 @@ private static boolean isBeforeOrEqual(Position pos1, Position pos2) {
|| (pos1.getLine() == pos2.getLine() && pos1.getCharacter() <= pos2.getCharacter());
}

private static boolean covers(Range range, Position position) {
public static boolean covers(Range range, Position position) {
return isBeforeOrEqual(range.getStart(), position) && isBeforeOrEqual(position, range.getEnd());
}

private static Range getTagNameRange(TokenType tokenType, int startOffset, DOMDocument xmlDocument) {
public static Range getTagNameRange(TokenType tokenType, int startOffset, DOMDocument xmlDocument) {

Scanner scanner = XMLScanner.createScanner(xmlDocument.getText(), startOffset);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionContext;
Expand Down Expand Up @@ -46,7 +45,6 @@
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.dom.DOMElement;
import org.eclipse.lsp4xml.extensions.contentmodel.settings.XMLValidationSettings;
import org.eclipse.lsp4xml.services.extensions.CompletionSettings;
import org.eclipse.lsp4xml.services.extensions.XMLExtensionsRegistry;
import org.eclipse.lsp4xml.settings.SharedSettings;
import org.eclipse.lsp4xml.settings.XMLFormattingOptions;
Expand Down Expand Up @@ -164,8 +162,7 @@ public List<FoldingRange> getFoldingRanges(TextDocument document, FoldingRangeCa
}

public WorkspaceEdit doRename(DOMDocument xmlDocument, Position position, String newText) {
List<TextEdit> textEdits = findDocumentHighlights(xmlDocument, position).stream()
.map(h -> new TextEdit(h.getRange(), newText)).collect(Collectors.toList());
List<TextEdit> textEdits = XMLRename.getTextEdits(xmlDocument, position, newText);
Map<String, List<TextEdit>> changes = new HashMap<>();
changes.put(xmlDocument.getDocumentURI(), textEdits);
return new WorkspaceEdit(changes);
Expand Down
Loading

0 comments on commit 25d9b55

Please sign in to comment.