Search in sources :

Example 6 with TypeConversionDescriptor

use of com.intellij.refactoring.typeMigration.TypeConversionDescriptor in project intellij-community by JetBrains.

the class ConvertFieldToAtomicIntention method invoke.

@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
    final PsiVariable psiVariable = getVariable(element);
    LOG.assertTrue(psiVariable != null);
    final Query<PsiReference> refs = ReferencesSearch.search(psiVariable);
    final Set<PsiElement> elements = new HashSet<>();
    elements.add(element);
    for (PsiReference reference : refs) {
        elements.add(reference.getElement());
    }
    if (!FileModificationService.getInstance().preparePsiElementsForWrite(elements))
        return;
    psiVariable.normalizeDeclaration();
    final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
    final PsiType fromType = psiVariable.getType();
    PsiClassType toType;
    final String atomicQualifiedName = myFromToMap.get(fromType);
    if (atomicQualifiedName != null) {
        final PsiClass atomicClass = psiFacade.findClass(atomicQualifiedName, GlobalSearchScope.allScope(project));
        if (atomicClass == null) {
            //show warning
            return;
        }
        toType = factory.createType(atomicClass);
    } else if (fromType instanceof PsiArrayType) {
        final PsiClass atomicReferenceArrayClass = psiFacade.findClass(AtomicReferenceArray.class.getName(), GlobalSearchScope.allScope(project));
        if (atomicReferenceArrayClass == null) {
            //show warning
            return;
        }
        final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
        final PsiTypeParameter[] typeParameters = atomicReferenceArrayClass.getTypeParameters();
        if (typeParameters.length == 1) {
            PsiType componentType = ((PsiArrayType) fromType).getComponentType();
            if (componentType instanceof PsiPrimitiveType)
                componentType = ((PsiPrimitiveType) componentType).getBoxedType(element);
            substitutor.put(typeParameters[0], componentType);
        }
        toType = factory.createType(atomicReferenceArrayClass, factory.createSubstitutor(substitutor));
    } else {
        final PsiClass atomicReferenceClass = psiFacade.findClass(AtomicReference.class.getName(), GlobalSearchScope.allScope(project));
        if (atomicReferenceClass == null) {
            //show warning
            return;
        }
        final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
        final PsiTypeParameter[] typeParameters = atomicReferenceClass.getTypeParameters();
        if (typeParameters.length == 1) {
            PsiType type = fromType;
            if (type instanceof PsiPrimitiveType)
                type = ((PsiPrimitiveType) fromType).getBoxedType(element);
            substitutor.put(typeParameters[0], type);
        }
        toType = factory.createType(atomicReferenceClass, factory.createSubstitutor(substitutor));
    }
    try {
        for (PsiReference reference : refs) {
            PsiElement refElement = reference.getElement();
            PsiElement psiElement = refElement;
            if (psiElement instanceof PsiExpression) {
                final PsiElement parent = psiElement.getParent();
                if (parent instanceof PsiExpression && !(parent instanceof PsiReferenceExpression || parent instanceof PsiPolyadicExpression)) {
                    psiElement = parent;
                }
                if (psiElement instanceof PsiBinaryExpression) {
                    PsiBinaryExpression binary = (PsiBinaryExpression) psiElement;
                    if (isBinaryOpApplicable(binary.getOperationTokenType(), binary.getLOperand(), binary.getROperand(), refElement, toType)) {
                        continue;
                    }
                } else if (psiElement instanceof PsiAssignmentExpression) {
                    final PsiAssignmentExpression assignment = (PsiAssignmentExpression) psiElement;
                    final IElementType opSign = TypeConversionUtil.convertEQtoOperation(assignment.getOperationTokenType());
                    if (isBinaryOpApplicable(opSign, assignment.getLExpression(), assignment.getRExpression(), refElement, toType)) {
                        continue;
                    }
                }
                final TypeConversionDescriptor directConversion = AtomicConversionRule.findDirectConversion(psiElement, toType, fromType);
                if (directConversion != null) {
                    TypeMigrationReplacementUtil.replaceExpression((PsiExpression) psiElement, project, directConversion, new TypeEvaluator(null, null));
                }
            }
        }
        PsiExpression initializer = psiVariable.getInitializer();
        if (initializer != null) {
            if (initializer instanceof PsiArrayInitializerExpression) {
                PsiExpression normalizedExpr = RefactoringUtil.createNewExpressionFromArrayInitializer((PsiArrayInitializerExpression) initializer, psiVariable.getType());
                initializer = (PsiExpression) initializer.replace(normalizedExpr);
            }
            final TypeConversionDescriptor directConversion = AtomicConversionRule.wrapWithNewExpression(toType, fromType, initializer, element);
            if (directConversion != null) {
                TypeMigrationReplacementUtil.replaceExpression(initializer, project, directConversion, new TypeEvaluator(null, null));
            }
        } else if (!assertNotNull(psiVariable.getModifierList()).hasModifierProperty(PsiModifier.FINAL)) {
            final PsiExpression newInitializer = factory.createExpressionFromText("new " + toType.getCanonicalText() + "()", psiVariable);
            if (psiVariable instanceof PsiLocalVariable) {
                ((PsiLocalVariable) psiVariable).setInitializer(newInitializer);
            } else if (psiVariable instanceof PsiField) {
                ((PsiField) psiVariable).setInitializer(newInitializer);
            }
            JavaCodeStyleManager.getInstance(project).shortenClassReferences(psiVariable.getInitializer());
        }
        PsiElement replaced = assertNotNull(psiVariable.getTypeElement()).replace(factory.createTypeElement(toType));
        JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced);
        if (psiVariable instanceof PsiField || CodeStyleSettingsManager.getSettings(project).GENERATE_FINAL_LOCALS) {
            final PsiModifierList modifierList = assertNotNull(psiVariable.getModifierList());
            modifierList.setModifierProperty(PsiModifier.FINAL, true);
            modifierList.setModifierProperty(PsiModifier.VOLATILE, false);
        }
    } catch (IncorrectOperationException e) {
        LOG.error(e);
    }
}
Also used : TypeEvaluator(com.intellij.refactoring.typeMigration.TypeEvaluator) HashSet(java.util.HashSet) IElementType(com.intellij.psi.tree.IElementType) TypeConversionDescriptor(com.intellij.refactoring.typeMigration.TypeConversionDescriptor) IncorrectOperationException(com.intellij.util.IncorrectOperationException) Map(java.util.Map)

