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
;
22 * @author Konstantin Bulenkov
24 public class PropertyFoldingBuilder
extends FoldingBuilderEx
{
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() {
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
) {
49 for (int i
= 1; i
< count
+ 1; i
++) {
50 Object value
= ConstantExpressionEvaluator
.computeConstantExpression(args
[i
], false);
52 if (!(args
[i
] instanceof PsiReferenceExpression
)) {
59 result
.add(new FoldingDescriptor(parent
.getParent(), parent
.getParent().getTextRange()));
65 result
.add(new FoldingDescriptor(expression
, expression
.getTextRange()));
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();
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);
96 if (args
[i
] instanceof PsiReferenceExpression
) {
97 value
= "{" + args
[i
].getText() + "}";
104 text
= text
.replace("{" + (i
- 1) + "}", value
.toString());
107 if (!text
.equals(methodCallExpression
.getText())) {
108 text
= text
.replace("''", "'");
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
) {
146 if (expr
== null || (text
= expr
.getText()) == null) return false;
147 return text
.startsWith("\"") && text
.endsWith("\"") && text
.length() > 2;