private static boolean hasCorrectType(
        @Nullable PsiAnnotationMemberValue value, PsiType expectedType) {
      if (value == null) return false;

      if (expectedType instanceof PsiClassType
          && expectedType.equalsToText(CommonClassNames.JAVA_LANG_CLASS)
          && !(value instanceof PsiClassObjectAccessExpression)) {
        return false;
      }

      if (value instanceof PsiAnnotation) {
        final PsiJavaCodeReferenceElement nameRef =
            ((PsiAnnotation) value).getNameReferenceElement();
        if (nameRef == null) return true;

        if (expectedType instanceof PsiClassType) {
          final PsiClass aClass = ((PsiClassType) expectedType).resolve();
          if (aClass != null && nameRef.isReferenceTo(aClass)) return true;
        }

        if (expectedType instanceof PsiArrayType) {
          final PsiType componentType = ((PsiArrayType) expectedType).getComponentType();
          if (componentType instanceof PsiClassType) {
            final PsiClass aClass = ((PsiClassType) componentType).resolve();
            if (aClass != null && nameRef.isReferenceTo(aClass)) return true;
          }
        }
        return false;
      }
      if (value instanceof PsiArrayInitializerMemberValue) {
        return expectedType instanceof PsiArrayType;
      }
      if (value instanceof PsiExpression) {
        final PsiExpression expression = (PsiExpression) value;
        return expression.getType() != null
                && TypeConversionUtil.areTypesAssignmentCompatible(expectedType, expression)
            || expectedType instanceof PsiArrayType
                && TypeConversionUtil.areTypesAssignmentCompatible(
                    ((PsiArrayType) expectedType).getComponentType(), expression);
      }
      return true;
    }
 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;
 }
  @Nullable
  public static HighlightInfo checkMemberValueType(
      @Nullable PsiAnnotationMemberValue value, PsiType expectedType) {
    if (value == null) return null;

    if (expectedType instanceof PsiClassType
        && expectedType.equalsToText(CommonClassNames.JAVA_LANG_CLASS)) {
      if (!(value instanceof PsiClassObjectAccessExpression)) {
        String description =
            JavaErrorMessages.message("annotation.non.class.literal.attribute.value");
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
            .range(value)
            .descriptionAndTooltip(description)
            .create();
      }
    }

    if (value instanceof PsiAnnotation) {
      PsiJavaCodeReferenceElement nameRef = ((PsiAnnotation) value).getNameReferenceElement();
      if (nameRef == null) return null;

      if (expectedType instanceof PsiClassType) {
        PsiClass aClass = ((PsiClassType) expectedType).resolve();
        if (aClass != null && nameRef.isReferenceTo(aClass)) return null;
      }

      if (expectedType instanceof PsiArrayType) {
        PsiType componentType = ((PsiArrayType) expectedType).getComponentType();
        if (componentType instanceof PsiClassType) {
          PsiClass aClass = ((PsiClassType) componentType).resolve();
          if (aClass != null && nameRef.isReferenceTo(aClass)) return null;
        }
      }

      String description =
          JavaErrorMessages.message(
              "annotation.incompatible.types",
              formatReference(nameRef),
              JavaHighlightUtil.formatType(expectedType));
      return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
          .range(value)
          .descriptionAndTooltip(description)
          .create();
    }
    if (value instanceof PsiArrayInitializerMemberValue) {
      if (expectedType instanceof PsiArrayType) return null;
      String description =
          JavaErrorMessages.message(
              "annotation.illegal.array.initializer", JavaHighlightUtil.formatType(expectedType));
      return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
          .range(value)
          .descriptionAndTooltip(description)
          .create();
    }
    if (value instanceof PsiExpression) {
      PsiExpression expr = (PsiExpression) value;
      PsiType type = expr.getType();
      if (type != null && TypeConversionUtil.areTypesAssignmentCompatible(expectedType, expr)
          || expectedType instanceof PsiArrayType
              && TypeConversionUtil.areTypesAssignmentCompatible(
                  ((PsiArrayType) expectedType).getComponentType(), expr)) {
        return null;
      }

      String description =
          JavaErrorMessages.message(
              "annotation.incompatible.types",
              JavaHighlightUtil.formatType(type),
              JavaHighlightUtil.formatType(expectedType));
      return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
          .range(value)
          .descriptionAndTooltip(description)
          .create();
    }

    LOG.error("Unknown annotation member value: " + value);
    return null;
  }
