work only with string literals
[fedora-idea.git] / plugins / java-i18n / src / com / intellij / codeInspection / i18n / folding / PropertyFoldingBuilder.java
bloba97e4b66c80e6347f281db5beac260bef57e1957
1 package com.intellij.codeInspection.i18n.folding;
3 import com.intellij.codeInsight.AnnotationUtil;
4 import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
5 import com.intellij.codeInspection.i18n.JavaI18nUtil;
6 import com.intellij.lang.ASTNode;
7 import com.intellij.lang.folding.FoldingBuilderEx;
8 import com.intellij.lang.folding.FoldingDescriptor;
9 import com.intellij.lang.properties.psi.Property;
10 import com.intellij.openapi.editor.Document;
11 import com.intellij.psi.*;
12 import com.intellij.psi.impl.ConstantExpressionEvaluator;
13 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
14 import org.jetbrains.annotations.NotNull;
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
21 /**
22 * @author Konstantin Bulenkov
24 public class PropertyFoldingBuilder extends FoldingBuilderEx {
26 @NotNull
27 public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement element, @NotNull Document document, boolean quick) {
28 if (!(element instanceof PsiJavaFile) || quick) {
29 return FoldingDescriptor.EMPTY;
31 final PsiJavaFile file = (PsiJavaFile) element;
32 final List<FoldingDescriptor> result = new ArrayList<FoldingDescriptor>();
34 file.accept(new JavaRecursiveElementWalkingVisitor() {
35 @Override
36 public void visitLiteralExpression(PsiLiteralExpression expression) {
37 if (isI18nProperty(expression)) {
38 final String msg = getI18nMessage(expression);
40 final PsiElement parent = expression.getParent();
41 if (!msg.equals(expression.getText()) &&
42 parent instanceof PsiExpressionList &&
43 ((PsiExpressionList)parent).getExpressions()[0] == expression) {
44 final PsiExpressionList expressions = (PsiExpressionList)parent;
45 final int count = JavaI18nUtil.getPropertyValueParamsMaxCount(expression);
46 final PsiExpression[] args = expressions.getExpressions();
47 if (args.length == 1 + count && parent.getParent() instanceof PsiMethodCallExpression) {
48 boolean ok = true;
49 for (int i = 1; i < count + 1; i++) {
50 Object value = ConstantExpressionEvaluator.computeConstantExpression(args[i], false);
51 if (value == null) {
52 if (!(args[i] instanceof PsiReferenceExpression)) {
53 ok = false;
54 break;
58 if (ok) {
59 result.add(new FoldingDescriptor(parent.getParent(), parent.getParent().getTextRange()));
60 return;
65 result.add(new FoldingDescriptor(expression, expression.getTextRange()));
68 });
70 return result.toArray(new FoldingDescriptor[result.size()]);
75 public String getPlaceholderText(@NotNull ASTNode node) {
76 final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(node);
77 if (element instanceof PsiLiteralExpression) {
78 return getI18nMessage((PsiLiteralExpression)element);
79 } else if (element instanceof PsiMethodCallExpression) {
80 return formatMethodCallExpression((PsiMethodCallExpression)element);
82 return element.getText();
85 private static String formatMethodCallExpression(PsiMethodCallExpression methodCallExpression) {
86 final PsiExpression[] args = methodCallExpression.getArgumentList().getExpressions();
87 if (args.length > 0
88 && args[0] instanceof PsiLiteralExpression
89 && isI18nProperty((PsiLiteralExpression)args[0])) {
90 final int count = JavaI18nUtil.getPropertyValueParamsMaxCount((PsiLiteralExpression)args[0]);
91 if (args.length == 1 + count) {
92 String text = getI18nMessage((PsiLiteralExpression)args[0]);
93 for (int i = 1; i < count + 1; i++) {
94 Object value = ConstantExpressionEvaluator.computeConstantExpression(args[i], false);
95 if (value == null) {
96 if (args[i] instanceof PsiReferenceExpression) {
97 value = "{" + args[i].getText() + "}";
99 else {
100 text = null;
101 break;
104 text = text.replace("{" + (i - 1) + "}", value.toString());
106 if (text != null) {
107 if (!text.equals(methodCallExpression.getText())) {
108 text = text.replace("''", "'");
110 return text;
115 return methodCallExpression.getText();
118 private static String getI18nMessage(PsiLiteralExpression literal) {
119 if (isI18nProperty(literal)) {
120 final PsiReference[] references = literal.getReferences();
121 for (PsiReference reference : references) {
122 final PsiElement element = reference.resolve();
123 if (element instanceof Property) {
124 return "\"" + ((Property)element).getValue() + "\"";
128 return literal.getText();
131 public boolean isCollapsedByDefault(@NotNull ASTNode node) {
132 return JavaCodeFoldingSettings.getInstance().isCollapseI18nMessages();
136 public static boolean isI18nProperty(PsiLiteralExpression expr) {
137 if (! isStringLiteral(expr)) return false;
139 final Map<String, Object> annotationParams = new HashMap<String, Object>();
140 annotationParams.put(AnnotationUtil.PROPERTY_KEY_RESOURCE_BUNDLE_PARAMETER, null);
141 return JavaI18nUtil.mustBePropertyKey(expr, annotationParams);
144 private static boolean isStringLiteral(PsiLiteralExpression expr) {
145 final String text;
146 if (expr == null || (text = expr.getText()) == null) return false;
147 return text.startsWith("\"") && text.endsWith("\"") && text.length() > 2;