diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index dfde88a10827..4062a9ad0c09 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -378,14 +378,18 @@ public class HighlightUtil { if (opSign == null) return null; HighlightInfo errorResult = null; final PsiType lType = assignment.getLExpression().getType(); - if (!TypeConversionUtil.isBinaryOperatorApplicable(opSign, assignment.getLExpression(), assignment.getRExpression(), true) || + final PsiExpression rExpression = assignment.getRExpression(); + if (rExpression == null) return null; + final PsiType rType = rExpression.getType(); + if (!TypeConversionUtil.isBinaryOperatorApplicable(opSign, lType, rType, true) || PsiType.getJavaLangObject(assignment.getManager(), assignment.getResolveScope()).equals(lType)) { String operatorText = operationSign.getText().substring(0, operationSign.getText().length() - 1); String message = JavaErrorMessages.message("binary.operator.not.applicable", operatorText, formatType(lType), - formatType(assignment.getRExpression().getType())); + formatType(rType)); errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, assignment, message); + QuickFixAction.registerQuickFixAction(errorResult, new ChangeToAppendFix(eqOpSign, lType, rType, assignment)); } return errorResult; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeToAppendFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeToAppendFix.java new file mode 100644 index 000000000000..180af116ff2c --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeToAppendFix.java @@ -0,0 +1,87 @@ +/* + * Copyright 2000-2011 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.daemon.impl.quickfix; + +import com.intellij.codeInsight.CodeInsightUtilBase; +import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; + +/** + * @author Bas Leijdekkers + */ +public class ChangeToAppendFix implements IntentionAction { + + private final IElementType myTokenType; + private final PsiType myLhsType; + private final PsiType myRhsType; + private final PsiAssignmentExpression myAssignmentExpression; + + public ChangeToAppendFix(IElementType eqOpSign, PsiType lType, PsiType rType, PsiAssignmentExpression assignmentExpression) { + myTokenType = eqOpSign; + myLhsType = lType; + myRhsType = rType; + myAssignmentExpression = assignmentExpression; + } + + @NotNull + @Override + public String getText() { + return QuickFixBundle.message("change.to.append.text", + myAssignmentExpression.getLExpression().getText(), + myAssignmentExpression.getRExpression().getText()); + } + + @NotNull + @Override + public String getFamilyName() { + return QuickFixBundle.message("change.to.append.family"); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return JavaTokenType.PLUSEQ == myTokenType && + myAssignmentExpression.isValid() && + myAssignmentExpression.getManager().isInProject(myAssignmentExpression) && + myRhsType.equalsToText("java.lang.String") && + (myLhsType.equalsToText("java.lang.StringBuilder") || myLhsType.equalsToText("java.lang.StringBuffer")); + } + + @Override + public boolean startInWriteAction() { + return true; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; + final PsiExpression rExpression = myAssignmentExpression.getRExpression(); + if (rExpression == null) { + return; + } + final String appendCallText = + myAssignmentExpression.getLExpression().getText() + ".append(" + rExpression.getText() + ')'; + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(myAssignmentExpression.getProject()); + final PsiExpression appendCall = factory.createExpressionFromText(appendCallText, myAssignmentExpression); + myAssignmentExpression.replace(appendCall); + } +} diff --git a/resources-en/src/messages/QuickFixBundle.properties b/resources-en/src/messages/QuickFixBundle.properties index 75e5249bc6a7..a0fc1f94fd83 100644 --- a/resources-en/src/messages/QuickFixBundle.properties +++ b/resources-en/src/messages/QuickFixBundle.properties @@ -251,4 +251,7 @@ create.readable.writable.property.with.field=Create getter, setter and field for create.readable.property=Create getter for ''{0}'' create.writable.property=Create setter for ''{0}'' create.readable.property.with.field=Create getter and field for ''{0}'' -create.writable.property.with.field=Create setter and field for ''{0}'' +create.writable.property.with.field=Create setter and field for ''{0}'' + +change.to.append.family=Fix StringBuilder append +change.to.append.text=Change to ''{0}.append({1})''