qualify this with containing class (IDEA-49251)

This commit is contained in:
anna
2011-10-25 20:17:53 +02:00
parent ed24c9b396
commit 1ba41a4b26
10 changed files with 249 additions and 0 deletions
@@ -505,6 +505,7 @@ public class HighlightMethodUtil {
VariableTypeFromCallFix.registerQuickFixActions(methodCall, list, highlightInfo);
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new ReplaceAddAllArrayToCollectionFix(methodCall), null);
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new SurroundWithArrayFix(methodCall), null);
QualifyThisArgumentFix.registerQuickFixAction(methodCandidates, methodCall, highlightInfo, fixRange);
CandidateInfo[] candidates = resolveHelper.getReferencedMethodCandidates(methodCall, true);
ChangeStringLiteralToCharInMethodCallFix.registerFixes(candidates, methodCall, highlightInfo);
@@ -0,0 +1,121 @@
/*
* 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.
*/
/**
* Created by IntelliJ IDEA.
* User: cdr
* Date: Nov 13, 2002
* Time: 3:26:50 PM
* To change this template use Options | File Templates.
*/
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
public class QualifyThisArgumentFix extends PsiElementBaseIntentionAction {
private final PsiThisExpression myExpression;
private final PsiClass myPsiClass;
public QualifyThisArgumentFix(@NotNull PsiThisExpression expression, @NotNull PsiClass psiClass) {
myExpression = expression;
myPsiClass = psiClass;
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
if (!myExpression.isValid()) return false;
if (!myPsiClass.isValid()) return false;
setText("Qualify this expression with \'" + myPsiClass.getQualifiedName() + "\'");
return true;
}
@NotNull
@Override
public String getFamilyName() {
return "Qualify this";
}
@Override
public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException {
myExpression.replace(RefactoringUtil.createThisExpression(PsiManager.getInstance(project), myPsiClass));
}
public static void registerQuickFixAction(CandidateInfo[] candidates, PsiCall call, HighlightInfo highlightInfo, final TextRange fixRange) {
if (candidates.length == 0) return;
final Set<PsiClass> containingClasses = new HashSet<PsiClass>();
PsiClass parentClass = PsiTreeUtil.getParentOfType(call, PsiClass.class);
while (parentClass != null) {
if (parentClass.hasModifierProperty(PsiModifier.STATIC)) break;
if (!(parentClass instanceof PsiAnonymousClass)) {
containingClasses.add(parentClass);
}
parentClass = PsiTreeUtil.getParentOfType(parentClass, PsiClass.class, true);
}
if (containingClasses.isEmpty()) return;
final PsiExpressionList list = call.getArgumentList();
final PsiExpression[] expressions = list.getExpressions();
if (expressions.length == 0) return;
for (int i1 = 0, expressionsLength = expressions.length; i1 < expressionsLength; i1++) {
final PsiExpression expression = expressions[i1];
if (expression instanceof PsiThisExpression) {
final PsiType exprType = expression.getType();
for (CandidateInfo candidate : candidates) {
PsiMethod method = (PsiMethod)candidate.getElement();
PsiSubstitutor substitutor = candidate.getSubstitutor();
assert method != null;
PsiParameter[] parameters = method.getParameterList().getParameters();
if (expressions.length != parameters.length) {
continue;
}
PsiParameter parameter = parameters[i1];
PsiType parameterType = substitutor.substitute(parameter.getType());
if (exprType == null || parameterType == null) {
continue;
}
if (!TypeConversionUtil.isAssignable(parameterType, exprType)) {
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(parameterType);
if (psiClass != null && containingClasses.contains(psiClass)) {
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new QualifyThisArgumentFix((PsiThisExpression)expression, psiClass), null);
}
}
}
}
}
}
}
@@ -0,0 +1,10 @@
// "Qualify this expression with 'Test'" "true"
class Test {
void foo(Test t){}
class Foo {
Foo() {
foo(Test.this);
}
}
}
@@ -0,0 +1,18 @@
// "Qualify this expression with 'Test.Foo'" "true"
class Test {
void foo(Foo m) {
}
class Foo {
void bar() {
new Runnable() {
@Override
public void run() {
foo(Foo.this);
}
}.run();
}
}
}
@@ -0,0 +1,10 @@
// "Qualify this expression with 'Test'" "true"
class Test {
void foo(Test t){}
class Foo {
Foo() {
foo(thi<caret>s);
}
}
}
@@ -0,0 +1,10 @@
// "Qualify this expression with 'Test'" "false"
class Test {
void foo(Test t){}
static class Foo {
Foo() {
foo(thi<caret>s);
}
}
}
@@ -0,0 +1,10 @@
// "Qualify this expression with 'Test'" "false"
class Test {
void foo(String t){}
static class Foo {
Foo() {
foo(thi<caret>s);
}
}
}
@@ -0,0 +1,24 @@
// "Qualify this expression with 'Test.Foo'" "false"
class Test {
public void main() {
new Foo() {
void bar() {
new Runnable() {
@Override
public void run() {
foo(th<caret>is);
}
}.run();
}
}.toString();
}
void foo(Foo m) {
}
class Foo {
}
}
@@ -0,0 +1,18 @@
// "Qualify this expression with 'Test.Foo'" "true"
class Test {
void foo(Foo m) {
}
class Foo {
void bar() {
new Runnable() {
@Override
public void run() {
foo(th<caret>is);
}
}.run();
}
}
}
@@ -0,0 +1,27 @@
/*
* 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.quickFix;
public class QualifyThisArgumentFixTest extends LightQuickFixTestCase {
public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/qualifyThis";
}
}