Example 7 with TypeConversionDescriptor

use of com.intellij.refactoring.typeMigration.TypeConversionDescriptor in project intellij-community by JetBrains.

the class AtomicConversionRule method findDirectConversionForAtomicReferenceArray.

@Nullable
private static TypeConversionDescriptor findDirectConversionForAtomicReferenceArray(PsiElement context, PsiType to, PsiType from) {
    LOG.assertTrue(from instanceof PsiArrayType);
    from = ((PsiArrayType) from).getComponentType();
    final PsiElement parent = context.getParent();
    final PsiElement parentParent = parent.getParent();
    if (parent instanceof PsiAssignmentExpression) {
        final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) parent;
        final IElementType operationSign = assignmentExpression.getOperationTokenType();
        final String sign = assignmentExpression.getOperationSign().getText();
        if (context instanceof PsiArrayAccessExpression) {
            if (parentParent instanceof PsiExpressionStatement) {
                if (assignmentExpression.getLExpression() == context) {
                    if (operationSign == JavaTokenType.EQ) {
                        return new TypeConversionDescriptor("$qualifier$[$idx$] = $val$", "$qualifier$.set($idx$, $val$)", assignmentExpression);
                    } else {
                        return new TypeConversionDescriptor("$qualifier$[$idx$]" + sign + "$val$", "$qualifier$.set($idx$, " + getBoxedWrapper(from, to, "$qualifier$.get($idx$) " + sign.charAt(0) + " $val$") + ")", assignmentExpression);
                    }
                }
            }
        //else should be a conflict
        } else {
            final PsiExpression rExpression = assignmentExpression.getRExpression();
            if (rExpression == context && operationSign == JavaTokenType.EQ) {
                //array = new T[l];
                return wrapWithNewExpression(to, from, rExpression, context);
            }
        }
    } else if (parent instanceof PsiVariable) {
        if (((PsiVariable) parent).getInitializer() == context) {
            return wrapWithNewExpression(to, from, (PsiExpression) context, context);
        }
    }
    if (parentParent instanceof PsiExpressionStatement) {
        if (parent instanceof PsiPostfixExpression) {
            final String sign = ((PsiPostfixExpression) parent).getOperationSign().getText();
            return new TypeConversionDescriptor("$qualifier$[$idx$]" + sign, "$qualifier$.getAndSet($idx$, " + getBoxedWrapper(from, to, "$qualifier$.get($idx$) " + sign.charAt(0) + " 1") + ")", (PsiExpression) parent);
        } else if (parent instanceof PsiPrefixExpression) {
            final String sign = ((PsiPrefixExpression) parent).getOperationSign().getText();
            return new TypeConversionDescriptor(sign + "$qualifier$[$idx$]", "$qualifier$.set($idx$, " + getBoxedWrapper(from, to, "$qualifier$.get($idx$) " + sign.charAt(0) + " 1") + ")", (PsiExpression) parent);
        } else if (parent instanceof PsiBinaryExpression) {
            final String sign = ((PsiBinaryExpression) parent).getOperationSign().getText();
            return new TypeConversionDescriptor("$qualifier$[$idx$]" + sign + "$val$", "$qualifier$.set($idx$, " + getBoxedWrapper(from, to, "$qualifier$.get($idx$) " + sign + " $val$)") + ")", (PsiExpression) parent);
        }
    }
    if (context instanceof PsiArrayAccessExpression) {
        return new TypeConversionDescriptor("$qualifier$[$idx$]", "$qualifier$.get($idx$)", (PsiExpression) context);
    }
    return null;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) TypeConversionDescriptor(com.intellij.refactoring.typeMigration.TypeConversionDescriptor) Nullable(org.jetbrains.annotations.Nullable)

