2 * Copyright 2006 Sascha Weinreuter
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.intellij
.plugins
.intelliLang
.util
;
18 import com
.intellij
.openapi
.project
.Project
;
19 import com
.intellij
.openapi
.util
.Ref
;
20 import com
.intellij
.openapi
.util
.text
.StringUtil
;
21 import com
.intellij
.psi
.*;
22 import com
.intellij
.util
.SmartList
;
23 import org
.jetbrains
.annotations
.NotNull
;
25 import java
.util
.ArrayList
;
26 import java
.util
.List
;
29 * Helper class that can compute the prefix and suffix of an expression inside a binary (usually additive) expression
30 * that computes the values not only for compile-time constants, but also for elements annotated with a substitution
33 * @see org.intellij.plugins.intelliLang.util.SubstitutedExpressionEvaluationHelper
35 public class ContextComputationProcessor
{
37 private final SubstitutedExpressionEvaluationHelper myEvaluationHelper
;
39 private ContextComputationProcessor(final Project project
) {
40 myEvaluationHelper
= new SubstitutedExpressionEvaluationHelper(project
);
44 public static List
<Object
> collectOperands(@NotNull final String prefix
, final String suffix
, final Ref
<Boolean
> unparsable
, final PsiElement
[] operands
) {
45 final ArrayList
<Object
> result
= new ArrayList
<Object
>();
46 final ContextComputationProcessor processor
= new ContextComputationProcessor(operands
[0].getProject());
47 addStringFragment(prefix
, result
);
48 for (PsiElement operand
: operands
) {
49 processor
.collectOperands(operand
, result
, unparsable
);
51 addStringFragment(suffix
, result
);
55 private static void addStringFragment(final String string
, final List
<Object
> result
) {
56 if (StringUtil
.isEmpty(string
)) return;
57 final int size
= result
.size();
58 final Object last
= size
> 0? result
.get(size
-1) : null;
59 if (last
instanceof String
) {
60 result
.set(size
- 1, last
+ string
);
67 public void collectOperands(final PsiElement expression
, final List
<Object
> result
, final Ref
<Boolean
> unparsable
) {
68 final PsiElement firstChild
;
69 if (expression
instanceof PsiParenthesizedExpression
) {
70 collectOperands(((PsiParenthesizedExpression
)expression
).getExpression(), result
, unparsable
);
72 else if (expression
instanceof PsiTypeCastExpression
) {
73 collectOperands(((PsiTypeCastExpression
)expression
).getOperand(), result
, unparsable
);
75 else if (expression
instanceof PsiConditionalExpression
) {
76 unparsable
.set(Boolean
.TRUE
);
77 collectOperands(((PsiConditionalExpression
)expression
).getThenExpression(), result
, unparsable
);
78 collectOperands(((PsiConditionalExpression
)expression
).getElseExpression(), result
, unparsable
);
80 else if (expression
instanceof PsiBinaryExpression
&&
81 ((PsiBinaryExpression
)expression
).getOperationSign().getTokenType() == JavaTokenType
.PLUS
) {
82 final PsiBinaryExpression binaryExpression
= (PsiBinaryExpression
)expression
;
83 collectOperands(binaryExpression
.getLOperand(), result
, unparsable
);
84 collectOperands(binaryExpression
.getROperand(), result
, unparsable
);
86 else if (expression
instanceof PsiAssignmentExpression
&&
87 ((PsiAssignmentExpression
)expression
).getOperationSign().getTokenType() == JavaTokenType
.PLUSEQ
) {
88 unparsable
.set(Boolean
.TRUE
);
89 final PsiAssignmentExpression assignmentExpression
= (PsiAssignmentExpression
)expression
;
90 collectOperands(assignmentExpression
.getLExpression(), result
, unparsable
);
91 collectOperands(assignmentExpression
.getRExpression(), result
, unparsable
);
93 else if (PsiUtilEx
.isStringOrCharacterLiteral(expression
)) {
94 result
.add(expression
);
97 final SmartList
<PsiExpression
> uncomputables
= new SmartList
<PsiExpression
>();
98 final Object o
= expression
instanceof PsiExpression? myEvaluationHelper
.computeExpression((PsiExpression
)expression
, true, uncomputables
) : null;
99 if (uncomputables
.size() > 0) {
100 unparsable
.set(Boolean
.TRUE
);
103 result
.add(expression
);
105 addStringFragment(String
.valueOf(o
), result
);
111 public static PsiElement
getTopLevelInjectionTarget(@NotNull final PsiElement host
) {
112 PsiElement target
= host
;
113 PsiElement parent
= target
.getParent();
114 for (; parent
!= null; target
= parent
, parent
= target
.getParent()) {
115 if (parent
instanceof PsiBinaryExpression
) continue;
116 if (parent
instanceof PsiParenthesizedExpression
) continue;
117 if (parent
instanceof PsiConditionalExpression
&& ((PsiConditionalExpression
)parent
).getCondition() != target
) continue;
118 if (parent
instanceof PsiArrayInitializerMemberValue
) continue;
119 if (parent
instanceof PsiArrayInitializerExpression
) {
120 parent
= parent
.getParent(); continue;