Skip to content

Commit

Permalink
Hover for referenced entities
Browse files Browse the repository at this point in the history
Fixes eclipse#663

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed May 25, 2020
1 parent 569ebd4 commit 2bfe3d0
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@

import org.eclipse.lemminx.extensions.entities.participants.EntitiesCompletionParticipant;
import org.eclipse.lemminx.extensions.entities.participants.EntitiesDefinitionParticipant;
import org.eclipse.lemminx.extensions.entities.participants.EntitiesHoverParticipant;
import org.eclipse.lemminx.services.extensions.ICompletionParticipant;
import org.eclipse.lemminx.services.extensions.IDefinitionParticipant;
import org.eclipse.lemminx.services.extensions.IHoverParticipant;
import org.eclipse.lemminx.services.extensions.IXMLExtension;
import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry;
import org.eclipse.lemminx.services.extensions.save.ISaveContext;
Expand All @@ -30,18 +32,23 @@ public class EntitiesPlugin implements IXMLExtension {

private IDefinitionParticipant definitionParticipant;

private IHoverParticipant hoverParticipant;

@Override
public void start(InitializeParams params, XMLExtensionsRegistry registry) {
completionParticipant = new EntitiesCompletionParticipant();
registry.registerCompletionParticipant(completionParticipant);
definitionParticipant = new EntitiesDefinitionParticipant();
registry.registerDefinitionParticipant(definitionParticipant);
hoverParticipant = new EntitiesHoverParticipant();
registry.registerHoverParticipant(hoverParticipant);
}

@Override
public void stop(XMLExtensionsRegistry registry) {
registry.unregisterCompletionParticipant(completionParticipant);
registry.unregisterDefinitionParticipant(definitionParticipant);
registry.unregisterHoverParticipant(hoverParticipant);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
* Copyright (c) 2020 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
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*/
package org.eclipse.lemminx.extensions.entities.participants;

import java.util.Collection;
import java.util.List;

import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.dom.DOMDocumentType;
import org.eclipse.lemminx.dom.DTDEntityDecl;
import org.eclipse.lemminx.extensions.contentmodel.model.CMDocument;
import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager;
import org.eclipse.lemminx.extensions.entities.EntitiesDocumentationUtils;
import org.eclipse.lemminx.services.extensions.HoverParticipantAdapter;
import org.eclipse.lemminx.services.extensions.IHoverRequest;
import org.eclipse.lemminx.utils.XMLPositionUtility;
import org.eclipse.lsp4j.MarkupContent;
import org.eclipse.lsp4j.MarkupKind;
import org.eclipse.lsp4j.Range;
import org.w3c.dom.Entity;
import org.w3c.dom.NamedNodeMap;

/**
* Entities hover used in a text node (ex : &amp;).
*
*/
public class EntitiesHoverParticipant extends HoverParticipantAdapter {

@Override
public String onText(IHoverRequest request) throws Exception {
DOMDocument document = request.getXMLDocument();
int offset = request.getOffset();
String text = document.getText();
int entityReferenceStart = XMLPositionUtility.getEntityReferenceStartOffset(text, offset);
if (entityReferenceStart == -1) {
return null;
}
// the start offset is the amp character, ignore it
entityReferenceStart++;
int entityReferenceEnd = XMLPositionUtility.getEntityReferenceEndOffset(text, offset);
// Find hover of the entity
// abcd &loc|al; --> in this case search local entity
if (text.charAt(entityReferenceEnd - 1) == ';') {
entityReferenceEnd--;
}
String entityName = text.substring(entityReferenceStart, entityReferenceEnd);
Range entityRange = XMLPositionUtility.createRange(entityReferenceStart, entityReferenceEnd, document);
MarkupContent entityContent = searchInInternalEntities(entityName, entityRange, document, request);
if (entityContent == null) {
entityContent = searchInExternalEntities(entityName, entityRange, document, request);
}
if (entityContent != null) {
return entityContent.getValue();
}
return null;
}

/**
* Search the given entity name in the internal entities.
*
* @param document the DOM document.
* @param entityName the entity name.
* @param entityRange the entity range.
* @param locations the location links
*/
private static MarkupContent searchInInternalEntities(String entityName, Range entityRange, DOMDocument document,
IHoverRequest request) {
DOMDocumentType docType = document.getDoctype();
if (docType == null) {
return null;
}
// Loop for entities declared in the DOCTYPE of the document
NamedNodeMap entities = docType.getEntities();
for (int i = 0; i < entities.getLength(); i++) {
DTDEntityDecl entity = (DTDEntityDecl) entities.item(i);
if (entityName.equals(entityName)) {
boolean markdown = request.canSupportMarkupKind(MarkupKind.MARKDOWN);
return EntitiesDocumentationUtils.getDocumentation(entity.getName(), entity.getNotationName(), true,
false, markdown);
}
}
return null;
}

/**
* Search the given entity name in the external entities.
*
* @param document the DOM document.
* @param entityName the entity name.
* @param entityRange the entity range.
* @param locations the location links
* @param request the definition request.
* @return
*/
private static MarkupContent searchInExternalEntities(String entityName, Range entityRange, DOMDocument document,
IHoverRequest request) {
ContentModelManager contentModelManager = request.getComponent(ContentModelManager.class);
Collection<CMDocument> cmDocuments = contentModelManager.findCMDocument(document, null, false);
for (CMDocument cmDocument : cmDocuments) {
List<Entity> entities = cmDocument.getEntities();
for (Entity ent : entities) {
DTDEntityDecl entity = (DTDEntityDecl) ent;
if (entityName.equals(entityName)) {
boolean markdown = request.canSupportMarkupKind(MarkupKind.MARKDOWN);
return EntitiesDocumentationUtils.getDocumentation(entity.getName(), entity.getNotationName(), true,
false, markdown);
}
}
}
return null;
}

}

0 comments on commit 2bfe3d0

Please sign in to comment.