Example 8 with TypeConversionDescriptor

use of com.intellij.refactoring.typeMigration.TypeConversionDescriptor in project intellij-community by JetBrains.

the class ElementToArrayConversionRule method findConversion.

public TypeConversionDescriptorBase findConversion(final PsiType from, final PsiType to, final PsiMember member, final PsiExpression context, final TypeMigrationLabeler labeler) {
    if (member == null && to instanceof PsiArrayType && TypeConversionUtil.isAssignable(((PsiArrayType) to).getComponentType(), from)) {
        TypeConversionDescriptor wrapDescription = new TypeConversionDescriptor("$qualifier$", "new " + from.getCanonicalText() + "[]{$qualifier$}", context);
        if (((PsiArrayType) to).getComponentType() instanceof PsiClassType && from instanceof PsiPrimitiveType) {
            final String boxedTypeName = ((PsiPrimitiveType) from).getBoxedTypeName();
            final String normalizedArrayInitializer = PsiUtil.isLanguageLevel5OrHigher(context) ? "$qualifier$" : boxedTypeName + ".valueOf($qualifier$)";
            wrapDescription = new TypeConversionDescriptor("$qualifier$", "new " + boxedTypeName + "[]{" + normalizedArrayInitializer + "}", context);
        }
        final PsiElement parent = context.getParent();
        if ((context instanceof PsiLiteralExpression || context instanceof PsiReferenceExpression) && parent instanceof PsiStatement) {
            return wrapDescription;
        }
        if (parent instanceof PsiAssignmentExpression && ((PsiAssignmentExpression) parent).getRExpression() == context) {
            return wrapDescription;
        }
    }
    return null;
}
Also used : TypeConversionDescriptor(com.intellij.refactoring.typeMigration.TypeConversionDescriptor)

Example 9 with TypeConversionDescriptor

