find type parameters for class

This commit is contained in:
anna
2009-11-24 16:23:53 +03:00
parent ce736df9a2
commit 073e7392bb
13 changed files with 133 additions and 28 deletions
@@ -18,6 +18,8 @@ package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.TokenType;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.Constants;
@@ -52,6 +54,13 @@ public class MethodElement extends CompositeElement implements Constants {
return super.addInternal(first, last, anchor, before);
}
@Override
public ASTNode copyElement() {
CharTable table = SharedImplUtil.findCharTableByTree(this);
final PsiClass psiClass = ((PsiMethod)getPsi()).getContainingClass();
return psiClass != null ? ChangeUtil.copyElement(this, psiClass.getTypeParameterList(), table) : super.copyElement();
}
public void deleteChildInternal(@NotNull ASTNode child) {
if (child.getElementType() == CODE_BLOCK){
final ASTNode prevWS = TreeUtil.prevLeaf(child);
@@ -510,27 +510,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
}
private void substituteMethodTypeParams(PsiElement scope, final PsiSubstitutor substitutor) {
scope.accept(new JavaRecursiveElementVisitor() {
@Override public void visitTypeElement(PsiTypeElement typeElement) {
PsiType type = typeElement.getType();
if (type instanceof PsiClassType) {
JavaResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
PsiElement resolved = resolveResult.getElement();
if (resolved instanceof PsiTypeParameter && ((PsiTypeParameter)resolved).getOwner() == myMethodCopy) {
PsiType newType = resolveResult.getSubstitutor().putAll(substitutor).substitute((PsiTypeParameter)resolved);
try {
typeElement.replace(myFactory.createTypeElement(newType));
return;
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
}
super.visitTypeElement(typeElement);
}
});
InlineUtil.substituteTypeParams(scope, substitutor, myFactory);
}
private boolean isStrictlyFinal(PsiParameter parameter) {
@@ -212,7 +212,6 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
return true;
}
}.run();
replaceInnerTypeUsages();
RefactoringUtil.sortDepthFirstRightLeftOrder(usages);
for (UsageInfo usageInfo : usages) {
@@ -225,6 +224,7 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
}
}
}
replaceInnerTypeUsages();
//postpone broken hierarchy
for (UsageInfo usage : usages) {
@@ -20,10 +20,10 @@
*/
package com.intellij.refactoring.inlineSuperClass.usageInfo;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiCodeBlock;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.*;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.util.FixableUsageInfo;
import com.intellij.refactoring.util.InlineUtil;
import com.intellij.util.IncorrectOperationException;
public class CopyDefaultConstructorUsageInfo extends FixableUsageInfo{
@@ -41,7 +41,11 @@ public class CopyDefaultConstructorUsageInfo extends FixableUsageInfo{
final PsiCodeBlock body = myConstructor.getBody();
assert body != null;
if (body.getFirstBodyElement() != null) { //do not copy empty constructor
myTargetClass.add(myConstructor.copy());
final PsiElement constructorCopy = myConstructor.copy();
final PsiClass srcClass = myConstructor.getContainingClass();
assert srcClass != null;
InlineUtil.substituteTypeParams(constructorCopy, TypeConversionUtil.getSuperClassSubstitutor(srcClass, myTargetClass, PsiSubstitutor.EMPTY), JavaPsiFacade.getElementFactory(getProject()));
myTargetClass.add(constructorCopy);
}
}
}
@@ -277,6 +277,30 @@ public class InlineUtil {
return TailCallType.None;
}
public static void substituteTypeParams(PsiElement scope, final PsiSubstitutor substitutor, final PsiElementFactory factory) {
scope.accept(new JavaRecursiveElementVisitor() {
@Override public void visitTypeElement(PsiTypeElement typeElement) {
PsiType type = typeElement.getType();
if (type instanceof PsiClassType) {
JavaResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
PsiElement resolved = resolveResult.getElement();
if (resolved instanceof PsiTypeParameter) {
PsiType newType = resolveResult.getSubstitutor().putAll(substitutor).substitute((PsiTypeParameter)resolved);
try {
typeElement.replace(factory.createTypeElement(newType));
return;
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
}
super.visitTypeElement(typeElement);
}
});
}
public enum TailCallType {
None, Simple, Return
}
@@ -0,0 +1,16 @@
import java.util.*;
public class Super<T> {
void <caret>foo() {
List<T> l = new ArrayList<T>();
for (T t : l) {
System.out.println(t);
}
}
}
class Test extends Super<String>{
void bar() {
foo();
}
}
@@ -0,0 +1,13 @@
import java.util.*;
public class Super<T> {
}
class Test extends Super<String>{
void bar() {
List<String> l = new ArrayList<String>();
for (String t : l) {
System.out.println(t);
}
}
}
@@ -0,0 +1,23 @@
import java.util.List;
import java.util.Set;
class Test {
List<String> l;
Test() {
Set<String> s = new HashSet<String>();
for (String t : s) {
System.out.println(t);
}
}
void foo(String t) {
System.out.println(t);
}
void bar() {
for (String t : l) {
System.out.println(t);
}
}
}
@@ -0,0 +1,22 @@
import java.util.*;
class Super<T> {
List<T> l;
Super() {
Set<T> s = new HashSet<T>();
for (T t : s) {
System.out.println(t);
}
}
void foo(T t) {
System.out.println(t);
}
void bar() {
for (T t : l) {
System.out.println(t);
}
}
}
@@ -0,0 +1,2 @@
class Test extends Super<String>{
}
@@ -155,6 +155,10 @@ public class InlineSuperClassTest extends MultiFileTestCase {
doTest();
}
public void testReplaceGenericsInside() throws Exception {
doTest();
}
public void testMultipleSubclasses() throws Exception {
doTest(new PerformAction() {
public void performAction(final VirtualFile rootDir, final VirtualFile rootAfter) throws Exception {
@@ -136,6 +136,10 @@ public class InlineMethodTest extends LightCodeInsightTestCase {
doTest();
}
public void testReplaceGenericsInside() throws Exception {
doTest();
}
@Override
protected Sdk getProjectJDK() {
return JavaSdkImpl.getMockJdk15("java 1.5");
@@ -129,10 +129,14 @@ public class ChangeUtil {
}
public static TreeElement copyElement(TreeElement original, CharTable table) {
CompositeElement treeParent = original.getTreeParent();
return copyElement(original, treeParent == null ? null : treeParent.getPsi(), table);
}
public static TreeElement copyElement(TreeElement original, final PsiElement context, CharTable table) {
final TreeElement element = (TreeElement)original.clone();
final PsiManager manager = original.getManager();
CompositeElement treeParent = original.getTreeParent();
DummyHolderFactory.createHolder(manager, element, treeParent == null ? null : treeParent.getPsi(), table).getTreeElement();
DummyHolderFactory.createHolder(manager, element, context, table).getTreeElement();
encodeInformation(element, original);
TreeUtil.clearCaches(element);
saveIndentationToCopy(original, element);