2 * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
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 com
.siyeh
.ipp
.forloop
;
18 import com
.intellij
.openapi
.project
.Project
;
19 import com
.intellij
.openapi
.util
.text
.StringUtil
;
20 import com
.intellij
.psi
.*;
21 import com
.intellij
.psi
.codeStyle
.CodeStyleSettings
;
22 import com
.intellij
.psi
.codeStyle
.CodeStyleSettingsManager
;
23 import com
.intellij
.psi
.codeStyle
.JavaCodeStyleManager
;
24 import com
.intellij
.util
.IncorrectOperationException
;
25 import com
.siyeh
.ipp
.base
.Intention
;
26 import com
.siyeh
.ipp
.base
.PsiElementPredicate
;
27 import org
.jetbrains
.annotations
.NonNls
;
28 import org
.jetbrains
.annotations
.NotNull
;
30 public class ReplaceForEachLoopWithIndexedForLoopIntention
extends Intention
{
34 public PsiElementPredicate
getElementPredicate() {
35 return new IndexedForEachLoopPredicate();
39 public void processIntention(@NotNull PsiElement element
)
40 throws IncorrectOperationException
{
41 final PsiForeachStatement statement
=
42 (PsiForeachStatement
)element
.getParent();
43 if (statement
== null) {
46 final PsiExpression iteratedValue
= statement
.getIteratedValue();
47 if (iteratedValue
== null) {
50 final PsiParameter iterationParameter
=
51 statement
.getIterationParameter();
52 final PsiType type
= iterationParameter
.getType();
53 final PsiType iteratedValueType
= iteratedValue
.getType();
54 if (iteratedValueType
== null) {
57 final boolean isArray
= iteratedValueType
instanceof PsiArrayType
;
58 final Project project
= statement
.getProject();
59 final JavaCodeStyleManager codeStyleManager
=
60 JavaCodeStyleManager
.getInstance(project
);
61 final String indexText
=
62 codeStyleManager
.suggestUniqueVariableName("i", statement
, true);
63 final String variableNameRoot
;
64 if (iteratedValue
instanceof PsiMethodCallExpression
) {
65 final PsiMethodCallExpression methodCallExpression
=
66 (PsiMethodCallExpression
)iteratedValue
;
67 final PsiReferenceExpression methodExpression
=
68 methodCallExpression
.getMethodExpression();
69 final String name
= methodExpression
.getReferenceName();
73 if (name
.startsWith("to") && name
.length() > 2) {
74 variableNameRoot
= StringUtil
.decapitalize(name
.substring(2));
75 } else if (name
.startsWith("get") && name
.length() > 3) {
76 variableNameRoot
= StringUtil
.decapitalize(name
.substring(3));
78 variableNameRoot
= name
;
80 } else if (iteratedValue
instanceof PsiTypeCastExpression
) {
81 final PsiTypeCastExpression castExpression
=
82 (PsiTypeCastExpression
) iteratedValue
;
83 final PsiExpression operand
= castExpression
.getOperand();
84 if (operand
== null) {
85 variableNameRoot
= "";
87 variableNameRoot
= operand
.getText();
90 variableNameRoot
= iteratedValue
.getText();
92 final String lengthText
;
94 lengthText
= codeStyleManager
.suggestUniqueVariableName(
95 variableNameRoot
+ "Length", statement
, true);
97 lengthText
= codeStyleManager
.suggestUniqueVariableName(
98 variableNameRoot
+ "Size", statement
, true);
100 final CodeStyleSettings codeStyleSettings
=
101 CodeStyleSettingsManager
.getSettings(project
);
102 if (iteratedValue
instanceof PsiMethodCallExpression
) {
103 final String variableName
=
104 codeStyleManager
.suggestUniqueVariableName(
105 variableNameRoot
, statement
, true);
106 final StringBuilder declaration
= new StringBuilder();
107 if (codeStyleSettings
.GENERATE_FINAL_LOCALS
) {
108 declaration
.append("final ");
110 declaration
.append(iteratedValueType
.getCanonicalText());
111 declaration
.append(' ');
112 declaration
.append(variableName
);
113 declaration
.append('=');
114 declaration
.append(iteratedValue
.getText());
115 declaration
.append(';');
116 final PsiElementFactory elementFactory
=
117 JavaPsiFacade
.getElementFactory(project
);
118 final PsiStatement declarationStatement
=
119 elementFactory
.createStatementFromText(
120 declaration
.toString(), statement
);
121 statement
.getParent().addBefore(declarationStatement
, statement
);
123 @NonNls final StringBuilder newStatement
= new StringBuilder();
124 newStatement
.append("for(int ");
125 newStatement
.append(indexText
);
126 newStatement
.append(" = 0, ");
128 newStatement
.append(lengthText
);
129 newStatement
.append(" = ");
130 if (iteratedValue
instanceof PsiTypeCastExpression
) {
131 newStatement
.append('(');
132 newStatement
.append(iteratedValue
.getText());
133 newStatement
.append(')');
135 newStatement
.append(variableNameRoot
);
138 newStatement
.append(".length;");
140 newStatement
.append(".size();");
142 newStatement
.append(indexText
);
143 newStatement
.append('<');
144 newStatement
.append(lengthText
);
145 newStatement
.append(';');
146 newStatement
.append(indexText
);
147 newStatement
.append("++)");
148 newStatement
.append("{ ");
149 if (codeStyleSettings
.GENERATE_FINAL_LOCALS
) {
150 newStatement
.append("final ");
152 newStatement
.append(type
.getCanonicalText());
153 newStatement
.append(' ');
154 newStatement
.append(iterationParameter
.getName());
155 newStatement
.append(" = ");
156 if (iteratedValue
instanceof PsiTypeCastExpression
) {
157 newStatement
.append('(');
158 newStatement
.append(iteratedValue
.getText());
159 newStatement
.append(')');
161 newStatement
.append(variableNameRoot
);
164 newStatement
.append('[');
165 newStatement
.append(indexText
);
166 newStatement
.append("];");
168 newStatement
.append(".get(");
169 newStatement
.append(indexText
);
170 newStatement
.append(");");
172 final PsiStatement body
= statement
.getBody();
176 if (body
instanceof PsiBlockStatement
) {
177 final PsiCodeBlock block
= ((PsiBlockStatement
)body
).getCodeBlock();
178 final PsiElement
[] children
= block
.getChildren();
179 for (int i
= 1; i
< children
.length
- 1; i
++) {
181 newStatement
.append(children
[i
].getText());
184 newStatement
.append(body
.getText());
186 newStatement
.append('}');
187 replaceStatementAndShorten(newStatement
.toString(), statement
);