public void migrateClassTypeParameter( final PsiReferenceParameterList referenceParameterList, final PsiClassType migrationType) { final PsiClass psiClass = PsiTreeUtil.getParentOfType(referenceParameterList, PsiClass.class); LOG.assertTrue(psiClass != null); final PsiClass superClass = psiClass.getSuperClass(); LOG.assertTrue(superClass != null); myLabeler.getTypeEvaluator().setType(new TypeMigrationUsageInfo(superClass), migrationType); final Map<PsiElement, Pair<PsiReference[], PsiType>> roots = new HashMap<PsiElement, Pair<PsiReference[], PsiType>>(); markTypeParameterUsages(psiClass, migrationType, referenceParameterList, roots); final Set<PsiElement> processed = new HashSet<PsiElement>(); for (Map.Entry<PsiElement, Pair<PsiReference[], PsiType>> entry : roots.entrySet()) { final PsiElement member = entry.getKey(); final PsiType type = entry.getValue().second; if (member instanceof PsiParameter && ((PsiParameter) member).getDeclarationScope() instanceof PsiMethod) { myLabeler.migrateMethodCallExpressions(type, (PsiParameter) member, psiClass); } final PsiReference[] references = entry.getValue().first; for (PsiReference usage : references) { myLabeler.migrateRootUsageExpression(usage, processed); } } }
/** signature should be changed for methods with type parameters */ private void prepareMethodsChangeSignature( final PsiClass currentClass, final PsiElement memberToChangeSignature, final PsiType memberType) { if (memberToChangeSignature instanceof PsiMethod) { final PsiMethod method = MethodSignatureUtil.findMethodBySuperMethod( currentClass, (PsiMethod) memberToChangeSignature, true); if (method != null && method.getContainingClass() == currentClass) { myLabeler.addRoot(new TypeMigrationUsageInfo(method), memberType, method, false); } } else if (memberToChangeSignature instanceof PsiParameter && ((PsiParameter) memberToChangeSignature).getDeclarationScope() instanceof PsiMethod) { final PsiMethod superMethod = (PsiMethod) ((PsiParameter) memberToChangeSignature).getDeclarationScope(); final int parameterIndex = superMethod.getParameterList().getParameterIndex((PsiParameter) memberToChangeSignature); final PsiMethod method = MethodSignatureUtil.findMethodBySuperMethod(currentClass, superMethod, true); if (method != null && method.getContainingClass() == currentClass) { final PsiParameter parameter = method.getParameterList().getParameters()[parameterIndex]; if (!parameter.getType().equals(memberType)) { myLabeler.addRoot(new TypeMigrationUsageInfo(parameter), memberType, parameter, false); } } } }
public static void change(TypeMigrationLabeler labeler, UsageInfo[] usages) { List<UsageInfo> nonCodeUsages = new ArrayList<UsageInfo>(); for (UsageInfo usage : usages) { if (((TypeMigrationUsageInfo) usage).isExcluded()) continue; final PsiElement element = usage.getElement(); if (element instanceof PsiVariable || element instanceof PsiMember || element instanceof PsiExpression || element instanceof PsiReferenceParameterList) { labeler.change((TypeMigrationUsageInfo) usage); } else { nonCodeUsages.add(usage); } } for (UsageInfo usageInfo : nonCodeUsages) { final PsiElement element = usageInfo.getElement(); if (element != null) { final PsiReference reference = element.getReference(); if (reference != null) { final Object target = labeler.getConversion(element); if (target instanceof PsiMember) { try { reference.bindToElement((PsiElement) target); } catch (IncorrectOperationException e) { // skip } } } } } }
@NotNull public UsageInfo[] findUsages() { myLabeler = new TypeMigrationLabeler(myRules); try { return myLabeler.getMigratedUsages(!isPreviewUsages(), myRoot); } catch (TypeMigrationLabeler.MigrateException e) { setPreviewUsages(true); return myLabeler.getMigratedUsages(false, myRoot); } }
public static void change(UsageInfo[] usages, TypeMigrationLabeler labeler, Project project) { final List<SmartPsiElementPointer<PsiNewExpression>> newExpressionsToCheckDiamonds = new SmartList<>(); final TypeMigrationLabeler.MigrationProducer producer = labeler.createMigratorFor(usages); final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project); List<UsageInfo> nonCodeUsages = new ArrayList<>(); for (UsageInfo usage : usages) { if (((TypeMigrationUsageInfo) usage).isExcluded()) continue; final PsiElement element = usage.getElement(); if (element instanceof PsiVariable || element instanceof PsiMember || element instanceof PsiExpression || element instanceof PsiReferenceParameterList) { producer.change( (TypeMigrationUsageInfo) usage, expression -> newExpressionsToCheckDiamonds.add( smartPointerManager.createSmartPsiElementPointer(expression))); } else { nonCodeUsages.add(usage); } } for (SmartPsiElementPointer<PsiNewExpression> newExpressionPointer : newExpressionsToCheckDiamonds) { final PsiNewExpression newExpression = newExpressionPointer.getElement(); if (newExpression != null) { labeler.postProcessNewExpression(newExpression); } } for (UsageInfo usageInfo : nonCodeUsages) { final PsiElement element = usageInfo.getElement(); if (element != null) { final PsiReference reference = element.getReference(); if (reference != null) { final Object target = producer.getConversion(usageInfo); if (target instanceof PsiMember) { try { reference.bindToElement((PsiElement) target); } catch (IncorrectOperationException ignored) { } } } } } producer.flush(); }
public static boolean canBeMigrated(final PsiElement e) { if (e == null) { return false; } final PsiElement element = normalizeElement(e); if (!element.getManager().isInProject(element)) { return false; } final PsiType type = TypeMigrationLabeler.getElementType(element); if (type != null) { final PsiType elemenType = type instanceof PsiArrayType ? type.getDeepComponentType() : type; if (elemenType instanceof PsiPrimitiveType) { return !elemenType.equals(PsiType.VOID); } final PsiClass aClass = ((PsiClassType) elemenType).resolve(); return aClass != null /* && !aClass.hasTypeParameters()*/; } return false; }
@Override protected void previewRefactoring(@NotNull final UsageInfo[] usages) { MigrationPanel panel = new MigrationPanel(myRoot, myLabeler, myProject, isPreviewUsages()); String name; if (myRoot.length == 1) { String fromType = assertNotNull(TypeMigrationLabeler.getElementType(myRoot[0])).getPresentableText(); String toType = myRootTypes.fun(myRoot[0]).getPresentableText(); String text; text = getPresentation(myRoot[0]); name = "Migrate Type of " + text + " from \'" + fromType + "\' to \'" + toType + "\'"; } else { final int rootsInPresentationCount = myRoot.length > MAX_ROOT_IN_PREVIEW_PRESENTATION ? MAX_ROOT_IN_PREVIEW_PRESENTATION : myRoot.length; String[] rootsPresentation = new String[rootsInPresentationCount]; for (int i = 0; i < rootsInPresentationCount; i++) { final PsiElement root = myRoot[i]; rootsPresentation[i] = root instanceof PsiNamedElement ? ((PsiNamedElement) root).getName() : root.getText(); } rootsPresentation = StringUtil.surround(rootsPresentation, "\'", "\'"); name = "Migrate Type of " + StringUtil.join(rootsPresentation, ", "); if (myRoot.length > MAX_ROOT_IN_PREVIEW_PRESENTATION) { name += "..."; } } Content content = UsageViewManager.getInstance(myProject).addContent(name, false, panel, true, true); panel.setContent(content); ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.FIND).activate(null); }
@Override protected void previewRefactoring(final UsageInfo[] usages) { MigrationPanel panel = new MigrationPanel(myRoot[0], myLabeler, myProject, isPreviewUsages()); String text; if (myRoot[0] instanceof PsiField) { text = "field \'" + ((PsiField) myRoot[0]).getName() + "\'"; } else if (myRoot[0] instanceof PsiParameter) { text = "parameter \'" + ((PsiParameter) myRoot[0]).getName() + "\'"; } else if (myRoot[0] instanceof PsiLocalVariable) { text = "variable \'" + ((PsiLocalVariable) myRoot[0]).getName() + "\'"; } else if (myRoot[0] instanceof PsiMethod) { text = "method \'" + ((PsiMethod) myRoot[0]).getName() + "\' return"; } else { text = Arrays.toString(myRoot); } Content content = UsageViewManager.getInstance(myProject) .addContent( "Migrate Type of " + text + " from \'" + TypeMigrationLabeler.getElementType(myRoot[0]).getPresentableText() + "\' to \'" + myRules.getMigrationRootType().getPresentableText() + "\'", false, panel, true, true); panel.setContent(content); ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.FIND).activate(null); }
@Override protected boolean preprocessUsages(@NotNull Ref<UsageInfo[]> refUsages) { if (hasFailedConversions()) { if (ApplicationManager.getApplication().isUnitTestMode()) { throw new RuntimeException(StringUtil.join(myLabeler.getFailedConversionsReport(), "\n")); } FailedConversionsDialog dialog = new FailedConversionsDialog(myLabeler.getFailedConversionsReport(), myProject); if (!dialog.showAndGet()) { final int exitCode = dialog.getExitCode(); prepareSuccessful(); if (exitCode == FailedConversionsDialog.VIEW_USAGES_EXIT_CODE) { previewRefactoring(refUsages.get()); } return false; } } prepareSuccessful(); return true; }
private void processMemberType( final PsiElement element, final TypeParameterSearcher parameterSearcher, final PsiClass psiClass, final PsiSubstitutor substitutor, final Map<PsiElement, Pair<PsiReference[], PsiType>> roots) { final PsiType elementType = TypeMigrationLabeler.getElementType(element); if (elementType != null && elementType.accept(parameterSearcher).booleanValue()) { final PsiType memberType = substitutor.substitute(elementType); prepareMethodsChangeSignature(psiClass, element, memberType); final List<PsiReference> refs = TypeMigrationLabeler.filterReferences( psiClass, ReferencesSearch.search(element, psiClass.getUseScope())); roots.put( element, Pair.create( myLabeler.markRootUsages( element, memberType, refs.toArray(new PsiReference[refs.size()])), memberType)); } }
public boolean hasFailedConversions() { return myLabeler.hasFailedConversions(); }