Exemple #1
0
  @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;
  }
Exemple #2
0
    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);
       }
     }
   }
 }
Exemple #4
0
 @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;
 }
Exemple #7
0
 @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);
  }