Пример #4
0
  private NamesByExprInfo suggestVariableNameByExpressionPlace(
      PsiExpression expr, final VariableKind variableKind, boolean correctKeywords) {
    if (expr.getParent() instanceof PsiExpressionList) {
      PsiExpressionList list = (PsiExpressionList) expr.getParent();
      PsiElement listParent = list.getParent();
      PsiSubstitutor subst = PsiSubstitutor.EMPTY;
      PsiMethod method = null;
      if (listParent instanceof PsiMethodCallExpression) {
        final JavaResolveResult resolveResult =
            ((PsiMethodCallExpression) listParent).getMethodExpression().advancedResolve(false);
        method = (PsiMethod) resolveResult.getElement();
        subst = resolveResult.getSubstitutor();
      } else {
        if (listParent instanceof PsiAnonymousClass) {
          listParent = listParent.getParent();
        }
        if (listParent instanceof PsiNewExpression) {
          method = ((PsiNewExpression) listParent).resolveConstructor();
        }
      }

      if (method != null) {
        final PsiElement navElement = method.getNavigationElement();
        if (navElement instanceof PsiMethod) {
          method = (PsiMethod) navElement;
        }
        PsiExpression[] expressions = list.getExpressions();
        int index = -1;
        for (int i = 0; i < expressions.length; i++) {
          if (expressions[i] == expr) {
            index = i;
            break;
          }
        }
        PsiParameter[] parameters = method.getParameterList().getParameters();
        if (index < parameters.length) {
          String name = parameters[index].getName();
          if (name != null
              && TypeConversionUtil.areTypesAssignmentCompatible(
                  subst.substitute(parameters[index].getType()), expr)) {
            name = variableNameToPropertyName(name, VariableKind.PARAMETER);
            String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords);
            if (expressions.length == 1) {
              final String methodName = method.getName();
              String[] words = NameUtil.nameToWords(methodName);
              if (words.length > 0) {
                final String firstWord = words[0];
                if (SET_PREFIX.equals(firstWord)) {
                  final String propertyName = methodName.substring(firstWord.length());
                  final String[] setterNames =
                      getSuggestionsByName(propertyName, variableKind, false, correctKeywords);
                  names = ArrayUtil.mergeArrays(names, setterNames);
                }
              }
            }
            return new NamesByExprInfo(name, names);
          }
        }
      }
    } else if (expr.getParent() instanceof PsiAssignmentExpression
        && variableKind == VariableKind.PARAMETER) {
      final PsiAssignmentExpression assignmentExpression =
          (PsiAssignmentExpression) expr.getParent();
      if (expr == assignmentExpression.getRExpression()) {
        final PsiExpression leftExpression = assignmentExpression.getLExpression();
        if (leftExpression instanceof PsiReferenceExpression
            && ((PsiReferenceExpression) leftExpression).getQualifier() == null) {
          String name = leftExpression.getText();
          if (name != null) {
            final PsiElement resolve = ((PsiReferenceExpression) leftExpression).resolve();
            if (resolve instanceof PsiVariable) {
              name = variableNameToPropertyName(name, getVariableKind((PsiVariable) resolve));
            }
            String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords);
            return new NamesByExprInfo(name, names);
          }
        }
      }
    }

    return new NamesByExprInfo(null, ArrayUtil.EMPTY_STRING_ARRAY);
  }
 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()]);
  }