update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / daemon / impl / quickfix / ChangeStringLiteralToCharInMethodCallFix.java
blob7e08e4c91af2bcfe91c006006ba4c03b5215c1fc
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
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.intellij.codeInsight.daemon.impl.quickfix;
18 import com.intellij.codeInsight.CodeInsightUtilBase;
19 import com.intellij.codeInsight.daemon.QuickFixBundle;
20 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
21 import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
22 import com.intellij.codeInsight.intention.IntentionAction;
23 import com.intellij.openapi.editor.Editor;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.util.Comparing;
26 import com.intellij.psi.*;
27 import com.intellij.psi.infos.CandidateInfo;
28 import com.intellij.psi.infos.MethodCandidateInfo;
29 import com.intellij.util.IncorrectOperationException;
30 import org.jetbrains.annotations.NotNull;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Set;
36 public class ChangeStringLiteralToCharInMethodCallFix implements IntentionAction {
37 private final PsiLiteralExpression myLiteral;
38 private final PsiCall myCall;
40 public ChangeStringLiteralToCharInMethodCallFix(final PsiLiteralExpression literal, final PsiCall methodCall) {
41 myLiteral = literal;
42 myCall = methodCall;
45 @NotNull
46 public String getText() {
47 final String convertedValue = convertedValue();
48 final boolean isString = isString(myLiteral.getType());
49 return QuickFixBundle.message("fix.single.character.string.to.char.literal.text", myLiteral.getText(),
50 quote(convertedValue, ! isString), isString ? PsiType.CHAR.getCanonicalText() : "String");
53 @NotNull
54 public String getFamilyName() {
55 return QuickFixBundle.message("fix.single.character.string.to.char.literal.family");
58 public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
59 return myCall.isValid() && myLiteral.isValid() && myCall.getManager().isInProject(myCall);
62 public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
63 if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
65 final Object value = myLiteral.getValue();
66 if ((value != null) && (value.toString().length() == 1)) {
67 final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
69 final PsiExpression newExpression = factory.createExpressionFromText(quote(convertedValue(), ! isString(myLiteral.getType())),
70 myLiteral.getParent());
71 myLiteral.replace(newExpression);
75 public boolean startInWriteAction() {
76 return true;
79 private String quote(final String value, final boolean doubleQuotes) {
80 final char quote = doubleQuotes ? '"' : '\'';
81 return quote + value + quote;
84 private String convertedValue() {
85 String value = String.valueOf(myLiteral.getValue());
86 return ("\"".equals(value) || "'".equals(value)) ? "\\" + value : value;
89 public static void createHighLighting(@NotNull final PsiMethod[] candidates, @NotNull final PsiConstructorCall call,
90 @NotNull final List<HighlightInfo> out) {
91 final Set<PsiLiteralExpression> literals = new HashSet<PsiLiteralExpression>();
92 if (call.getArgumentList() == null) {
93 return;
95 boolean exactMatch = false;
96 for (PsiMethod method : candidates) {
97 exactMatch |= findMatchingExpressions(call.getArgumentList().getExpressions(), method, literals);
99 if (! exactMatch) {
100 processLiterals(literals, call, out);
104 public static void createHighLighting(@NotNull final CandidateInfo[] candidates, @NotNull final PsiMethodCallExpression methodCall,
105 @NotNull final List<HighlightInfo> out) {
106 final Set<PsiLiteralExpression> literals = new HashSet<PsiLiteralExpression>();
107 boolean exactMatch = false;
108 for (CandidateInfo candidate : candidates) {
109 if (candidate instanceof MethodCandidateInfo) {
110 final PsiMethod method = ((MethodCandidateInfo) candidate).getElement();
111 exactMatch |= findMatchingExpressions(methodCall.getArgumentList().getExpressions(), method, literals);
114 if (! exactMatch) {
115 processLiterals(literals, methodCall, out);
119 private static void processLiterals(@NotNull final Set<PsiLiteralExpression> literals, @NotNull final PsiCall call,
120 @NotNull final List<HighlightInfo> out) {
121 for (PsiLiteralExpression literal : literals) {
122 final HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, literal, null);
123 final ChangeStringLiteralToCharInMethodCallFix fix = new ChangeStringLiteralToCharInMethodCallFix(literal, call);
124 QuickFixAction.registerQuickFixAction(info, fix);
125 out.add(info);
130 * @return <code>true</code> if exact TYPEs match
132 private static boolean findMatchingExpressions(final PsiExpression[] arguments, final PsiMethod existingMethod,
133 final Set<PsiLiteralExpression> result) {
134 final PsiParameterList parameterList = existingMethod.getParameterList();
135 final PsiParameter[] parameters = parameterList.getParameters();
137 if (arguments.length != parameters.length) {
138 return false;
141 boolean typeMatch = true;
142 for (int i = 0; (i < parameters.length) && (i < arguments.length); i++) {
143 final PsiParameter parameter = parameters[i];
144 final PsiType parameterType = parameter.getType();
145 final PsiType argumentType = arguments[i].getType();
147 typeMatch &= Comparing.equal(parameterType, argumentType);
149 if ((arguments[i] instanceof PsiLiteralExpression) &&
150 (! result.contains(arguments[i])) &&
151 (charToString(parameterType, argumentType) || charToString(argumentType, parameterType))) {
153 final String value = String.valueOf(((PsiLiteralExpression) arguments[i]).getValue());
154 if ((value != null) && (value.length() == 1)) {
155 result.add((PsiLiteralExpression) arguments[i]);
159 return typeMatch;
162 private static boolean charToString(final PsiType firstType, final PsiType secondType) {
163 return Comparing.equal(PsiType.CHAR, firstType) && isString(secondType);
166 private static boolean isString(final PsiType type) {
167 return (type != null) && "java.lang.String".equals((type.getCanonicalText()));