use of com.intellij.refactoring.typeMigration.TypeConversionDescriptor in project intellij-community by JetBrains.

the class ThreadLocalConversionRule method findDirectConversion.

@Nullable
public static TypeConversionDescriptor findDirectConversion(PsiElement context, PsiType to, PsiType from, TypeMigrationLabeler labeler) {
    final PsiClass toTypeClass = PsiUtil.resolveClassInType(to);
    LOG.assertTrue(toTypeClass != null);
    if (context instanceof PsiArrayAccessExpression) {
        return new TypeConversionDescriptor("$qualifier$[$val$]", "$qualifier$.get()[$val$]");
    }
    final PsiElement parent = context.getParent();
    if (parent instanceof PsiAssignmentExpression) {
        final IElementType operationSign = ((PsiAssignmentExpression) parent).getOperationTokenType();
        if (operationSign == JavaTokenType.EQ) {
            return new TypeConversionDescriptor("$qualifier$ = $val$", "$qualifier$.set(" + toBoxed("$val$", from, context) + ")", (PsiAssignmentExpression) parent);
        }
    }
    if (context instanceof PsiReferenceExpression) {
        final PsiExpression qualifierExpression = ((PsiReferenceExpression) context).getQualifierExpression();
        final PsiExpression expression = context.getParent() instanceof PsiMethodCallExpression && qualifierExpression != null ? qualifierExpression : (PsiExpression) context;
        return new TypeConversionDescriptor("$qualifier$", toPrimitive("$qualifier$.get()", from, context), expression);
    } else if (context instanceof PsiBinaryExpression) {
        final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) context;
        final String sign = binaryExpression.getOperationSign().getText();
        return new TypeConversionDescriptor("$qualifier$" + sign + "$val$", toPrimitive("$qualifier$.get()", from, context) + " " + sign + " $val$");
    }
    if (parent instanceof PsiExpressionStatement) {
        if (context instanceof PsiPostfixExpression) {
            final PsiPostfixExpression postfixExpression = (PsiPostfixExpression) context;
            final String sign = postfixExpression.getOperationSign().getText();
            return new TypeConversionDescriptor("$qualifier$" + sign, "$qualifier$.set(" + getBoxedWrapper(from, to, toPrimitive("$qualifier$.get()", from, context) + " " + sign.charAt(0) + " 1", labeler, context, postfixExpression.getOperand().getText() + sign.charAt(0) + " 1") + ")");
        } else if (context instanceof PsiPrefixExpression) {
            final PsiPrefixExpression prefixExpression = (PsiPrefixExpression) context;
            final PsiJavaToken operationSign = ((PsiPrefixExpression) context).getOperationSign();
            if (operationSign.getTokenType() == JavaTokenType.EXCL) {
                return new TypeConversionDescriptor("!$qualifier$", "!$qualifier$.get()");
            }
            final String sign = operationSign.getText();
            final PsiExpression operand = prefixExpression.getOperand();
            return new TypeConversionDescriptor(sign + "$qualifier$", "$qualifier$.set(" + getBoxedWrapper(from, to, toPrimitive("$qualifier$.get()", from, context) + " " + sign.charAt(0) + " 1", labeler, context, operand != null ? operand.getText() + sign.charAt(0) + " 1" : null) + ")");
        } else if (context instanceof PsiAssignmentExpression) {
            final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) context;
            final PsiJavaToken signToken = assignmentExpression.getOperationSign();
            final IElementType operationSign = signToken.getTokenType();
            final String sign = signToken.getText();
            final PsiExpression lExpression = assignmentExpression.getLExpression();
            if (operationSign == JavaTokenType.EQ) {
                if (lExpression instanceof PsiReferenceExpression) {
                    final PsiElement element = ((PsiReferenceExpression) lExpression).resolve();
                    if (element instanceof PsiVariable && ((PsiVariable) element).hasModifierProperty(PsiModifier.FINAL)) {
                        return wrapWithNewExpression(to, from, ((PsiAssignmentExpression) context).getRExpression());
                    }
                }
                return new TypeConversionDescriptor("$qualifier$ = $val$", "$qualifier$.set(" + toBoxed("$val$", from, context) + ")");
            } else {
                final PsiExpression rExpression = assignmentExpression.getRExpression();
                return new TypeConversionDescriptor("$qualifier$" + sign + "$val$", "$qualifier$.set(" + getBoxedWrapper(from, to, toPrimitive("$qualifier$.get()", from, context) + " " + sign.charAt(0) + " $val$", labeler, context, rExpression != null ? lExpression.getText() + sign.charAt(0) + rExpression.getText() : null) + ")");
            }
        }
    }
    return null;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) TypeConversionDescriptor(com.intellij.refactoring.typeMigration.TypeConversionDescriptor) Nullable(org.jetbrains.annotations.Nullable)

