Skip to content

Commit

Permalink
Discrepancy in completion between prefixed and default namespaces
Browse files Browse the repository at this point in the history
Fix #311

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Jun 28, 2019
1 parent 7d2d324 commit 8f7c821
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,23 @@
*/
public interface CMDocument {

/**
* Returns true if the model document defines the given namespace and false
* otherwise.
*
* @param namespaceURI
* @return true if the model document defines the given namespace and false
* otherwise.
*/
boolean hasNamespace(String namespaceURI);

/**
* Returns the elements declaration of the model document root.
*
* @return the elements declaration of the model document root.
*/
Collection<CMElementDeclaration> getElements();

/**
* Returns the declared element which matches the given XML element and null
* otherwise.
Expand All @@ -32,6 +47,11 @@ public interface CMDocument {
*/
CMElementDeclaration findCMElement(DOMElement element, String namespace);

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,11 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response)
String schemaURI;
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 = contentModelManager.findCMDocument(document, null);
CMDocument cmDocument = contentModelManager.findCMDocument(document, null);
if (cmDocument != null) {
schemaURI = cmDocument.getURI();
fillWithChildrenElementDeclaration(null, cmDocument.getElements(), null, false, request, response,
Expand All @@ -60,9 +59,10 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response)
}
// Try to retrieve XML Schema/DTD element declaration for the parent element
// where completion was triggered.
cmDocument = contentModelManager.findCMDocument(parentElement, parentElement.getNamespaceURI());
final CMDocument cmRootDocument = contentModelManager.findCMDocument(parentElement,
parentElement.getNamespaceURI());

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

Expand All @@ -72,17 +72,21 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response)
request, response, schemaURI);
}
if (parentElement.isDocumentElement()) {
// root document element
// completion on root document element
Collection<String> prefixes = parentElement.getAllPrefixes();
for (String prefix : prefixes) {
if (defaultPrefix != null && prefix.equals(defaultPrefix)) {
continue;
}
String namespaceURI = parentElement.getNamespaceURI(prefix);
cmDocument = contentModelManager.findCMDocument(parentElement, namespaceURI);
if (cmDocument != null) {
fillWithChildrenElementDeclaration(parentElement, cmDocument.getElements(), prefix, true,
request, response, cmDocument.getURI());
if (!cmRootDocument.hasNamespace(namespaceURI)) {
// The model document root doesn't define the namespace, try to load the
// external model document (XML Schema, DTD)
CMDocument cmDocument = contentModelManager.findCMDocument(parentElement, namespaceURI);
if (cmDocument != null) {
fillWithChildrenElementDeclaration(parentElement, cmDocument.getElements(), prefix, true,
request, response, cmRootDocument.getURI());
}
}
}
}
Expand Down Expand Up @@ -121,8 +125,8 @@ private void fillWithChildrenElementDeclaration(DOMElement element, Collection<C
}

@Override
public void onAttributeName(boolean generateValue, ICompletionRequest request,
ICompletionResponse response) throws Exception {
public void onAttributeName(boolean generateValue, ICompletionRequest request, ICompletionResponse response)
throws Exception {
// otherwise, manage completion based on XML Schema, DTD.
DOMElement parentElement = request.getNode().isElement() ? (DOMElement) request.getNode() : null;
if (parentElement == null) {
Expand Down Expand Up @@ -171,8 +175,8 @@ private void fillAttributesWithCMAttributeDeclarations(DOMElement parentElement,
}

@Override
public void onAttributeValue(String valuePrefix, ICompletionRequest request,
ICompletionResponse response) throws Exception {
public void onAttributeValue(String valuePrefix, ICompletionRequest request, ICompletionResponse response)
throws Exception {
DOMElement parentElement = request.getNode().isElement() ? (DOMElement) request.getNode() : null;
if (parentElement == null) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,18 @@ public class CMDTDDocument extends XMLDTDLoader implements CMDocument {
private Set<String> hierarchies;
private String uri;

public CMDTDDocument() {}
public CMDTDDocument() {
}

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

@Override
public boolean hasNamespace(String namespaceURI) {
return false;
}

@Override
public Collection<CMElementDeclaration> getElements() {
if (elements == null) {
Expand All @@ -67,10 +73,8 @@ public Collection<CMElementDeclaration> getElements() {
return elements;
}


/**
* Returns the URI of this document, is none was provided this
* returns null.
* Returns the URI of this document, is none was provided this returns null.
*/
@Override
public String getURI() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ public CMXSDDocument(XSModel model, String uri) {
this.uri = uri;
}

@Override
public boolean hasNamespace(String namespaceURI) {
if (namespaceURI == null || model.getNamespaces() == null) {
return false;
}
return model.getNamespaces().contains(namespaceURI);
}

@Override
public String getURI() {
return uri;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,38 @@ public void issue214() throws BadLocationException {
c("ComplexType", "<ComplexType Name=\"\"></ComplexType>"));
}

/**
* @see https://github.com/angelozerr/lsp4xml/issues/311
*
* @throws BadLocationException
*/
@Test
public void issue311() throws BadLocationException {
// with xmlns:edm="http://docs.oasis-open.org/odata/ns/edm"
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
+ "<edmx:Edmx xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\" xmlns:edm=\"http://docs.oasis-open.org/odata/ns/edm\" Version=\"4.0\">\r\n"
+ " | \r\n" //
+ "</edmx:Edmx>";
XMLAssert.testCompletionFor(xml, "src/test/resources/catalogs/catalog.xml", "test.xsd",
4 /*
* edmx:DataServices, <edmx:DataServices, #region, #endregion AND NOT
* edm:Annotation
*/, c("edmx:DataServices", "<edmx:DataServices></edmx:DataServices>"), //
c("edmx:Reference", "<edmx:Reference Uri=\"\"></edmx:Reference>"));

// with xmlns="http://docs.oasis-open.org/odata/ns/edm"
xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
+ "<edmx:Edmx xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\" xmlns=\"http://docs.oasis-open.org/odata/ns/edm\" Version=\"4.0\">\r\n"
+ " | \r\n" //
+ "</edmx:Edmx>";
XMLAssert.testCompletionFor(xml, "src/test/resources/catalogs/catalog.xml", "test.xsd",
4 /*
* edmx:DataServices, <edmx:DataServices, #region, #endregion AND NOT
* edm:Annotation
*/, c("edmx:DataServices", "<edmx:DataServices></edmx:DataServices>"), //
c("edmx:Reference", "<edmx:Reference Uri=\"\"></edmx:Reference>"));
}

@Test
public void xsiCompletionTestAllItems() throws BadLocationException {
String xml =
Expand Down

0 comments on commit 8f7c821

Please sign in to comment.