Skip to content

Commit

Permalink
Add support for textDocument/typeDefinition from XML to XMLSchema/DTD
Browse files Browse the repository at this point in the history
Fix #371

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Jul 17, 2019
1 parent 0c41043 commit c15c6f5
Show file tree
Hide file tree
Showing 34 changed files with 1,193 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ public void triggerValidationIfNeeded() {
private boolean codeActionLiteralSupport;
private boolean hierarchicalDocumentSymbolSupport;
private boolean definitionLinkSupport;

private boolean typeDefinitionLinkSupport;

public XMLTextDocumentService(XMLLanguageServer xmlLanguageServer) {
this.xmlLanguageServer = xmlLanguageServer;
DOMParser parser = DOMParser.getInstance();
Expand All @@ -157,6 +158,9 @@ public void updateClientCapabilities(ClientCapabilities capabilities, ExtendedCl
definitionLinkSupport = textDocumentClientCapabilities.getDefinition() != null
&& textDocumentClientCapabilities.getDefinition().getLinkSupport() != null
&& textDocumentClientCapabilities.getDefinition().getLinkSupport();
typeDefinitionLinkSupport = textDocumentClientCapabilities.getTypeDefinition() != null
&& textDocumentClientCapabilities.getTypeDefinition().getLinkSupport() != null
&& textDocumentClientCapabilities.getTypeDefinition().getLinkSupport();
}
if (extendedClientCapabilities != null) {
// Extended client capabilities
Expand Down Expand Up @@ -304,6 +308,23 @@ public CompletableFuture<Either<List<? extends Location>, List<? extends Locatio
return Either.forLeft(locations);
});
}

@Override
public CompletableFuture<Either<List<? extends Location>, List<? extends LocationLink>>> typeDefinition(
TextDocumentPositionParams params) {
return computeDOMAsync(params.getTextDocument(), (cancelChecker, xmlDocument) -> {
if (typeDefinitionLinkSupport) {
return Either.forRight(
getXMLLanguageService().findTypeDefinition(xmlDocument, params.getPosition(), cancelChecker));
}
List<? extends Location> locations = getXMLLanguageService()
.findTypeDefinition(xmlDocument, params.getPosition(), cancelChecker) //
.stream() //
.map(locationLink -> XMLPositionUtility.toLocation(locationLink)) //
.collect(Collectors.toList());
return Either.forLeft(locations);
});
}

