/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntention.java
https://bitbucket.org/nbargnesi/idea · Java · 272 lines · 244 code · 10 blank · 18 comment · 51 complexity · 8a701b491fbe4e6a41326587318fa59f MD5 · raw file
- /*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.siyeh.ipp.forloop;
- import com.intellij.openapi.project.Project;
- import com.intellij.openapi.util.text.StringUtil;
- import com.intellij.psi.*;
- import com.intellij.psi.codeStyle.*;
- import com.intellij.util.IncorrectOperationException;
- import com.siyeh.ipp.base.Intention;
- import com.siyeh.ipp.base.PsiElementPredicate;
- import org.jetbrains.annotations.NonNls;
- import org.jetbrains.annotations.NotNull;
- import org.jetbrains.annotations.Nullable;
- public class ReplaceForEachLoopWithIndexedForLoopIntention extends Intention {
- @Override
- @NotNull
- public PsiElementPredicate getElementPredicate() {
- return new IndexedForEachLoopPredicate();
- }
- @Override
- public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
- final PsiForeachStatement statement = (PsiForeachStatement)element.getParent();
- if (statement == null) {
- return;
- }
- final PsiExpression iteratedValue = statement.getIteratedValue();
- if (iteratedValue == null) {
- return;
- }
- final PsiParameter iterationParameter =
- statement.getIterationParameter();
- final PsiType type = iterationParameter.getType();
- final PsiType iteratedValueType = iteratedValue.getType();
- if (iteratedValueType == null) {
- return;
- }
- final boolean isArray = iteratedValueType instanceof PsiArrayType;
- final PsiElement grandParent = statement.getParent();
- final PsiStatement context;
- if (grandParent instanceof PsiLabeledStatement) {
- context = (PsiStatement)grandParent;
- } else {
- context = statement;
- }
- final String iteratedValueText = getReferenceToIterate(iteratedValue, context);
- @NonNls final StringBuilder newStatement = new StringBuilder();
- final String indexText = createVariableName("i", PsiType.INT, statement);
- createForLoopDeclaration(statement, iteratedValue, isArray, iteratedValueText, newStatement, indexText);
- final Project project = statement.getProject();
- final CodeStyleSettings codeStyleSettings =
- CodeStyleSettingsManager.getSettings(project);
- if (codeStyleSettings.GENERATE_FINAL_LOCALS) {
- newStatement.append("final ");
- }
- newStatement.append(type.getCanonicalText());
- newStatement.append(' ');
- newStatement.append(iterationParameter.getName());
- newStatement.append(" = ");
- newStatement.append(iteratedValueText);
- if (isArray) {
- newStatement.append('[');
- newStatement.append(indexText);
- newStatement.append("];");
- }
- else {
- newStatement.append(".get(");
- newStatement.append(indexText);
- newStatement.append(");");
- }
- final PsiStatement body = statement.getBody();
- if (body == null) {
- return;
- }
- if (body instanceof PsiBlockStatement) {
- final PsiCodeBlock block = ((PsiBlockStatement)body).getCodeBlock();
- final PsiElement[] children = block.getChildren();
- for (int i = 1; i < children.length - 1; i++) {
- //skip the braces
- newStatement.append(children[i].getText());
- }
- }
- else {
- newStatement.append(body.getText());
- }
- newStatement.append('}');
- replaceStatementAndShorten(newStatement.toString(), statement);
- }
- protected void createForLoopDeclaration(PsiForeachStatement statement,
- PsiExpression iteratedValue,
- boolean array,
- String iteratedValueText, StringBuilder newStatement,
- final String indexText) {
- newStatement.append("for(int ");
- newStatement.append(indexText);
- newStatement.append(" = 0; ");
- newStatement.append(indexText);
- newStatement.append('<');
- if (iteratedValue instanceof PsiTypeCastExpression) {
- newStatement.append('(');
- newStatement.append(iteratedValueText);
- newStatement.append(')');
- }
- else {
- newStatement.append(iteratedValueText);
- }
- if (array) {
- newStatement.append(".length");
- }
- else {
- newStatement.append(".size()");
- }
- newStatement.append(';');
- newStatement.append(indexText);
- newStatement.append("++)");
- newStatement.append("{ ");
- }
- private static String getVariableName(PsiExpression expression) {
- if (expression instanceof PsiMethodCallExpression) {
- final PsiMethodCallExpression methodCallExpression =
- (PsiMethodCallExpression)expression;
- final PsiReferenceExpression methodExpression =
- methodCallExpression.getMethodExpression();
- final String name = methodExpression.getReferenceName();
- if (name == null) {
- return null;
- }
- if (name.startsWith("to") && name.length() > 2) {
- return StringUtil.decapitalize(name.substring(2));
- }
- else if (name.startsWith("get") && name.length() > 3) {
- return StringUtil.decapitalize(name.substring(3));
- }
- else {
- return name;
- }
- }
- else if (expression instanceof PsiTypeCastExpression) {
- final PsiTypeCastExpression castExpression =
- (PsiTypeCastExpression)expression;
- final PsiExpression operand = castExpression.getOperand();
- return getVariableName(operand);
- }
- else if (expression instanceof PsiArrayAccessExpression) {
- final PsiArrayAccessExpression arrayAccessExpression =
- (PsiArrayAccessExpression)expression;
- final PsiExpression arrayExpression =
- arrayAccessExpression.getArrayExpression();
- return StringUtil.unpluralize(getVariableName(arrayExpression));
- }
- else if (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- final PsiExpression innerExpression =
- parenthesizedExpression.getExpression();
- return getVariableName(innerExpression);
- }
- else if (expression instanceof PsiJavaCodeReferenceElement) {
- final PsiJavaCodeReferenceElement referenceElement =
- (PsiJavaCodeReferenceElement)expression;
- final String referenceName = referenceElement.getReferenceName();
- if (referenceName == null) {
- return expression.getText();
- }
- return referenceName;
- }
- return null;
- }
- private static String getReferenceToIterate(
- PsiExpression expression, PsiElement context) {
- if (expression instanceof PsiMethodCallExpression ||
- expression instanceof PsiTypeCastExpression ||
- expression instanceof PsiArrayAccessExpression ||
- expression instanceof PsiNewExpression) {
- final String variableName = getVariableName(expression);
- return createVariable(variableName, expression, context);
- }
- else if (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- final PsiExpression innerExpression =
- parenthesizedExpression.getExpression();
- return getReferenceToIterate(innerExpression, context);
- }
- else if (expression instanceof PsiJavaCodeReferenceElement) {
- final PsiJavaCodeReferenceElement referenceElement =
- (PsiJavaCodeReferenceElement)expression;
- final String variableName = getVariableName(expression);
- if (referenceElement.isQualified()) {
- return createVariable(variableName, expression, context);
- }
- final PsiElement target = referenceElement.resolve();
- if (target instanceof PsiVariable) {
- // maybe should not do this for local variables outside of
- // anonymous classes
- return variableName;
- }
- return createVariable(variableName, expression, context);
- }
- return null;
- }
- private static String createVariable(String variableNameRoot,
- PsiExpression iteratedValue,
- PsiElement context) {
- final String variableName =
- createVariableName(variableNameRoot, iteratedValue);
- final Project project = context.getProject();
- final PsiType iteratedValueType = iteratedValue.getType();
- assert iteratedValueType != null;
- final PsiElementFactory elementFactory =
- JavaPsiFacade.getElementFactory(project);
- final PsiDeclarationStatement declarationStatement =
- elementFactory.createVariableDeclarationStatement(variableName,
- iteratedValueType, iteratedValue);
- context.getParent().addBefore(declarationStatement, context);
- return variableName;
- }
- public static String createVariableName(
- @Nullable String baseName,
- @NotNull PsiExpression assignedExpression) {
- final Project project = assignedExpression.getProject();
- final JavaCodeStyleManager codeStyleManager =
- JavaCodeStyleManager.getInstance(project);
- final SuggestedNameInfo names =
- codeStyleManager.suggestVariableName(VariableKind.LOCAL_VARIABLE,
- baseName, assignedExpression, null);
- if (names.names.length == 0) {
- return codeStyleManager.suggestUniqueVariableName(baseName,
- assignedExpression, true);
- }
- return codeStyleManager.suggestUniqueVariableName(names.names[0],
- assignedExpression, true);
- }
- public static String createVariableName(@Nullable String baseName,
- @NotNull PsiType type,
- @NotNull PsiElement context) {
- final Project project = context.getProject();
- final JavaCodeStyleManager codeStyleManager =
- JavaCodeStyleManager.getInstance(project);
- final SuggestedNameInfo names =
- codeStyleManager.suggestVariableName(
- VariableKind.LOCAL_VARIABLE, baseName, null, type);
- if (names.names.length == 0) {
- return codeStyleManager.suggestUniqueVariableName(baseName,
- context, true);
- }
- return codeStyleManager.suggestUniqueVariableName(names.names[0],
- context, true);
- }
- }