Skip to content

Commit

Permalink
Display attribute in outline (see #226)
Browse files Browse the repository at this point in the history
  • Loading branch information
angelozerr committed Nov 30, 2018
1 parent 2e155e6 commit 8af3594
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
Expand Down Expand Up @@ -756,4 +759,13 @@ public boolean isDTD() {
}
return false;
}

public Collection<DOMNode> getDTDAttrList(String elementName) {
DOMDocumentType docType = getDoctype();
if (docType == null) {
return Collections.emptyList();
}
return docType.getChildren().stream().filter(DOMNode::isDTDAttListDecl)
.filter(n -> elementName.equals(((DTDAttlistDecl) n).getElementName())).collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,18 @@ public DOMDocument parse(TextDocument document, URIResolverExtensionManager reso
break;
}

case DTDAttlistElementName: {
DTDAttlistDecl attribute = (DTDAttlistDecl) curr;
attribute.elementName = scanner.getTokenText();
break;
}

case DTDAttlistAttributeName: {
DTDAttlistDecl attribute = (DTDAttlistDecl) curr;
attribute.name = scanner.getTokenText();
break;
}

case DTDStartEntity: {
DTDEntityDecl child = new DTDEntityDecl(scanner.getTokenOffset(), text.length(), (DOMDocumentType) curr);
curr.addChild(child);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ public class DTDAttlistDecl extends DOMNode {
private final DOMDocumentType ownerDTDDocument;

String name;

String elementName;

public DTDAttlistDecl(int start, int end, DOMDocumentType ownerDTDDocument) {
super(start, end, ownerDTDDocument.getOwnerDocument());
this.ownerDTDDocument = ownerDTDDocument;
Expand All @@ -36,9 +37,23 @@ public String getNodeName() {
return getName();
}

/**
* Returns the attribute name
*
* @return the attribute name
*/
public String getName() {
return name;
}

/**
* Returns the element name
*
* @return the element name
*/
public String getElementName() {
return elementName;
}

@Override
public short getNodeType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ public String getName() {
public short getNodeType() {
return DOMNode.DTD_ELEMENT_DECL_NODE;
}

/**
* Returns the offset of the end of tag <!ELEMENT
* @return the offset of the end of tag <!ELEMENT
*
* @return the offset of the end of tag <!ELEMENT
*/
public int getEndElementTag() {
return getStart() + "<!ELEMENT".length();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ TokenType internalScan() {

if (!stream.advanceIfRegExp(Constants.ELEMENT_NAME_REGEX).equals("")) {
state = ScannerState.DTDAfterAttlistElementName;
return finishToken(offset, TokenType.DTDAttlistAttributeName);
return finishToken(offset, TokenType.DTDAttlistElementName);
}

if (stream.advanceIfChar(_RAN)) { // >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package org.eclipse.lsp4xml.services;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand All @@ -23,6 +24,7 @@
import org.eclipse.lsp4xml.commons.BadLocationException;
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.dom.DOMNode;
import org.eclipse.lsp4xml.dom.DTDAttlistDecl;
import org.eclipse.lsp4xml.dom.DTDElementDecl;
import org.eclipse.lsp4xml.services.extensions.XMLExtensionsRegistry;
import org.w3c.dom.DocumentType;
Expand All @@ -44,39 +46,55 @@ public XMLSymbolsProvider(XMLExtensionsRegistry extensionsRegistry) {

public List<SymbolInformation> findDocumentSymbols(DOMDocument xmlDocument) {
List<SymbolInformation> symbols = new ArrayList<>();
boolean isDTD = xmlDocument.isDTD();
xmlDocument.getRoots().forEach(node -> {
try {
provideFileSymbolsInternal(node, "", symbols);
provideFileSymbolsInternal(node, "", symbols, (node.isDoctype() && isDTD), true);
} catch (BadLocationException e) {
LOGGER.log(Level.SEVERE, "XMLSymbolsProvider was given a BadLocation by a 'node' variable", e);
}
});
return symbols;
}

private void provideFileSymbolsInternal(DOMNode node, String container, List<SymbolInformation> symbols)
throws BadLocationException {
if (!isNodeSymbol(node)) {
private void provideFileSymbolsInternal(DOMNode node, String container, List<SymbolInformation> symbols,
boolean ignoreNode, boolean checkSymbol) throws BadLocationException {
if (checkSymbol && !isNodeSymbol(node)) {
return;
}
String name = nodeToName(node);
String name = ignoreNode ? "" : nodeToName(node);
DOMDocument xmlDocument = node.getOwnerDocument();
Position start = xmlDocument.positionAt(node.getStart());
Position end = xmlDocument.positionAt(node.getEnd());
Range range = new Range(start, end);
Location location = new Location(xmlDocument.getDocumentURI(), range);
SymbolInformation symbol = new SymbolInformation(name, getSymbolKind(node), location, container);

symbols.add(symbol);

if (!ignoreNode) {
symbols.add(symbol);
}
node.getChildren().forEach(child -> {
try {
provideFileSymbolsInternal(child, name, symbols);
provideFileSymbolsInternal(child, name, symbols, false, true);
} catch (BadLocationException e) {
LOGGER.log(Level.SEVERE, "XMLSymbolsProvider was given a BadLocation by the provided 'node' variable",
e);
}
});
if (node.isDTDElementDecl()) {
String elementName = node.getNodeName();
// Display DTD <!ATTLIST as children of the DTD element declaration !ELEMENT
Collection<DOMNode> attributes = node.getOwnerDocument().getDTDAttrList(elementName);
attributes.forEach(child -> {
try {
provideFileSymbolsInternal(child, elementName, symbols, false, false);
} catch (BadLocationException e) {
LOGGER.log(Level.SEVERE,
"XMLSymbolsProvider was given a BadLocation by the provided 'node' variable", e);
}
});

}

}

Expand All @@ -93,7 +111,7 @@ private SymbolKind getSymbolKind(DOMNode node) {

private boolean isNodeSymbol(DOMNode node) {
return node.isElement() || node.isDoctype() || node.isProcessingInstruction() || node.isProlog()
|| node.isDTDElementDecl() || node.isDTDAttListDecl() || node.isDTDEntityDecl();
|| node.isDTDElementDecl() || node.isDTDEntityDecl();
}

private static String nodeToName(DOMNode node) {
Expand All @@ -107,7 +125,8 @@ private static String nodeToName(DOMNode node) {
} else if (node.isDTDElementDecl()) {
name = ((DTDElementDecl) node).getName();
} else if (node.isDTDAttListDecl()) {
name = "AttList (TODO)";
DTDAttlistDecl attr = (DTDAttlistDecl) node;
name = attr.getElementName() + "/@" + attr.getName();
} else if (node.isDTDEntityDecl()) {
name = node.getNodeName();
}
Expand Down

0 comments on commit 8af3594

Please sign in to comment.