Resolving Properties

Hi,

In XML files, especially in spring configurations, when we add the .properties file path to the .xml file, IDEA is able to resolve ${} property placeholder values and display the value instead of placeholder in the .xml file view.

Is there a way to programatically add a .properties file so that IDEA would resolve properties from that file as well? Is there an API for that?

An example would be as below

0
6 comments
Official comment

You may only iterate over all unresolved properties and then create its using com.intellij.lang.properties.psi.PropertiesFile#addProperty(java.lang.String, java.lang.String) or similar method from PropertiesFile class

Avatar
Permanently deleted user

This would add a property value to the XML file right? What want is that the property to be shown resolved in the UI, but when you hover over the resolved property, the actual placeholder is shown as seen in above screenshot.

0
Avatar
Permanently deleted user

After digging a little bit further into IC code, I have found out that this feature is given by code folding. Hence, I've implemented a custom CodeFoldingBuilder extending FoldingBuilderEx and registered is as below

<lang.foldingBuilder language="XML" implementationClass="org.test.core.file.XmlPropertyFoldingBuilder"/>

Still, the property placeholders are not folded as shown in below screenshot. Below is the code of my codef olding builder

 



package org.test.core.file;

import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.FoldingBuilderEx;
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @author Sajith Dilshan
*/
public class XmlPropertyFoldingBuilder extends FoldingBuilderEx {
private static final Pattern PATTERN = Pattern.compile("\\$\\{(.*)\\}");


@NotNull
@Override
public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement psiElement, @NotNull Document document, boolean quick) {

Project project = psiElement.getProject();

PsiFile containingFile = psiElement.getContainingFile();
if (containingFile == null) {
return FoldingDescriptor.EMPTY;
}

String extension = containingFile.getVirtualFile().getExtension();
if (extension == null) {
return FoldingDescriptor.EMPTY;

}

PsiFile[] propFiles = FilenameIndex.getFilesByName(project, "default.properties", ProjectScope.getProjectScope(project));

if (propFiles.length < 1) {
return FoldingDescriptor.EMPTY;
}

if (extension.equals("xcml") || extension.equals("xpml")) {

PropertiesFile defaultPropFile = PropertiesFile.class.cast(propFiles[0]);

if (psiElement instanceof XmlFile) {


List<FoldingDescriptor> descriptors = new LinkedList<>();

XmlFile xmlFile = XmlFile.class.cast(psiElement);
Collection<XmlAttributeValue> xmlAttributeValues = PsiTreeUtil.findChildrenOfAnyType(xmlFile.getRootTag(), XmlAttributeValue.class);

for (XmlAttributeValue attributeValue : xmlAttributeValues) {
Matcher matcher = PATTERN.matcher(attributeValue.getValue());

if (matcher.matches()) {
IProperty propVal = defaultPropFile.findPropertyByKey(matcher.group(1));
if (propVal != null) {
descriptors.add(new FoldingDescriptor(attributeValue, attributeValue.getTextRange()));
}
}
}
return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
}
}

return FoldingDescriptor.EMPTY;
}


@Nullable
@Override
public String getPlaceholderText(@NotNull ASTNode node) {
return "testString";
}

@Override
public boolean isCollapsedByDefault(@NotNull ASTNode node) {
return false;
}
}
0

Are you expect to see foldings inside a popup in screenshot? Or you mean that your code doesn't work at all?

0
Avatar
Permanently deleted user

I'm expecting to see the folding in a pop-up. But so far, my code doesn't work at all. I've debugged the code as well. It correctly resolve the descriptors as well. But no pop-ups. Am I giving a wrong text range?

0
Avatar
Permanently deleted user

Finally got it to work. I had to always return true for isCollapsedByDefault method. Is there a way to make it permanently folded?

0

Please sign in to leave a comment.