@NotNull public List<String> createConversions(@NotNull PsiCallExpression expression) { PsiExpressionList argumentList = expression.getArgumentList(); PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[] {}; List<String> conversions = new LinkedList<String>(); //noinspection UnusedDeclaration for (PsiExpression a : arguments) { conversions.add(""); } PsiMethod resolve = expression.resolveMethod(); if (resolve != null) { List<PsiType> expectedTypes = new LinkedList<PsiType>(); List<PsiType> actualTypes = new LinkedList<PsiType>(); for (PsiParameter p : resolve.getParameterList().getParameters()) expectedTypes.add(p.getType()); for (PsiExpression e : arguments) actualTypes.add(e.getType()); if (conversions.size() == actualTypes.size() && actualTypes.size() == expectedTypes.size()) { for (int i = 0; i < actualTypes.size(); i++) conversions.set(i, createConversionForExpression(arguments[i], expectedTypes.get(i))); } } return conversions; }
private void processListenerProperties(@NotNull PsiMethod method) { if (!method.getName().startsWith("add") || method.getParameterList().getParametersCount() != 1) return; final PsiParameter parameter = method.getParameterList().getParameters()[0]; final PsiType type = parameter.getType(); if (!(type instanceof PsiClassType)) return; final PsiClassType classType = (PsiClassType) type; final PsiClass listenerClass = classType.resolve(); if (listenerClass == null) return; final PsiMethod[] listenerMethods = listenerClass.getMethods(); if (!InheritanceUtil.isInheritorOrSelf(listenerClass, myEventListener, true)) return; for (PsiMethod listenerMethod : listenerMethods) { final String name = listenerMethod.getName(); if (myPropertyNames.add(name)) { LookupElementBuilder builder = LookupElementBuilder.create( generatePropertyResolveResult(name, listenerMethod, null, null), name) .withIcon(JetgroovyIcons.Groovy.Property); myConsumer.consume(builder); } } }
/** 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); } } } }
@NotNull public Parameter parameterToParameter(@NotNull PsiParameter parameter) { return new Parameter( new IdentifierImpl(parameter.getName()), typeToType( parameter.getType(), ConverterUtil.isAnnotatedAsNotNull(parameter.getModifierList()))); }
private static PsiType getNormalizedType(PsiParameter parameter) { final PsiType type = parameter.getType(); if (type instanceof PsiEllipsisType) { return ((PsiEllipsisType) type).getComponentType(); } return type; }
static boolean isArgumentInVarargPosition( PsiExpression[] expressions, int ei, PsiParameter varargParam, PsiSubstitutor substitutor) { if (varargParam == null) return false; final PsiExpression expression = expressions[ei]; if (expression == null || TypeConversionUtil.areTypesAssignmentCompatible( substitutor.substitute(((PsiEllipsisType) varargParam.getType()).getComponentType()), expression)) { final int lastExprIdx = expressions.length - 1; if (ei == lastExprIdx) return true; return expressions[lastExprIdx].getType() != PsiType.NULL; } return false; }
@NotNull private ParameterList createFunctionParameters(@NotNull PsiMethod method) { List<Parameter> result = new LinkedList<Parameter>(); for (PsiParameter parameter : method.getParameterList().getParameters()) { result.add( new Parameter( new IdentifierImpl(parameter.getName()), typeToType( parameter.getType(), ConverterUtil.isAnnotatedAsNotNull(parameter.getModifierList())), ConverterUtil.isReadOnly(parameter, method.getBody()))); } return new ParameterList(result); }
public static boolean isMethodEquivalentTo(@NotNull PsiMethod method1, PsiElement another) { if (method1 == another) return true; if (!(another instanceof PsiMethod)) return false; PsiMethod method2 = (PsiMethod) another; if (!another.isValid()) return false; if (!method1.getName().equals(method2.getName())) return false; PsiClass aClass1 = method1.getContainingClass(); PsiClass aClass2 = method2.getContainingClass(); PsiManager manager = method1.getManager(); if (!(aClass1 != null && aClass2 != null && manager.areElementsEquivalent(aClass1, aClass2))) return false; PsiParameter[] parameters1 = method1.getParameterList().getParameters(); PsiParameter[] parameters2 = method2.getParameterList().getParameters(); if (parameters1.length != parameters2.length) return false; for (int i = 0; i < parameters1.length; i++) { PsiParameter parameter1 = parameters1[i]; PsiParameter parameter2 = parameters2[i]; PsiType type1 = parameter1.getType(); PsiType type2 = parameter2.getType(); if (!compareParamTypes(manager, type1, type2)) return false; } return true; }
private static void fixExceptions(PsiElement ref, PsiClassType[] newExceptions) throws IncorrectOperationException { // methods' throws lists are already modified, may use ExceptionUtil.collectUnhandledExceptions newExceptions = filterCheckedExceptions(newExceptions); PsiElement context = PsiTreeUtil.getParentOfType(ref, PsiTryStatement.class, PsiMethod.class); if (context instanceof PsiTryStatement) { PsiTryStatement tryStatement = (PsiTryStatement) context; PsiCodeBlock tryBlock = tryStatement.getTryBlock(); // Remove unused catches Collection<PsiClassType> classes = ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock); PsiParameter[] catchParameters = tryStatement.getCatchBlockParameters(); for (PsiParameter parameter : catchParameters) { final PsiType caughtType = parameter.getType(); if (!(caughtType instanceof PsiClassType)) continue; if (ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType) caughtType)) continue; if (!isCatchParameterRedundant((PsiClassType) caughtType, classes)) continue; parameter.getParent().delete(); // delete catch section } PsiClassType[] exceptionsToAdd = filterUnhandledExceptions(newExceptions, tryBlock); addExceptions(exceptionsToAdd, tryStatement); adjustPossibleEmptyTryStatement(tryStatement); } else { newExceptions = filterUnhandledExceptions(newExceptions, ref); if (newExceptions.length > 0) { // Add new try statement PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(ref.getProject()); PsiTryStatement tryStatement = (PsiTryStatement) elementFactory.createStatementFromText("try {} catch (Exception e) {}", null); PsiStatement anchor = PsiTreeUtil.getParentOfType(ref, PsiStatement.class); LOG.assertTrue(anchor != null); tryStatement.getTryBlock().add(anchor); tryStatement = (PsiTryStatement) anchor.getParent().addAfter(tryStatement, anchor); addExceptions(newExceptions, tryStatement); anchor.delete(); tryStatement.getCatchSections()[0].delete(); // Delete dummy catch section } } }
private static void checkCall( @NotNull PsiCallExpression methodCall, @NotNull ProblemsHolder holder) { PsiMethod method = methodCall.resolveMethod(); if (method == null) return; PsiParameter[] parameters = method.getParameterList().getParameters(); PsiExpression[] arguments = methodCall.getArgumentList().getExpressions(); for (int i = 0; i < parameters.length; i++) { PsiParameter parameter = parameters[i]; AllowedValues values = getAllowedValues(parameter, parameter.getType(), null); if (values == null) continue; if (i >= arguments.length) break; PsiExpression argument = arguments[i]; argument = PsiUtil.deparenthesizeExpression(argument); if (argument == null) continue; checkMagicParameterArgument(parameter, argument, values, holder); } }
protected boolean findNewParamsPlace( PsiExpression[] expressions, PsiMethod targetMethod, PsiSubstitutor substitutor, StringBuilder buf, HashSet<ParameterInfoImpl> newParams, PsiParameter[] parameters, List<ParameterInfoImpl> result) { // find which parameters to introduce and where Set<String> existingNames = new HashSet<String>(); for (PsiParameter parameter : parameters) { existingNames.add(parameter.getName()); } int ei = 0; int pi = 0; PsiParameter varargParam = targetMethod.isVarArgs() ? parameters[parameters.length - 1] : null; while (ei < expressions.length || pi < parameters.length) { if (buf.length() > 0) buf.append(", "); PsiExpression expression = ei < expressions.length ? expressions[ei] : null; PsiParameter parameter = pi < parameters.length ? parameters[pi] : null; PsiType paramType = parameter == null ? null : substitutor.substitute(parameter.getType()); boolean parameterAssignable = paramType != null && (expression == null || TypeConversionUtil.areTypesAssignmentCompatible(paramType, expression)); if (parameterAssignable) { final PsiType type = parameter.getType(); result.add(new ParameterInfoImpl(pi, parameter.getName(), type)); buf.append(escapePresentableType(type)); pi++; ei++; } else if (isArgumentInVarargPosition(expressions, ei, varargParam, substitutor)) { if (pi == parameters.length - 1) { assert varargParam != null; final PsiType type = varargParam.getType(); result.add(new ParameterInfoImpl(pi, varargParam.getName(), type)); buf.append(escapePresentableType(type)); } pi++; ei++; } else if (expression != null) { if (varargParam != null && pi >= parameters.length) return false; if (PsiPolyExpressionUtil.isPolyExpression(expression)) return false; PsiType exprType = RefactoringUtil.getTypeByExpression(expression); if (exprType == null) return false; if (exprType instanceof PsiDisjunctionType) { exprType = ((PsiDisjunctionType) exprType).getLeastUpperBound(); } JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(expression.getProject()); String name = suggestUniqueParameterName(codeStyleManager, expression, exprType, existingNames); final ParameterInfoImpl newParameterInfo = new ParameterInfoImpl(-1, name, exprType, expression.getText().replace('\n', ' ')); result.add(newParameterInfo); newParams.add(newParameterInfo); buf.append("<b>").append(escapePresentableType(exprType)).append("</b>"); ei++; } } if (result.size() != expressions.length && varargParam == null) return false; return true; }
private ParameterInfoImpl[] getNewParametersInfo( PsiExpression[] expressions, PsiMethod targetMethod, PsiSubstitutor substitutor, final StringBuilder buf, final HashSet<ParameterInfoImpl> newParams, final HashSet<ParameterInfoImpl> removedParams, final HashSet<ParameterInfoImpl> changedParams) { PsiParameter[] parameters = targetMethod.getParameterList().getParameters(); List<ParameterInfoImpl> result = new ArrayList<ParameterInfoImpl>(); if (expressions.length < parameters.length) { // find which parameters to remove int ei = 0; int pi = 0; while (ei < expressions.length && pi < parameters.length) { PsiExpression expression = expressions[ei]; PsiParameter parameter = parameters[pi]; PsiType paramType = substitutor.substitute(parameter.getType()); if (buf.length() > 0) buf.append(", "); final PsiType parameterType = PsiUtil.convertAnonymousToBaseType(paramType); final String presentableText = escapePresentableType(parameterType); final ParameterInfoImpl parameterInfo = new ParameterInfoImpl(pi, parameter.getName(), parameter.getType()); if (TypeConversionUtil.areTypesAssignmentCompatible(paramType, expression)) { buf.append(presentableText); result.add(parameterInfo); pi++; ei++; } else { buf.append("<s>").append(presentableText).append("</s>"); removedParams.add(parameterInfo); pi++; } } if (result.size() != expressions.length) return null; for (int i = pi; i < parameters.length; i++) { if (buf.length() > 0) buf.append(", "); buf.append("<s>").append(escapePresentableType(parameters[i].getType())).append("</s>"); final ParameterInfoImpl parameterInfo = new ParameterInfoImpl(pi, parameters[i].getName(), parameters[i].getType()); removedParams.add(parameterInfo); } } else if (expressions.length > parameters.length) { if (!findNewParamsPlace( expressions, targetMethod, substitutor, buf, newParams, parameters, result)) return null; } else { // parameter type changed for (int i = 0; i < parameters.length; i++) { if (buf.length() > 0) buf.append(", "); PsiParameter parameter = parameters[i]; PsiExpression expression = expressions[i]; PsiType paramType = substitutor.substitute(parameter.getType()); final String presentableText = escapePresentableType(paramType); if (TypeConversionUtil.areTypesAssignmentCompatible(paramType, expression)) { result.add(new ParameterInfoImpl(i, parameter.getName(), paramType)); buf.append(presentableText); } else { if (PsiPolyExpressionUtil.isPolyExpression(expression)) return null; PsiType exprType = RefactoringUtil.getTypeByExpression(expression); if (exprType == null) return null; if (exprType instanceof PsiDisjunctionType) { exprType = ((PsiDisjunctionType) exprType).getLeastUpperBound(); } final ParameterInfoImpl changedParameterInfo = new ParameterInfoImpl(i, parameter.getName(), exprType); result.add(changedParameterInfo); changedParams.add(changedParameterInfo); buf.append("<s>") .append(presentableText) .append("</s> <b>") .append(escapePresentableType(exprType)) .append("</b>"); } } // do not perform silly refactorings boolean isSilly = true; for (int i = 0; i < result.size(); i++) { PsiParameter parameter = parameters[i]; PsiType paramType = substitutor.substitute(parameter.getType()); ParameterInfoImpl parameterInfo = result.get(i); String typeText = parameterInfo.getTypeText(); if (!paramType.equalsToText(typeText) && !paramType.getPresentableText().equals(typeText)) { isSilly = false; break; } } if (isSilly) return null; } return result.toArray(new ParameterInfoImpl[result.size()]); }
public static boolean isFreeFromTypeInferenceArgs( final PsiParameter[] methodParameters, final PsiLambdaExpression lambdaExpression, final PsiExpression expression, final PsiSubstitutor subst, final PsiType functionalInterfaceType, final PsiTypeParameter typeParam) { if (expression instanceof PsiCallExpression && ((PsiCallExpression) expression).getTypeArguments().length > 0) return true; if (expression instanceof PsiNewExpression) { final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression) expression).getClassOrAnonymousClassReference(); if (classReference != null) { final PsiReferenceParameterList parameterList = classReference.getParameterList(); if (parameterList != null) { final PsiTypeElement[] typeParameterElements = parameterList.getTypeParameterElements(); if (typeParameterElements.length > 0) { if (!(typeParameterElements[0].getType() instanceof PsiDiamondType)) { return true; } } } } } final PsiParameter[] lambdaParams = lambdaExpression.getParameterList().getParameters(); if (lambdaParams.length != methodParameters.length) return false; final boolean[] independent = {true}; final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(functionalInterfaceType); if (interfaceMethod == null) return false; final TypeParamsChecker paramsChecker = new TypeParamsChecker(lambdaExpression); for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) { subst.substitute(parameter.getType()).accept(paramsChecker); } paramsChecker.myUsedTypeParams.add(typeParam); expression.accept( new JavaRecursiveElementWalkingVisitor() { @Override public void visitConditionalExpression(PsiConditionalExpression expression) { final PsiExpression thenExpression = expression.getThenExpression(); if (thenExpression != null) { thenExpression.accept(this); } final PsiExpression elseExpression = expression.getElseExpression(); if (elseExpression != null) { elseExpression.accept(this); } } @Override public void visitReferenceExpression(PsiReferenceExpression expression) { super.visitReferenceExpression(expression); int usedParamIdx = -1; for (int i = 0; i < lambdaParams.length; i++) { PsiParameter param = lambdaParams[i]; if (expression.isReferenceTo(param)) { usedParamIdx = i; break; } } if (usedParamIdx > -1 && dependsOnTypeParams( subst.substitute(methodParameters[usedParamIdx].getType()), functionalInterfaceType, lambdaExpression, paramsChecker.myUsedTypeParams.toArray( new PsiTypeParameter[paramsChecker.myUsedTypeParams.size()]))) { independent[0] = false; } } }); return independent[0]; }
private static PsiMethod generateDelegateMethod( PsiMethod method, PsiClass superClass, PsiSubstitutor substitutor, boolean keepParameterAnnotations) { final LightMethodBuilder builder = new LightMethodBuilder( superClass.getManager(), GroovyFileType.GROOVY_LANGUAGE, method.getName()); builder.setContainingClass(superClass); builder.setMethodReturnType(substitutor.substitute(method.getReturnType())); builder.setNavigationElement(method); builder.addModifier(PsiModifier.PUBLIC); final PsiTypeParameter[] typeParameters = method.getTypeParameters(); final PsiClass containingClass = method.getContainingClass(); boolean isRaw = containingClass != null && PsiUtil.isRawSubstitutor(containingClass, substitutor); if (isRaw) { substitutor = JavaPsiFacade.getInstance(method.getProject()) .getElementFactory() .createRawSubstitutor(substitutor, typeParameters); } if (!isRaw) { for (PsiTypeParameter typeParameter : typeParameters) { builder.addTypeParameter(typeParameter); } } final PsiParameter[] originalParameters = method.getParameterList().getParameters(); for (int i = 0; i < originalParameters.length; i++) { PsiParameter originalParameter = originalParameters[i]; PsiType type; if (isRaw) { type = TypeConversionUtil.erasure(substitutor.substitute(originalParameter.getType())); } else { type = substitutor.substitute(originalParameter.getType()); } if (type == null) { type = PsiType.getJavaLangObject(superClass.getManager(), superClass.getResolveScope()); } final LightParameter lightParameter = new LightParameter( StringUtil.notNullize(originalParameter.getName(), "p" + i), type, builder, JavaLanguage.INSTANCE); if (keepParameterAnnotations) { final PsiCompositeModifierList delegatingModifierList = new PsiCompositeModifierList( method.getManager(), Collections.singletonList(originalParameter.getModifierList())); lightParameter.setModifierList(delegatingModifierList); } builder.addParameter(lightParameter); } builder.setBaseIcon(JetgroovyIcons.Groovy.Method); return new DelegatedMethod(builder, method); }