Example 10 with TypeConversionDescriptor

use of com.intellij.refactoring.typeMigration.TypeConversionDescriptor in project intellij-community by JetBrains.

the class FluentIterableConversionUtil method createToCollectionDescriptor.

static TypeConversionDescriptor createToCollectionDescriptor(@Nullable String methodName, @NotNull PsiExpression context) {
    final String findTemplate;
    final String replaceTemplate;
    final String returnType;
    if ("toMap".equals(methodName) || "uniqueIndex".equals(methodName)) {
        final GuavaTypeConversionDescriptor descriptor = new GuavaTypeConversionDescriptor("$it$.$methodName$($f$)", "$it$.collect(java.util.stream.Collectors.toMap(java.util.function.Function.identity(), $f$))");
        return descriptor.withConversionType(GuavaConversionUtil.addTypeParameters(CommonClassNames.JAVA_UTIL_MAP, context.getType(), context));
    } else if ("toList".equals(methodName)) {
        findTemplate = "$it$.toList()";
        replaceTemplate = GuavaFluentIterableConversionRule.STREAM_COLLECT_TO_LIST;
        returnType = CommonClassNames.JAVA_UTIL_LIST;
    } else if ("toSet".equals(methodName)) {
        findTemplate = "$it$.toSet()";
        replaceTemplate = "$it$.collect(java.util.stream.Collectors.toSet())";
        returnType = CommonClassNames.JAVA_UTIL_SET;
    } else if ("toSortedList".equals(methodName)) {
        findTemplate = "$it$.toSortedList($c$)";
        replaceTemplate = "$it$.sorted($c$).collect(java.util.stream.Collectors.toList())";
        returnType = CommonClassNames.JAVA_UTIL_LIST;
    } else if ("toSortedSet".equals(methodName)) {
        findTemplate = "$it$.toSortedSet($c$)";
        replaceTemplate = "$it$.collect(java.util.stream.Collectors.toCollection(() -> new java.util.TreeSet<>($c$)))";
        returnType = CommonClassNames.JAVA_UTIL_SET;
    } else {
        return null;
    }
    final PsiType type = GuavaConversionUtil.addTypeParameters(returnType, context.getType(), context);
    return new TypeConversionDescriptor(findTemplate, replaceTemplate).withConversionType(type);
}
Also used : TypeConversionDescriptor(com.intellij.refactoring.typeMigration.TypeConversionDescriptor)

Aggregations

TypeConversionDescriptor (com.intellij.refactoring.typeMigration.TypeConversionDescriptor)13 Nullable (org.jetbrains.annotations.Nullable)8 IElementType (com.intellij.psi.tree.IElementType)5 TypeEvaluator (com.intellij.refactoring.typeMigration.TypeEvaluator)5 NotNull (org.jetbrains.annotations.NotNull)3 JavaCodeStyleManager (com.intellij.psi.codeStyle.JavaCodeStyleManager)1 SuggestedNameInfo (com.intellij.psi.codeStyle.SuggestedNameInfo)1 TypeConversionDescriptorBase (com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase)1 IncorrectOperationException (com.intellij.util.IncorrectOperationException)1 HashSet (java.util.HashSet)1 Map (java.util.Map)1 NonNls (org.jetbrains.annotations.NonNls)1