Skip to content

Commit

Permalink
resolve and show documentation for field and group
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Timofte committed Oct 5, 2024
1 parent f49faf4 commit f6f68be
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;

import static ac.quant.quickfixspec.common.PsiUtils.isComponentsDeclaration;
import static ac.quant.quickfixspec.common.PsiUtils.isTagDeclaration;

@Slf4j
public class QuickFixPsiReferenceProvider extends PsiReferenceProvider {
Expand All @@ -23,7 +23,7 @@ public class QuickFixPsiReferenceProvider extends PsiReferenceProvider {

XmlAttributeValue attributeValue = (XmlAttributeValue) element;

if (isComponentsDeclaration(attributeValue)) {
if (isTagDeclaration(attributeValue)) {
return PsiReference.EMPTY_ARRAY;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;


import static ac.quant.quickfixspec.common.PsiUtils.findComponent;
import static ac.quant.quickfixspec.common.PsiUtils.getRootTag;
import static ac.quant.quickfixspec.common.PsiUtils.*;

@Slf4j
public class QuickfixPsiReference implements PsiReference {

private final XmlAttributeValue attributeValue;
private final XmlTag rootTag;
private final String parentTagName;

public QuickfixPsiReference(final XmlAttributeValue attributeValue) {
this.attributeValue = attributeValue;
this.parentTagName = ((XmlTag) attributeValue.getParent().getParent()).getName();
this.rootTag = getRootTag(attributeValue);
}

Expand All @@ -37,8 +37,8 @@ public QuickfixPsiReference(final XmlAttributeValue attributeValue) {

@Override
public @Nullable PsiElement resolve() {
String componentName = attributeValue.getValue();
return findComponent(rootTag, componentName);
String tagName = attributeValue.getValue();
return findDefinition(tagName, parentTagName, rootTag);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@
import com.intellij.psi.xml.XmlAttributeValue;
import org.jetbrains.annotations.NotNull;
import lombok.extern.slf4j.Slf4j;
import static ac.quant.quickfixspec.common.PsiUtils.NAME_ATTRIBUTE;
import static ac.quant.quickfixspec.common.PsiUtils.TAGS_WITH_DEFINITION;

@Slf4j
public class QuickfixSpecPsiReferenceContributor extends PsiReferenceContributor {


@Override
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {


PsiElementPattern.Capture<XmlAttributeValue> psiElementCapture = PlatformPatterns.psiElement(XmlAttributeValue.class)
.withParent(XmlPatterns.xmlAttribute().withName("name"))
.withSuperParent(2, XmlPatterns.xmlTag().withName("component"));
.withParent(XmlPatterns.xmlAttribute().withName(NAME_ATTRIBUTE))
.withSuperParent(2, XmlPatterns.xmlTag().withName(TAGS_WITH_DEFINITION));

registrar.registerReferenceProvider(
psiElementCapture,
Expand Down
44 changes: 36 additions & 8 deletions src/main/java/ac/quant/quickfixspec/common/PsiUtils.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
package ac.quant.quickfixspec.common;

import com.github.weisj.jsvg.S;

Check warning on line 3 in src/main/java/ac/quant/quickfixspec/common/PsiUtils.java

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused import

Unused import `import com.github.weisj.jsvg.S;`
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.Nullable;

import java.util.Map;

public class PsiUtils {

public final static String NAME_ATTRIBUTE = "name";

public static final Map<String, String> DEFINITION_GROUP_NAME = Map.of(
"component", "components",
"group", "fields",
"field", "fields"
);

public static final Map<String, String> DEFINITION_TAG_NAME = Map.of(
"component", "component",
"group", "field",
"field", "field"
);
public final static String[] TAGS_WITH_DEFINITION = new String[]{"component", "group", "field"};


// Helper method to navigate to the root tag
public static @Nullable XmlTag getRootTag(PsiElement element) {
Expand All @@ -22,25 +40,35 @@ public class PsiUtils {
return null;
}

public static @Nullable XmlTag findComponent(final XmlTag rootTag, final String componentName) {
public static @Nullable XmlTag findDefinition(final String tagName , final String parentTagName, final XmlTag rootTag) {

XmlTag[] componentsTags = rootTag.findSubTags("components");
XmlTag[] tags = rootTag.findSubTags(DEFINITION_GROUP_NAME.get(parentTagName));

for (XmlTag componentsTag : componentsTags) {
for (XmlTag componentTag : componentsTag.findSubTags("component")) {
String nameAttr = componentTag.getAttributeValue("name");
if (componentName.equals(nameAttr)) {
for (XmlTag tag : tags) {
for (XmlTag componentTag : tag.findSubTags(DEFINITION_TAG_NAME.get(parentTagName))) {
String nameAttr = componentTag.getAttributeValue(NAME_ATTRIBUTE);
if (tagName.equals(nameAttr)) {
return componentTag;
}
}
}
return null;
}

public static boolean isComponentsDeclaration(XmlAttributeValue valueElement) {
// answers the question :
// is the attribute value is inside one of the 2 tags that are used for declaration
// <components> <component name=""/> </components>
// <fields> <field name=""/> </fields>
public static boolean isTagDeclaration(XmlAttributeValue valueElement) {
XmlAttribute parentAttribute = (XmlAttribute) valueElement.getParent();
XmlTag xmlTag = parentAttribute.getParent();
XmlTag parentTag = xmlTag.getParentTag();
return parentTag != null && "components".equals(parentTag.getName());
if (parentTag == null) {
return false;
}

final String parentTagName = parentTag.getName();

return DEFINITION_GROUP_NAME.containsValue(parentTagName);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package ac.quant.quickfixspec.documentation


import ac.quant.quickfixspec.common.PsiUtils.findComponent
import ac.quant.quickfixspec.common.PsiUtils.findDefinition
import com.intellij.model.Pointer
import com.intellij.platform.backend.documentation.DocumentationResult
import com.intellij.platform.backend.documentation.DocumentationTarget
Expand All @@ -10,7 +10,8 @@ import com.intellij.psi.xml.XmlTag

@Suppress("UnstableApiUsage")
class QuickfixComponentDocumentationTarget(
private val componentName: String,
private val tagName: String,
private val parentTagName: String,
private val rootTag: XmlTag?
) : DocumentationTarget {

Expand All @@ -20,7 +21,7 @@ class QuickfixComponentDocumentationTarget(
}

override fun computePresentation(): TargetPresentation {
return TargetPresentation.builder(componentName).presentation()
return TargetPresentation.builder(tagName).presentation()
}

override fun computeDocumentationHint(): String {
Expand All @@ -29,21 +30,21 @@ class QuickfixComponentDocumentationTarget(
}

override fun computeDocumentation(): DocumentationResult {
val componentDetails = getComponentDetails(componentName)
val componentDetails = getTagDetails(tagName)
return DocumentationResult.documentation(componentDetails)
}

private fun getComponentDetails(componentName: String): String {
val component: XmlTag? = findComponent(rootTag, componentName)
component ?: return ""
return getDisplayText(component)
private fun getTagDetails(tagName: String): String {
val tag: XmlTag? = findDefinition(tagName, parentTagName, rootTag)
tag ?: return ""
return getDisplayText(tag)
}

private fun getDisplayText(component: XmlTag): String {
val text = component.children.joinToString("") { it.text }
private fun getDisplayText(tag: XmlTag): String {
val text = tag.children.joinToString("") { it.text }
val xmlEscapedText = xmlEscaped(text)
val indentationRemoved = indentationRemoved(xmlEscapedText)
val displayText = "<html><body><h1>${component.name}</h1><pre>$indentationRemoved</pre></body></html>"
val displayText = "<html><body><h1>${tag.name}</h1><pre>$indentationRemoved</pre></body></html>"
return displayText
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package ac.quant.quickfixspec.documentation

import ac.quant.quickfixspec.common.PsiUtils.NAME_ATTRIBUTE
import ac.quant.quickfixspec.common.PsiUtils.TAGS_WITH_DEFINITION
import ac.quant.quickfixspec.common.PsiUtils.DEFINITION_GROUP_NAME
import ac.quant.quickfixspec.common.PsiUtils.getRootTag
import com.intellij.platform.backend.documentation.DocumentationTarget
import com.intellij.platform.backend.documentation.DocumentationTargetProvider
Expand All @@ -22,24 +25,27 @@ class QuickfixComponentDocumentationTargetProvider : DocumentationTargetProvider
rootTag = getRootTag(attribute)
}

if ("name" != attribute.name) {
if (NAME_ATTRIBUTE != attribute.name) {
return emptyList()
}

val tag = attribute.parent as? XmlTag ?: return emptyList()

if ("component" != tag.name) {
if (tag.name !in TAGS_WITH_DEFINITION) {
return emptyList()
}

val tagParent = tag.parent as? XmlTag ?: return emptyList()

if ("components" == tagParent.name) {

// skip definition when tagParent.name is "components" or "fields"

if (tagParent.name in DEFINITION_GROUP_NAME.values) {
return emptyList()
}

val componentName = attribute.value ?: return emptyList()
return listOf(QuickfixComponentDocumentationTarget(componentName, rootTag))
val attrNameValue = attribute.value ?: return emptyList()
return listOf(QuickfixComponentDocumentationTarget(attrNameValue, tag.name, rootTag))

}

Expand Down

0 comments on commit f6f68be

Please sign in to comment.