Skip to content

Commit

Permalink
Add support for textDocument/documentHighlight for XML Schema types
Browse files Browse the repository at this point in the history
Fix #470


Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Jun 26, 2019
1 parent 0d20197 commit e7635ce
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
import org.eclipse.lsp4xml.extensions.xsd.contentmodel.CMXSDContentModelProvider;
import org.eclipse.lsp4xml.extensions.xsd.participants.XSDCompletionParticipant;
import org.eclipse.lsp4xml.extensions.xsd.participants.XSDDefinitionParticipant;
import org.eclipse.lsp4xml.extensions.xsd.participants.XSDHighlightingParticipant;
import org.eclipse.lsp4xml.extensions.xsd.participants.XSDReferenceParticipant;
import org.eclipse.lsp4xml.extensions.xsd.participants.diagnostics.XSDDiagnosticsParticipant;
import org.eclipse.lsp4xml.services.extensions.ICompletionParticipant;
import org.eclipse.lsp4xml.services.extensions.IDefinitionParticipant;
import org.eclipse.lsp4xml.services.extensions.IHighlightingParticipant;
import org.eclipse.lsp4xml.services.extensions.IReferenceParticipant;
import org.eclipse.lsp4xml.services.extensions.IXMLExtension;
import org.eclipse.lsp4xml.services.extensions.XMLExtensionsRegistry;
Expand All @@ -41,13 +43,16 @@ public class XSDPlugin implements IXMLExtension {

private final IReferenceParticipant referenceParticipant;

private final IHighlightingParticipant highlightingParticipant;

private XSDURIResolverExtension uiResolver;

public XSDPlugin() {
completionParticipant = new XSDCompletionParticipant();
definitionParticipant = new XSDDefinitionParticipant();
diagnosticsParticipant = new XSDDiagnosticsParticipant();
referenceParticipant = new XSDReferenceParticipant();
highlightingParticipant = new XSDHighlightingParticipant();
}

@Override
Expand Down Expand Up @@ -76,6 +81,7 @@ public void start(InitializeParams params, XMLExtensionsRegistry registry) {
registry.registerDefinitionParticipant(definitionParticipant);
registry.registerDiagnosticsParticipant(diagnosticsParticipant);
registry.registerReferenceParticipant(referenceParticipant);
registry.registerHighlightingParticipant(highlightingParticipant);
}

@Override
Expand All @@ -85,5 +91,6 @@ public void stop(XMLExtensionsRegistry registry) {
registry.unregisterDefinitionParticipant(definitionParticipant);
registry.unregisterDiagnosticsParticipant(diagnosticsParticipant);
registry.unregisterReferenceParticipant(referenceParticipant);
registry.unregisterHighlightingParticipant(highlightingParticipant);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.eclipse.lsp4xml.extensions.xsd.participants;

import java.util.List;

import org.eclipse.lsp4j.DocumentHighlight;
import org.eclipse.lsp4j.DocumentHighlightKind;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4xml.dom.DOMAttr;
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.dom.DOMNode;
import org.eclipse.lsp4xml.extensions.xsd.utils.XSDUtils;
import org.eclipse.lsp4xml.extensions.xsd.utils.XSDUtils.BindingType;
import org.eclipse.lsp4xml.services.extensions.IHighlightingParticipant;
import org.eclipse.lsp4xml.utils.DOMUtils;
import org.eclipse.lsp4xml.utils.XMLPositionUtility;

public class XSDHighlightingParticipant implements IHighlightingParticipant {

@Override
public void findDocumentHighlights(DOMNode node, Position position, int offset, List<DocumentHighlight> highlights,
CancelChecker cancelChecker) {
DOMDocument document = node.getOwnerDocument();
if (!DOMUtils.isXSD(document)) {
return;
}
DOMAttr attr = node.findAttrAt(offset);
if (attr == null) {
return;
}
BindingType bindingType = XSDUtils.getBindingType(attr);
if (bindingType != BindingType.NONE) {
DOMAttr originAttr = attr;
highlights
.add(new DocumentHighlight(XMLPositionUtility.createRange(originAttr.getNodeAttrValue().getStart(),
originAttr.getNodeAttrValue().getEnd(), document), DocumentHighlightKind.Read));
XSDUtils.collectXSTypes(originAttr, bindingType, true, (targetNamespacePrefix, targetAttr) -> {
highlights.add(new DocumentHighlight(
XMLPositionUtility.createRange(targetAttr.getNodeAttrValue().getStart(),
targetAttr.getNodeAttrValue().getEnd(), targetAttr.getOwnerDocument()),
DocumentHighlightKind.Write));
});

} else if (XSDUtils.isXSTargetElement(attr.getOwnerElement())) {

DOMAttr targetAttr = attr;
highlights.add(new DocumentHighlight(
XMLPositionUtility.createRange(targetAttr.getNodeAttrValue().getStart(),
targetAttr.getNodeAttrValue().getEnd(), targetAttr.getOwnerDocument()),
DocumentHighlightKind.Write));
XSDUtils.collectXSReferenceTypes(targetAttr,
(origin, target) -> highlights.add(new DocumentHighlight(
XMLPositionUtility.createRange(origin.getNodeAttrValue().getStart(),
origin.getNodeAttrValue().getEnd(), origin.getOwnerDocument()),
DocumentHighlightKind.Read)),
cancelChecker);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ protected void findReferences(DOMNode node, Position position, int offset, Refer
node = attr;
}
XSDUtils.collectXSReferenceTypes(node,
(from, to) -> locations.add(XMLPositionUtility.createLocation(from.getNodeAttrValue())), cancelChecker);
(origin, target) -> locations.add(XMLPositionUtility.createLocation(origin.getNodeAttrValue())),
cancelChecker);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,7 @@ private static List<DOMAttr> getTargetAttrs(DOMNode referencedNode) {
Node n = nodes.item(i);
if (n.getNodeType() == Node.ELEMENT_NODE) {
DOMElement element = (DOMElement) n;
if (isXSComplexType(element) || isXSSimpleType(element) || isXSElement(element)
|| isXSGroup(element)) {
if (isXSTargetElement(element)) {
addReferenceNode(element, referencedNodes);
}
}
Expand Down Expand Up @@ -337,4 +336,9 @@ public static boolean isXSElement(Element element) {
public static boolean isXSGroup(Element element) {
return "group".equals(element.getLocalName());
}

public static boolean isXSTargetElement(Element element) {
return isXSComplexType(element) || isXSSimpleType(element) || isXSElement(element)
|| isXSGroup(element);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.eclipse.lsp4xml.dom.DOMElement;
import org.eclipse.lsp4xml.dom.DOMNode;
import org.eclipse.lsp4xml.dom.parser.TokenType;
import org.eclipse.lsp4xml.services.extensions.IHighlightingParticipant;
import org.eclipse.lsp4xml.services.extensions.XMLExtensionsRegistry;

/**
Expand All @@ -56,10 +57,22 @@ public List<DocumentHighlight> findDocumentHighlights(DOMDocument xmlDocument, P
return Collections.emptyList();
}
DOMNode node = xmlDocument.findNodeAt(offset);
if (node == null || !node.isElement() || ((DOMElement) node).getTagName() == null) {
if (node == null) {
return Collections.emptyList();
}
List<DocumentHighlight> highlights = new ArrayList<>();
fillWithDefaultHighlights(node, position, offset, highlights, cancelChecker);
fillWithCustomHighlights(node, position, offset, highlights, cancelChecker);
return highlights;
}

private static void fillWithDefaultHighlights(DOMNode node, Position position, int offset,
List<DocumentHighlight> highlights, CancelChecker cancelChecker) {
if (!node.isElement() || ((DOMElement) node).getTagName() == null) {
return;
}

DOMDocument xmlDocument = node.getOwnerDocument();
Range startTagRange = null;
Range endTagRange = null;
if (node.isCDATA()) {
Expand All @@ -73,39 +86,41 @@ public List<DocumentHighlight> findDocumentHighlights(DOMDocument xmlDocument, P

} catch (BadLocationException e) {
LOGGER.log(Level.SEVERE, "In XMLHighlighting the Node at provided Offset is a BadLocation", e);
return Collections.emptyList();
return;
}
if (covers(tempRange, position)) {
startPos.setCharacter(startPos.getCharacter() + 1); // {Cursor}<![CDATA[ -> <{Cursor}![CDATA[
endPos.setCharacter(endPos.getCharacter() - 1); // ]]>{Cursor} -> ]]{Cursor}>
Position startPosEnd = new Position(startPos.getLine(), startPos.getCharacter() + 8);
Position endPosStart = new Position(endPos.getLine(), endPos.getCharacter() - 2);
return getHighlightsList(new Range(startPos, startPosEnd), new Range(endPosStart, endPos));
fillHighlightsList(new Range(startPos, startPosEnd), new Range(endPosStart, endPos), highlights);
}
return Collections.emptyList();
} else if (node.isElement()) {
DOMElement element = (DOMElement) node;
startTagRange = getTagNameRange(TokenType.StartTag, node.getStart(), xmlDocument);
endTagRange = element.hasEndTag()
? getTagNameRange(TokenType.EndTag, element.getEndTagOpenOffset(), xmlDocument)
: null;
if (doesTagCoverPosition(startTagRange, endTagRange, position)) {
return getHighlightsList(startTagRange, endTagRange);
fillHighlightsList(startTagRange, endTagRange, highlights);
}
}
return Collections.emptyList();
}

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

List<DocumentHighlight> result = new ArrayList<>(2);
private static void fillHighlightsList(Range startTagRange, Range endTagRange, List<DocumentHighlight> result) {
if (startTagRange != null) {
result.add(new DocumentHighlight(startTagRange, DocumentHighlightKind.Read));
}
if (endTagRange != null) {
result.add(new DocumentHighlight(endTagRange, DocumentHighlightKind.Read));
}
return result;
}

private void fillWithCustomHighlights(DOMNode node, Position position, int offset,
List<DocumentHighlight> highlights, CancelChecker cancelChecker) {
// Consume highlighting participant
for (IHighlightingParticipant highlightingParticipant : extensionsRegistry.getHighlightingParticipants()) {
highlightingParticipant.findDocumentHighlights(node, position, offset,highlights, cancelChecker);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.eclipse.lsp4xml.services.extensions;

import java.util.List;

import org.eclipse.lsp4j.DocumentHighlight;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4xml.dom.DOMNode;

public interface IHighlightingParticipant {

void findDocumentHighlights(DOMNode node, Position position, int offset, List<DocumentHighlight> highlights,
CancelChecker cancelChecker);

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public class XMLExtensionsRegistry implements IComponentProvider{
private final List<IDocumentLinkParticipant> documentLinkParticipants;
private final List<IDefinitionParticipant> definitionParticipants;
private final List<IReferenceParticipant> referenceParticipants;

private final List<IHighlightingParticipant> highlightingParticipants;

private IXMLDocumentProvider documentProvider;

private InitializeParams params;
Expand All @@ -62,6 +63,7 @@ public XMLExtensionsRegistry() {
documentLinkParticipants = new ArrayList<>();
definitionParticipants = new ArrayList<>();
referenceParticipants = new ArrayList<>();
highlightingParticipants = new ArrayList<>();
resolverExtensionManager = new URIResolverExtensionManager();
components = new HashMap<>();
registerComponent(resolverExtensionManager);
Expand Down Expand Up @@ -132,6 +134,11 @@ public Collection<IReferenceParticipant> getReferenceParticipants() {
return referenceParticipants;
}

public Collection<IHighlightingParticipant> getHighlightingParticipants() {
initializeIfNeeded();
return highlightingParticipants;
}

public void initializeIfNeeded() {
if (initialized) {
return;
Expand Down Expand Up @@ -223,6 +230,14 @@ public void unregisterReferenceParticipant(IReferenceParticipant referencePartic
referenceParticipants.add(referenceParticipant);
}

public void registerHighlightingParticipant(IHighlightingParticipant highlightingParticipant) {
highlightingParticipants.add(highlightingParticipant);
}

public void unregisterHighlightingParticipant(IHighlightingParticipant highlightingParticipant) {
highlightingParticipants.add(highlightingParticipant);
}

/**
* Returns the XML Document provider and null otherwise.
*
Expand All @@ -244,4 +259,5 @@ public void setDocumentProvider(IXMLDocumentProvider documentProvider) {
public URIResolverExtensionManager getResolverExtensionManager() {
return resolverExtensionManager;
}

}

0 comments on commit e7635ce

Please sign in to comment.