@Override
public CompletableFuture<List<? extends Location>> references(ReferenceParams params) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
import org.eclipse.lsp4xml.extensions.contentmodel.participants.ContentModelCompletionParticipant;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.ContentModelDocumentLinkParticipant;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.ContentModelHoverParticipant;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.ContentModelTypeDefinitionParticipant;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.diagnostics.ContentModelDiagnosticsParticipant;
import org.eclipse.lsp4xml.extensions.contentmodel.settings.ContentModelSettings;
import org.eclipse.lsp4xml.services.extensions.ICodeActionParticipant;
import org.eclipse.lsp4xml.services.extensions.ICompletionParticipant;
import org.eclipse.lsp4xml.services.extensions.IDocumentLinkParticipant;
import org.eclipse.lsp4xml.services.extensions.IHoverParticipant;
import org.eclipse.lsp4xml.services.extensions.ITypeDefinitionParticipant;
import org.eclipse.lsp4xml.services.extensions.IXMLExtension;
import org.eclipse.lsp4xml.services.extensions.XMLExtensionsRegistry;
import org.eclipse.lsp4xml.services.extensions.diagnostics.IDiagnosticsParticipant;
import org.eclipse.lsp4xml.services.extensions.save.ISaveContext;
import org.eclipse.lsp4xml.uriresolver.URIResolverExtensionManager;
import org.eclipse.lsp4xml.utils.DOMUtils;
Expand All @@ -32,22 +37,25 @@ public class ContentModelPlugin implements IXMLExtension {

private final IHoverParticipant hoverParticipant;

private final ContentModelDiagnosticsParticipant diagnosticsParticipant;
private final IDiagnosticsParticipant diagnosticsParticipant;

private final ContentModelCodeActionParticipant codeActionParticipant;
private final ICodeActionParticipant codeActionParticipant;

private final ContentModelDocumentLinkParticipant documentLinkParticipant;
private final IDocumentLinkParticipant documentLinkParticipant;

private final ITypeDefinitionParticipant typeDefinitionParticipant;

ContentModelManager contentModelManager;

private ContentModelSettings cmSettings;

public ContentModelPlugin() {
completionParticipant = new ContentModelCompletionParticipant();
hoverParticipant = new ContentModelHoverParticipant();
diagnosticsParticipant = new ContentModelDiagnosticsParticipant(this);
codeActionParticipant = new ContentModelCodeActionParticipant();
documentLinkParticipant = new ContentModelDocumentLinkParticipant();
typeDefinitionParticipant = new ContentModelTypeDefinitionParticipant();
}

@Override
Expand Down Expand Up @@ -99,8 +107,7 @@ private void updateSettings(ContentModelSettings settings, ISaveContext context)
}
if (settings.getFileAssociations() != null) {
// Update XML file associations
boolean fileAssociationsChanged = contentModelManager
.setFileAssociations(settings.getFileAssociations());
boolean fileAssociationsChanged = contentModelManager.setFileAssociations(settings.getFileAssociations());
if (fileAssociationsChanged) {
// Validate all opened XML files
context.collectDocumentToValidate(d -> {
Expand Down Expand Up @@ -130,6 +137,7 @@ public void start(InitializeParams params, XMLExtensionsRegistry registry) {
registry.registerDiagnosticsParticipant(diagnosticsParticipant);
registry.registerCodeActionParticipant(codeActionParticipant);
registry.registerDocumentLinkParticipant(documentLinkParticipant);
registry.registerTypeDefinitionParticipant(typeDefinitionParticipant);
}

@Override
Expand All @@ -139,6 +147,7 @@ public void stop(XMLExtensionsRegistry registry) {
registry.unregisterDiagnosticsParticipant(diagnosticsParticipant);
registry.unregisterCodeActionParticipant(codeActionParticipant);
registry.unregisterDocumentLinkParticipant(documentLinkParticipant);
registry.unregisterTypeDefinitionParticipant(typeDefinitionParticipant);
}

public ContentModelSettings getContentModelSettings() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

import java.util.Collection;

import org.eclipse.lsp4j.LocationLink;
import org.eclipse.lsp4xml.dom.DOMElement;
import org.eclipse.lsp4xml.dom.DOMNode;

/**
* Content model document which abstracts element declaration from a given
Expand Down Expand Up @@ -48,10 +50,17 @@ public interface CMDocument {
CMElementDeclaration findCMElement(DOMElement element, String namespace);

/**
* Returns the URI of the model document.
* Returns the root URI of the model document.
*
* @return the URI of the model document.
* @return the root URI of the model document.
*/
String getURI();

/**
* Returns the location of the type definition of the given node.
*
* @param node the node
* @return the location of the type definition of the given node.
*/
LocationLink findTypeLocation(DOMNode node);
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,6 @@ default String getName(String prefix) {

Collection<String> getEnumerationValues();

String getDocumentURI();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Copyright (c) 2019 Red Hat, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*/
package org.eclipse.lsp4xml.extensions.contentmodel.participants;

import java.util.List;

import org.eclipse.lsp4j.LocationLink;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4xml.dom.DOMAttr;
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.dom.DOMElement;
import org.eclipse.lsp4xml.dom.DOMNode;
import org.eclipse.lsp4xml.extensions.contentmodel.model.CMDocument;
import org.eclipse.lsp4xml.extensions.contentmodel.model.ContentModelManager;
import org.eclipse.lsp4xml.services.extensions.AbstractTypeDefinitionParticipant;
import org.eclipse.lsp4xml.services.extensions.ITypeDefinitionRequest;

/**
* Extension to support XML type definition based on content model (XML Schema
* type definition, etc)
*/
public class ContentModelTypeDefinitionParticipant extends AbstractTypeDefinitionParticipant {

@Override
protected boolean match(DOMDocument document) {
return true;
}

@Override
protected void doFindTypeDefinition(ITypeDefinitionRequest request, List<LocationLink> locations,
CancelChecker cancelChecker) {
ContentModelManager contentModelManager = request.getComponent(ContentModelManager.class);
DOMNode node = request.getNode();
if (node == null) {
return;
}
DOMElement element = null;
if (node.isElement()) {
element = (DOMElement) node;
} else if (node.isAttribute()) {
element = ((DOMAttr) node).getOwnerElement();
}
if (element != null) {
CMDocument cmDocument = contentModelManager.findCMDocument(element.getOwnerDocument(),
element.getNamespaceURI());
if (cmDocument != null) {
LocationLink location = cmDocument.findTypeLocation(node);
if (location != null) {
locations.add(location);
}
}

}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.grammars.Grammar;
import org.apache.xerces.xni.parser.XMLInputSource;
import org.eclipse.lsp4j.LocationLink;
import org.eclipse.lsp4xml.dom.DOMElement;
import org.eclipse.lsp4xml.dom.DOMNode;
import org.eclipse.lsp4xml.extensions.contentmodel.model.CMAttributeDeclaration;
import org.eclipse.lsp4xml.extensions.contentmodel.model.CMDocument;
import org.eclipse.lsp4xml.extensions.contentmodel.model.CMElementDeclaration;
Expand Down Expand Up @@ -182,4 +184,9 @@ void collectAttributesDeclaration(CMDTDElementDeclaration elementDecl, List<CMAt
index = grammar.getNextAttributeDeclIndex(index);
}
}

@Override
public LocationLink findTypeLocation(DOMNode node) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,8 @@ public int getIndex() {
return index;
}

@Override
public String getDocumentURI() {
return document.getURI();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
import java.util.List;

import org.eclipse.lsp4j.LocationLink;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.dom.DOMNode;
import org.eclipse.lsp4xml.extensions.references.XMLReferencesManager;
import org.eclipse.lsp4xml.services.extensions.AbstractDefinitionParticipant;
import org.eclipse.lsp4xml.services.extensions.IDefinitionRequest;
import org.eclipse.lsp4xml.utils.XMLPositionUtility;

public class XMLReferencesDefinitionParticipant extends AbstractDefinitionParticipant {
Expand All @@ -29,8 +29,9 @@ protected boolean match(DOMDocument document) {
}

@Override
protected void findDefinition(DOMNode origin, Position position, int offset, List<LocationLink> locations,
protected void doFindDefinition(IDefinitionRequest request, List<LocationLink> locations,
CancelChecker cancelChecker) {
DOMNode origin = request.getNode();
XMLReferencesManager.getInstance().collect(origin, target -> {
LocationLink location = XMLPositionUtility.createLocationLink(origin, target);
locations.add(location);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public boolean isRequired() {
return attributeUse.getRequired();
}

private XSAttributeDeclaration getAttrDeclaration() {
XSAttributeDeclaration getAttrDeclaration() {
return attributeUse.getAttrDeclaration();
}

Expand Down
Loading

0 comments on commit c15c6f5

Please sign in to comment.