use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.
the class TypeEvaluator method getReport.
public String getReport() {
final StringBuilder buffer = new StringBuilder();
final String[] t = new String[myTypeMap.size()];
int k = 0;
for (final TypeMigrationUsageInfo info : myTypeMap.keySet()) {
final LinkedList<PsiType> types = myTypeMap.get(info);
final StringBuilder b = new StringBuilder();
if (types != null) {
b.append(info.getElement()).append(" : ");
b.append(StringUtil.join(types, psiType -> psiType.getCanonicalText(), " "));
b.append("\n");
}
t[k++] = b.toString();
}
Arrays.sort(t);
for (String aT : t) {
buffer.append(aT);
}
return buffer.toString();
}
use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.
the class TypeEvaluator method evaluateType.
@Nullable
public PsiType evaluateType(final PsiExpression expr) {
if (expr == null)
return null;
final LinkedList<PsiType> e = myTypeMap.get(new TypeMigrationUsageInfo(expr));
if (e != null) {
return e.getFirst();
}
if (expr instanceof PsiArrayAccessExpression) {
final PsiType at = evaluateType(((PsiArrayAccessExpression) expr).getArrayExpression());
if (at instanceof PsiArrayType) {
return ((PsiArrayType) at).getComponentType();
}
} else if (expr instanceof PsiAssignmentExpression) {
return evaluateType(((PsiAssignmentExpression) expr).getLExpression());
} else if (expr instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression call = (PsiMethodCallExpression) expr;
final JavaResolveResult resolveResult = call.resolveMethodGenerics();
final PsiMethod method = (PsiMethod) resolveResult.getElement();
if (method != null) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
final PsiExpression[] actualParms = call.getArgumentList().getExpressions();
return PsiUtil.captureToplevelWildcards(createMethodSubstitution(parameters, actualParms, method, call, resolveResult.getSubstitutor(), false).substitute(evaluateType(call.getMethodExpression())), expr);
}
} else if (expr instanceof PsiPolyadicExpression) {
final PsiExpression[] operands = ((PsiPolyadicExpression) expr).getOperands();
final IElementType sign = ((PsiPolyadicExpression) expr).getOperationTokenType();
PsiType lType = operands.length > 0 ? evaluateType(operands[0]) : null;
for (int i = 1; i < operands.length; i++) {
lType = TypeConversionUtil.calcTypeForBinaryExpression(lType, evaluateType(operands[i]), sign, true);
}
return lType;
} else if (expr instanceof PsiPostfixExpression) {
return evaluateType(((PsiPostfixExpression) expr).getOperand());
} else if (expr instanceof PsiPrefixExpression) {
return evaluateType(((PsiPrefixExpression) expr).getOperand());
} else if (expr instanceof PsiParenthesizedExpression) {
return evaluateType(((PsiParenthesizedExpression) expr).getExpression());
} else if (expr instanceof PsiConditionalExpression) {
final PsiExpression thenExpression = ((PsiConditionalExpression) expr).getThenExpression();
final PsiExpression elseExpression = ((PsiConditionalExpression) expr).getElseExpression();
final PsiType thenType = evaluateType(thenExpression);
final PsiType elseType = evaluateType(elseExpression);
switch((thenType == null ? 0 : 1) + (elseType == null ? 0 : 2)) {
case 0:
return expr.getType();
case 1:
return thenType;
case 2:
return elseType;
case 3:
if (TypeConversionUtil.areTypesConvertible(thenType, elseType)) {
return thenType;
} else if (TypeConversionUtil.areTypesConvertible(elseType, thenType)) {
return elseType;
} else {
switch((thenType.equals(thenExpression.getType()) ? 0 : 1) + (elseType.equals(elseExpression.getType()) ? 0 : 2)) {
case 0:
return expr.getType();
case 1:
return thenType;
case 2:
return elseType;
case 3:
return expr.getType();
default:
LOG.error("Must not happen.");
return null;
}
}
default:
LOG.error("Must not happen.");
}
} else if (expr instanceof PsiNewExpression) {
final PsiExpression qualifier = ((PsiNewExpression) expr).getQualifier();
if (qualifier != null) {
final PsiClassType.ClassResolveResult qualifierResult = resolveType(evaluateType(qualifier));
if (qualifierResult.getElement() != null) {
final PsiSubstitutor qualifierSubs = qualifierResult.getSubstitutor();
final PsiClassType.ClassResolveResult result = resolveType(expr.getType());
if (result.getElement() != null) {
final PsiClass aClass = result.getElement();
return JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(aClass, result.getSubstitutor().putAll(qualifierSubs));
}
}
}
} else if (expr instanceof PsiFunctionalExpression) {
final PsiType functionalInterfaceType = ((PsiFunctionalExpression) expr).getFunctionalInterfaceType();
if (functionalInterfaceType != null) {
return functionalInterfaceType;
}
} else if (expr instanceof PsiReferenceExpression) {
final PsiType type = evaluateReferenceExpressionType(expr);
if (type != null) {
return PsiImplUtil.normalizeWildcardTypeByPosition(type, expr);
}
} else if (expr instanceof PsiSuperExpression) {
final PsiClass psiClass = PsiTreeUtil.getParentOfType(expr, PsiClass.class);
if (psiClass != null) {
final PsiClass superClass = psiClass.getSuperClass();
if (superClass != null) {
return getType(new TypeMigrationUsageInfo(superClass));
}
}
}
return getType(expr);
}
use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.
the class TypeMigrationLabeler method addMigrationRoot.
boolean addMigrationRoot(PsiElement element, PsiType type, final PsiElement place, boolean alreadyProcessed, final boolean isContraVariantPosition, final boolean userDefinedType) {
if (type.equals(PsiType.NULL)) {
return false;
}
final PsiElement resolved = Util.normalizeElement(element);
if (!canBeRoot(resolved, myRules.getSearchScope())) {
return false;
}
final PsiType originalType = getElementType(resolved);
LOG.assertTrue(originalType != null);
type = userDefinedType ? type : TypeEvaluator.substituteType(type, originalType, isContraVariantPosition);
if (!userDefinedType) {
final Set<PsiTypeParameter> collector;
if (type instanceof PsiClassType) {
collector = type.accept(new PsiExtendedTypeVisitor<Set<PsiTypeParameter>>() {
private final Set<PsiTypeParameter> myResult = new HashSet<>();
@Override
public Set<PsiTypeParameter> visitClassType(PsiClassType classType) {
super.visitClassType(classType);
final PsiClass resolved = classType.resolve();
if (resolved instanceof PsiTypeParameter) {
myResult.add((PsiTypeParameter) resolved);
}
return myResult;
}
});
} else {
collector = Collections.emptySet();
}
if (typeContainsTypeParameters(originalType, collector))
return false;
}
if (type instanceof PsiCapturedWildcardType) {
return false;
}
if (resolved instanceof PsiMethod) {
final PsiMethod method = ((PsiMethod) resolved);
final PsiClass containingClass = method.getContainingClass();
if (containingClass instanceof PsiAnonymousClass) {
final HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature();
final List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
if (!superSignatures.isEmpty()) {
final HierarchicalMethodSignature superSignature = superSignatures.get(0);
final PsiSubstitutor substitutor = superSignature.getSubstitutor();
if (!substitutor.getSubstitutionMap().isEmpty()) {
final PsiMethod superMethod = superSignature.getMethod();
final PsiType superReturnType = superMethod.getReturnType();
if (superReturnType instanceof PsiClassType) {
final PsiClass resolvedClass = ((PsiClassType) superReturnType).resolve();
if (resolvedClass instanceof PsiTypeParameter) {
final PsiType expectedReturnType = substitutor.substitute((PsiTypeParameter) resolvedClass);
if (Comparing.equal(expectedReturnType, method.getReturnType())) {
final PsiClassType baseClassType = ((PsiAnonymousClass) containingClass).getBaseClassType();
final PsiClassType.ClassResolveResult result = baseClassType.resolveGenerics();
final PsiClass anonymousBaseClass = result.getElement();
final PsiSubstitutor superHierarchySubstitutor = TypeConversionUtil.getClassSubstitutor(superMethod.getContainingClass(), anonymousBaseClass, PsiSubstitutor.EMPTY);
final PsiType maybeTypeParameter = superHierarchySubstitutor.substitute((PsiTypeParameter) resolvedClass);
if (maybeTypeParameter instanceof PsiClassType && ((PsiClassType) maybeTypeParameter).resolve() instanceof PsiTypeParameter) {
final PsiSubstitutor newSubstitutor = result.getSubstitutor().put((PsiTypeParameter) ((PsiClassType) maybeTypeParameter).resolve(), type);
addRoot(new TypeMigrationUsageInfo(((PsiAnonymousClass) containingClass).getBaseClassReference().getParameterList()), new PsiImmediateClassType(anonymousBaseClass, newSubstitutor), place, alreadyProcessed);
}
}
}
}
}
}
}
final PsiMethod[] methods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
final OverriderUsageInfo[] overriders = new OverriderUsageInfo[methods.length];
for (int i = -1; i < methods.length; i++) {
final TypeMigrationUsageInfo m;
if (i < 0) {
final OverriddenUsageInfo overriddenUsageInfo = new OverriddenUsageInfo(method);
m = overriddenUsageInfo;
final String newMethodName = isMethodNameCanBeChanged(method);
if (newMethodName != null) {
final MigrateGetterNameSetting migrateGetterNameSetting = myRules.getConversionSettings(MigrateGetterNameSetting.class);
migrateGetterNameSetting.askUserIfNeed(overriddenUsageInfo, newMethodName, myTypeEvaluator.getType(myCurrentRoot));
}
} else {
overriders[i] = new OverriderUsageInfo(methods[i], method);
m = overriders[i];
}
alreadyProcessed = addRoot(m, type, place, alreadyProcessed);
}
return !alreadyProcessed;
} else if (resolved instanceof PsiParameter && ((PsiParameter) resolved).getDeclarationScope() instanceof PsiMethod) {
final PsiMethod method = (PsiMethod) ((PsiParameter) resolved).getDeclarationScope();
final int index = method.getParameterList().getParameterIndex(((PsiParameter) resolved));
final PsiMethod[] methods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
final OverriderUsageInfo[] overriders = new OverriderUsageInfo[methods.length];
final OverriddenUsageInfo overriddenUsageInfo = new OverriddenUsageInfo(method.getParameterList().getParameters()[index]);
for (int i = -1; i < methods.length; i++) {
final PsiMethod m = i < 0 ? method : methods[i];
final PsiParameter p = m.getParameterList().getParameters()[index];
final TypeMigrationUsageInfo paramUsageInfo;
if (i < 0) {
paramUsageInfo = overriddenUsageInfo;
} else {
overriders[i] = new OverriderUsageInfo(p, method);
paramUsageInfo = overriders[i];
}
alreadyProcessed = addRoot(paramUsageInfo, type, place, alreadyProcessed);
}
return !alreadyProcessed;
} else {
return !addRoot(new TypeMigrationUsageInfo(resolved), type, place, alreadyProcessed);
}
}
use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.
the class TypeMigrationLabeler method sortMigratedUsages.
private TypeMigrationUsageInfo[] sortMigratedUsages(TypeMigrationUsageInfo[] infos) {
final DFSTBuilder<TypeMigrationUsageInfo> builder = new DFSTBuilder<>(GraphGenerator.generate(new InboundSemiGraph<TypeMigrationUsageInfo>() {
@Override
public Collection<TypeMigrationUsageInfo> getNodes() {
final Set<TypeMigrationUsageInfo> infos = new HashSet<>();
for (Map.Entry<TypeMigrationUsageInfo, HashSet<Pair<TypeMigrationUsageInfo, PsiType>>> entry : myRootsTree.entrySet()) {
infos.add(entry.getKey());
infos.addAll(ContainerUtil.map(entry.getValue(), pair -> pair.getFirst()));
}
return infos;
}
@Override
public Iterator<TypeMigrationUsageInfo> getIn(TypeMigrationUsageInfo n) {
final HashSet<Pair<TypeMigrationUsageInfo, PsiType>> rawNodes = myRootsTree.get(n);
if (rawNodes == null) {
return Collections.<TypeMigrationUsageInfo>emptyList().iterator();
}
final List<TypeMigrationUsageInfo> in = ContainerUtil.map(rawNodes, pair -> pair.getFirst());
return in.iterator();
}
}));
final Comparator<TypeMigrationUsageInfo> cmp = builder.comparator();
Arrays.sort(infos, (info1, info2) -> {
final TypeMigrationUsageInfo i1 = info1.getOwnerRoot();
final TypeMigrationUsageInfo i2 = info2.getOwnerRoot();
if (i1 == null && i2 == null) {
return 0;
}
if (i1 == null) {
return 1;
}
if (i2 == null) {
return -1;
}
final PsiElement element1 = info1.getElement();
final PsiElement element2 = info2.getElement();
LOG.assertTrue(element1 != null && element2 != null);
if (element1.equals(element2)) {
return 0;
}
final TextRange range1 = element1.getTextRange();
final TextRange range2 = element2.getTextRange();
if (range1.contains(range2)) {
return 1;
}
if (range2.contains(range1)) {
return -1;
}
final int res = cmp.compare(i1, i2);
if (res != 0) {
return res;
}
return range2.getStartOffset() - range1.getStartOffset();
});
return infos;
}
use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.
the class MigrationUsagesPanel method showRootUsages.
public void showRootUsages(UsageInfo root, UsageInfo migration, final TypeMigrationLabeler labeler) {
final PsiElement rootElement = root.getElement();
if (rootElement == null)
return;
final Set<PsiElement> usages = labeler.getTypeUsages((TypeMigrationUsageInfo) migration, ((TypeMigrationUsageInfo) root));
if (usages != null) {
final List<UsageInfo> infos = new ArrayList<>(usages.size());
for (PsiElement usage : usages) {
if (usage != null && usage.isValid()) {
infos.add(new UsageInfo(usage));
}
}
showUsages(new PsiElement[] { rootElement }, infos.toArray(new UsageInfo[infos.size()]));
} else {
showUsages(new PsiElement[] { rootElement }, new UsageInfo[] { migration });
}
}
Aggregations