blob: 9bc47e30f1fad2cc63432fdd88386f2d08e40161 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiConcatenationUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author ven
*/
public class ConcatenationToMessageFormatAction implements IntentionAction {
@Override
@NotNull
public String getFamilyName() {
return CodeInsightBundle.message("intention.replace.concatenation.with.formatted.output.family");
}
@Override
@NotNull
public String getText() {
return CodeInsightBundle.message("intention.replace.concatenation.with.formatted.output.text");
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
final PsiElement element = findElementAtCaret(editor, file);
PsiPolyadicExpression concatenation = getEnclosingLiteralConcatenation(element);
if (concatenation == null) return;
StringBuilder formatString = new StringBuilder();
List<PsiExpression> args = new ArrayList<PsiExpression>();
PsiConcatenationUtil.buildFormatString(concatenation, formatString, args, false);
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
PsiMethodCallExpression call = (PsiMethodCallExpression)
factory.createExpressionFromText("java.text.MessageFormat.format()", concatenation);
PsiExpressionList argumentList = call.getArgumentList();
PsiExpression formatArgument = factory.createExpressionFromText("\"" + formatString.toString() + "\"", null);
argumentList.add(formatArgument);
if (PsiUtil.isLanguageLevel5OrHigher(file)) {
for (PsiExpression arg : args) {
argumentList.add(arg);
}
}
else {
final PsiNewExpression arrayArg = (PsiNewExpression)factory.createExpressionFromText("new java.lang.Object[]{}", null);
final PsiArrayInitializerExpression arrayInitializer = arrayArg.getArrayInitializer();
assert arrayInitializer != null;
for (PsiExpression arg : args) {
arrayInitializer.add(arg);
}
argumentList.add(arrayArg);
}
call = (PsiMethodCallExpression) JavaCodeStyleManager.getInstance(project).shortenClassReferences(call);
call = (PsiMethodCallExpression) CodeStyleManager.getInstance(element.getManager().getProject()).reformat(call);
concatenation.replace(call);
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (PsiUtil.getLanguageLevel(file).compareTo(LanguageLevel.JDK_1_4) < 0) return false;
final PsiElement element = findElementAtCaret(editor, file);
PsiPolyadicExpression binaryExpression = getEnclosingLiteralConcatenation(element);
return binaryExpression != null && !AnnotationUtil.isInsideAnnotation(binaryExpression);
}
@Nullable
private static PsiElement findElementAtCaret(Editor editor, PsiFile file) {
return file.findElementAt(editor.getCaretModel().getOffset());
}
@Nullable
private static PsiPolyadicExpression getEnclosingLiteralConcatenation(final PsiElement element) {
PsiPolyadicExpression binaryExpression = PsiTreeUtil.getParentOfType(element, PsiPolyadicExpression.class, false, PsiMember.class);
if (binaryExpression == null) return null;
final PsiClassType stringType = PsiType.getJavaLangString(element.getManager(), element.getResolveScope());
if (!stringType.equals(binaryExpression.getType())) return null;
while (true) {
final PsiElement parent = binaryExpression.getParent();
if (!(parent instanceof PsiPolyadicExpression)) return binaryExpression;
PsiPolyadicExpression parentBinaryExpression = (PsiPolyadicExpression)parent;
if (!stringType.equals(parentBinaryExpression.getType())) return binaryExpression;
binaryExpression = parentBinaryExpression;
}
}
@Override
public boolean startInWriteAction() {
return true;
}
}