private List<PsiType> matchingTypeParameters(
      PsiType[] paramVals, PsiTypeParameter[] params, ExpectedTypeInfo info) {
    PsiType type = info.getType();
    int kind = info.getKind();

    List<PsiType> result = new ArrayList<>();
    for (int i = 0; i < paramVals.length; i++) {
      PsiType val = paramVals[i];
      if (val != null) {
        switch (kind) {
          case ExpectedTypeInfo.TYPE_STRICTLY:
            if (val.equals(type)) result.add(myFactory.createType(params[i]));
            break;
          case ExpectedTypeInfo.TYPE_OR_SUBTYPE:
            if (type.isAssignableFrom(val)) result.add(myFactory.createType(params[i]));
            break;
          case ExpectedTypeInfo.TYPE_OR_SUPERTYPE:
            if (val.isAssignableFrom(type)) result.add(myFactory.createType(params[i]));
            break;
        }
      }
    }

    return result;
  }
 @Override
 public void visitNewExpression(@NotNull PsiNewExpression expression) {
   if (!PsiUtil.isLanguageLevel5OrHigher(expression)) {
     return;
   }
   super.visitNewExpression(expression);
   final PsiType type = expression.getType();
   if (type == null) {
     return;
   }
   final String canonicalText = type.getCanonicalText();
   if (!cachedNumberTypes.contains(canonicalText)) {
     return;
   }
   final PsiClass aClass = ClassUtils.getContainingClass(expression);
   if (aClass != null && cachedNumberTypes.contains(aClass.getQualifiedName())) {
     return;
   }
   final PsiExpressionList argumentList = expression.getArgumentList();
   if (argumentList == null) {
     return;
   }
   final PsiExpression[] arguments = argumentList.getExpressions();
   if (arguments.length != 1) {
     return;
   }
   final PsiExpression argument = arguments[0];
   final PsiType argumentType = argument.getType();
   if (argumentType == null || argumentType.equalsToText("java.lang.String")) {
     return;
   }
   registerError(expression, expression);
 }
 private void checkExpression(PsiExpression expression) {
   if (expression.getParent() instanceof PsiParenthesizedExpression) {
     return;
   }
   final PsiType expressionType = expression.getType();
   if (expressionType == null) {
     return;
   }
   if (expressionType.getArrayDimensions() > 0) {
     // a horrible hack to get around what happens when you pass
     // an array to a vararg expression
     return;
   }
   if (TypeConversionUtil.isPrimitiveAndNotNull(expressionType)) {
     return;
   }
   final PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(expressionType);
   if (unboxedType == null) {
     return;
   }
   final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, false);
   if (expectedType == null) {
     return;
   }
   if (!TypeConversionUtil.isPrimitiveAndNotNull(expectedType)) {
     return;
   }
   if (!expectedType.isAssignableFrom(unboxedType)) {
     return;
   }
   registerError(expression, expression);
 }
예제 #4
0
  @NotNull
  private String createConversionForExpression(
      @Nullable PsiExpression expression, @NotNull PsiType expectedType) {
    String conversion = "";
    if (expression != null) {
      PsiType actualType = expression.getType();
      boolean isPrimitiveTypeOrNull =
          actualType == null || Node.PRIMITIVE_TYPES.contains(actualType.getCanonicalText());
      boolean isRef =
          (expression instanceof PsiReferenceExpression
                  && ((PsiReferenceExpression) expression).isQualified()
              || expression instanceof PsiMethodCallExpression);
      boolean containsQuestDot = expressionToExpression(expression).toKotlin().contains("?.");

      if (isPrimitiveTypeOrNull && isRef && containsQuestDot) {
        conversion += "!!";
      }

      if (actualType != null) {
        if (isConversionNeeded(actualType, expectedType)) {
          conversion += getPrimitiveTypeConversion(expectedType.getCanonicalText());
        }
      }
    }
    return conversion;
  }
  @Nullable
  private static String formatTypeParameters(
      @NotNull final PsiSubstitutor substitutor, final PsiTypeParameter[] params) {
    final boolean space = showSpaceAfterComma(params[0]);
    StringBuilder buffer = new StringBuilder();
    buffer.append("<");
    for (int i = 0; i < params.length; i++) {
      final PsiTypeParameter param = params[i];
      final PsiType type = substitutor.substitute(param);
      if (type == null) {
        return "";
      }
      if (type instanceof PsiClassType && ((PsiClassType) type).getParameters().length > 0) {
        buffer.append(((PsiClassType) type).rawType().getPresentableText()).append("<...>");
      } else {
        buffer.append(type.getPresentableText());
      }

      if (i < params.length - 1) {
        buffer.append(",");
        if (space) {
          buffer.append(" ");
        }
      }
    }
    buffer.append(">");
    return buffer.toString();
  }
 @Override
 public boolean isValid() {
   for (PsiType conjunct : myConjuncts) {
     if (!conjunct.isValid()) return false;
   }
   return true;
 }
 @Override
 public boolean isValid() {
   for (PsiType type : mySubstitutionMap.values()) {
     if (type != null && !type.isValid()) return false;
   }
   return true;
 }
  private void reportNullableReturns(
      DataFlowInstructionVisitor visitor,
      ProblemsHolder holder,
      Set<PsiElement> reportedAnchors,
      @NotNull PsiElement block) {
    final PsiMethod method = getScopeMethod(block);
    if (method == null || NullableStuffInspectionBase.isNullableNotInferred(method, true)) return;

    boolean notNullRequired = NullableNotNullManager.isNotNull(method);
    if (!notNullRequired && !SUGGEST_NULLABLE_ANNOTATIONS) return;

    PsiType returnType = method.getReturnType();
    // no warnings in void lambdas, where the expression is not returned anyway
    if (block instanceof PsiExpression
        && block.getParent() instanceof PsiLambdaExpression
        && returnType == PsiType.VOID) return;

    // no warnings for Void methods, where only null can be possibly returned
    if (returnType == null || returnType.equalsToText(CommonClassNames.JAVA_LANG_VOID)) return;

    for (PsiElement statement : visitor.getProblems(NullabilityProblem.nullableReturn)) {
      assert statement instanceof PsiExpression;
      final PsiExpression expr = (PsiExpression) statement;
      if (!reportedAnchors.add(expr)) continue;

      if (notNullRequired) {
        final String text =
            isNullLiteralExpression(expr)
                ? InspectionsBundle.message("dataflow.message.return.null.from.notnull")
                : InspectionsBundle.message("dataflow.message.return.nullable.from.notnull");
        holder.registerProblem(expr, text);
      } else if (AnnotationUtil.isAnnotatingApplicable(statement)) {
        final NullableNotNullManager manager =
            NullableNotNullManager.getInstance(expr.getProject());
        final String defaultNullable = manager.getDefaultNullable();
        final String presentableNullable = StringUtil.getShortName(defaultNullable);
        final String text =
            isNullLiteralExpression(expr)
                ? InspectionsBundle.message(
                    "dataflow.message.return.null.from.notnullable", presentableNullable)
                : InspectionsBundle.message(
                    "dataflow.message.return.nullable.from.notnullable", presentableNullable);
        final LocalQuickFix[] fixes =
            PsiTreeUtil.getParentOfType(expr, PsiMethod.class, PsiLambdaExpression.class)
                    instanceof PsiLambdaExpression
                ? LocalQuickFix.EMPTY_ARRAY
                : new LocalQuickFix[] {
                  new AnnotateMethodFix(
                      defaultNullable, ArrayUtil.toStringArray(manager.getNotNulls())) {
                    @Override
                    public int shouldAnnotateBaseMethod(
                        PsiMethod method, PsiMethod superMethod, Project project) {
                      return 1;
                    }
                  }
                };
        holder.registerProblem(expr, text, fixes);
      }
    }
  }
  private static void generateNamesForCollectionType(
      PsiType type, Set<String> possibleNames, NameValidator validator) {
    PsiType componentType = getCollectionComponentType(type, validator.getProject());
    if (!(type instanceof PsiClassType) || componentType == null) return;
    PsiClass clazz = ((PsiClassType) type).resolve();
    if (clazz == null) return;
    String collectionName = clazz.getName();
    assert collectionName != null;

    String componentName = cleanTypeName(componentType.getPresentableText());
    if (componentType instanceof PsiClassType) {
      PsiClassType classType = (PsiClassType) componentType;
      PsiClass psiClass = classType.resolve();
      if (psiClass == null) return;
      componentName = psiClass.getName();
    }

    assert componentName != null;
    String candidateName = StringUtil.pluralize(GroovyNamesUtil.fromLowerLetter(componentName));
    generateCamelNames(possibleNames, validator, candidateName);

    ArrayList<String> camelizedName = GroovyNamesUtil.camelizeString(candidateName);
    candidateName = camelizedName.get(camelizedName.size() - 1);
    candidateName = collectionName.toLowerCase() + "Of" + fromUpperLetter(candidateName);
    possibleNames.add(validator.validateName(candidateName, true));
  }
예제 #10
0
  @Nullable
  private static PsiType doNormalizeWildcardByPosition(
      final PsiType type, final GrExpression expression, final GrExpression toplevel) {
    if (type instanceof PsiCapturedWildcardType) {
      return doNormalizeWildcardByPosition(
          ((PsiCapturedWildcardType) type).getWildcard(), expression, toplevel);
    }

    if (type instanceof PsiWildcardType) {
      final PsiWildcardType wildcardType = (PsiWildcardType) type;

      if (PsiUtil.isAccessedForWriting(toplevel)) {
        return wildcardType.isSuper()
            ? wildcardType.getBound()
            : PsiCapturedWildcardType.create(wildcardType, expression);
      } else {
        if (wildcardType.isExtends()) {
          return wildcardType.getBound();
        } else {
          return PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope());
        }
      }
    } else if (type instanceof PsiArrayType) {
      final PsiType componentType = ((PsiArrayType) type).getComponentType();
      final PsiType normalizedComponentType =
          doNormalizeWildcardByPosition(componentType, expression, toplevel);
      if (normalizedComponentType != componentType) {
        assert normalizedComponentType != null;
        return normalizedComponentType.createArrayType();
      }
    }

    return type;
  }
    @Override
    public void visitBinaryExpression(GrBinaryExpression expression) {
      final IElementType type = expression.getOperationTokenType();
      final GrExpression left = expression.getLeftOperand();
      final GrExpression right = expression.getRightOperand();

      if (type == mREGEX_FIND || type == mREGEX_MATCH) {
        final PsiClassType string =
            TypesUtil.createType(CommonClassNames.JAVA_LANG_STRING, expression);
        myResult = createSimpleSubTypeResult(string);
        return;
      }

      final GrExpression other = myExpression == left ? right : left;
      final PsiType otherType = other != null ? other.getType() : null;

      if (otherType == null) return;

      if (type == mPLUS && otherType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
        final PsiClassType obj = TypesUtil.getJavaLangObject(expression);
        myResult = createSimpleSubTypeResult(obj);
        return;
      }

      myResult = createSimpleSubTypeResult(otherType);
    }
 private static boolean isCatchParameterRedundant(
     PsiClassType catchParamType, Collection<PsiClassType> thrownTypes) {
   for (PsiType exceptionType : thrownTypes) {
     if (exceptionType.isConvertibleFrom(catchParamType)) return false;
   }
   return true;
 }
 @Override
 protected String buildErrorString(Object... args) {
   PsiType ltype = (PsiType) args[0];
   PsiType rtype = (PsiType) args[1];
   return GroovyInspectionBundle.message(
       "rtype.cannot.contain.ltype", ltype.getPresentableText(), rtype.getPresentableText());
 }
  @Override
  protected void addCompletions(
      @NotNull final CompletionParameters parameters,
      final ProcessingContext processingContext,
      @NotNull final CompletionResultSet resultSet) {
    final PsiElement context = parameters.getPosition();

    final Pair<PsiClass, Integer> pair = getTypeParameterInfo(context);
    if (pair == null) return;

    PsiExpression expression = PsiTreeUtil.getContextOfType(context, PsiExpression.class, true);
    if (expression != null) {
      ExpectedTypeInfo[] types =
          ExpectedTypesProvider.getExpectedTypes(expression, true, false, false);
      if (types.length > 0) {
        for (ExpectedTypeInfo info : types) {
          PsiType type = info.getType();
          if (type instanceof PsiClassType && !type.equals(expression.getType())) {
            fillExpectedTypeArgs(
                resultSet,
                context,
                pair.first,
                pair.second,
                ((PsiClassType) type).resolveGenerics(),
                mySmart ? info.getTailType() : TailType.NONE);
          }
        }
        return;
      }
    }

    if (mySmart) {
      addInheritors(parameters, resultSet, pair.first, pair.second);
    }
  }
 @Override
 @NotNull
 protected String buildErrorString(Object... infos) {
   final PsiType expectedType = (PsiType) infos[0];
   final String typeText = expectedType.getPresentableText();
   return InspectionGadgetsBundle.message("overly.strong.type.cast.problem.descriptor", typeText);
 }
  private static Map<String, PsiType> getCompatibleTypeNames(
      @NotNull PsiType type, @Nullable PsiType min, PsiManager manager, GlobalSearchScope scope) {
    if (type instanceof PsiDisjunctionType) type = ((PsiDisjunctionType) type).getLeastUpperBound();

    // if initial type is not assignable to min type we don't take into consideration min type.
    if (min != null && !TypesUtil.isAssignable(min, type, manager, scope)) {
      min = null;
    }

    Map<String, PsiType> map = new LinkedHashMap<String, PsiType>();
    final PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(type);
    if (unboxed != null) type = unboxed;
    final Set<PsiType> set = new LinkedHashSet<PsiType>();
    set.add(type);
    while (!set.isEmpty()) {
      PsiType cur = set.iterator().next();
      set.remove(cur);
      if (!map.containsValue(cur)
          && (min == null || TypesUtil.isAssignable(min, cur, manager, scope))) {
        if (isPartiallySubstituted(cur)) {
          LOG.assertTrue(cur instanceof PsiClassType);
          PsiClassType rawType = ((PsiClassType) cur).rawType();
          map.put(rawType.getPresentableText(), rawType);
        } else {
          map.put(cur.getPresentableText(), cur);
        }
        for (PsiType superType : cur.getSuperTypes()) {
          if (!map.containsValue(superType)) {
            set.add(superType);
          }
        }
      }
    }
    return map;
  }
 @Override
 @NotNull
 public String buildErrorString(Object... infos) {
   final PsiType type = (PsiType) infos[0];
   final String typeName = type.getPresentableText();
   return InspectionGadgetsBundle.message("stringbuffer.field.problem.descriptor", typeName);
 }
  @Nullable
  private static String getTypeText(GrVariable var) {
    final PsiType type = var.getTypeGroovy();
    if (type == null) return null;

    return type.getCanonicalText();
  }
예제 #19
0
        @Override
        public PsiType fun(GrMethodBaseImpl method) {
          PsiType nominal = method.getNominalType();
          if (nominal != null) {
            if (!(nominal instanceof PsiClassType
                && hasTypeParametersToInfer((PsiClassType) nominal))) {
              return nominal;
            }
          }

          if (!GppTypeConverter.hasTypedContext(method)) {
            LOG.assertTrue(method.isValid(), "invalid method");

            final GrOpenBlock block = method.getBlock();
            if (block != null) {
              LOG.assertTrue(block.isValid(), "invalid code block");
              PsiType inferred =
                  GroovyPsiManager.inferType(method, new MethodTypeInferencer(block));
              if (inferred != null) {
                if (nominal == null || nominal.isAssignableFrom(inferred)) {
                  return inferred;
                }
              }
            }
          }
          if (nominal != null) {
            return nominal;
          }

          return TypesUtil.getJavaLangObject(method);
        }
예제 #20
0
 @Nullable
 @Override
 public Boolean visitWildcardType(PsiWildcardType wildcardType) {
   final PsiType bound = wildcardType.getBound();
   if (bound != null) return bound.accept(this);
   return false;
 }
  public static boolean haveConstructorsGenericsParameters(@NotNull final PsiClass psiClass) {
    for (PsiMethod method : psiClass.getConstructors()) {
      for (PsiParameter parameter : method.getParameterList().getParameters()) {
        final PsiType type = parameter.getType();
        final Boolean accept =
            type.accept(
                new PsiTypeVisitor<Boolean>() {
                  @Override
                  public Boolean visitArrayType(PsiArrayType arrayType) {
                    return arrayType.getComponentType().accept(this);
                  }

                  @Override
                  public Boolean visitClassType(PsiClassType classType) {
                    for (PsiType psiType : classType.getParameters()) {
                      if (psiType != null) {
                        final Boolean typaParamFound = psiType.accept(this);
                        if (typaParamFound != null && typaParamFound) return true;
                      }
                    }
                    return PsiUtil.resolveClassInType(classType) instanceof PsiTypeParameter;
                  }

                  @Override
                  public Boolean visitWildcardType(PsiWildcardType wildcardType) {
                    final PsiType bound = wildcardType.getBound();
                    if (bound == null) return false;
                    return bound.accept(this);
                  }
                });
        if (accept != null && accept.booleanValue()) return true;
      }
    }
    return false;
  }
  public String calcGenerics(@NotNull PsiElement context, InsertionContext insertionContext) {
    if (insertionContext.getCompletionChar() == '<') {
      return "";
    }

    assert context.isValid();
    if (myDiamond) {
      return "<>";
    }

    if (getObject() instanceof PsiClass) {
      PsiClass psiClass = (PsiClass) getObject();
      PsiResolveHelper resolveHelper =
          JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper();
      PsiSubstitutor substitutor = getSubstitutor();
      StringBuilder builder = new StringBuilder();
      for (PsiTypeParameter parameter : psiClass.getTypeParameters()) {
        PsiType substitute = substitutor.substitute(parameter);
        if (substitute == null
            || (PsiUtil.resolveClassInType(substitute) == parameter
                && resolveHelper.resolveReferencedClass(parameter.getName(), context)
                    != CompletionUtil.getOriginalOrSelf(parameter))) {
          return "";
        }
        if (builder.length() > 0) {
          builder.append(", ");
        }
        builder.append(substitute.getCanonicalText());
      }
      if (builder.length() > 0) {
        return "<" + builder + ">";
      }
    }
    return "";
  }
예제 #23
0
 @Nullable
 private static String getTypeName(PsiType type, boolean withIndices) {
   type = type.getDeepComponentType();
   if (type instanceof PsiClassType) {
     final PsiClassType classType = (PsiClassType) type;
     final String className = classType.getClassName();
     if (className != null || !withIndices) return className;
     final PsiClass aClass = classType.resolve();
     return aClass instanceof PsiAnonymousClass
         ? ((PsiAnonymousClass) aClass).getBaseClassType().getClassName()
         : null;
   } else if (type instanceof PsiPrimitiveType) {
     return type.getPresentableText();
   } else if (type instanceof PsiWildcardType) {
     return getTypeName(((PsiWildcardType) type).getExtendsBound(), withIndices);
   } else if (type instanceof PsiIntersectionType) {
     return getTypeName(((PsiIntersectionType) type).getRepresentative(), withIndices);
   } else if (type instanceof PsiCapturedWildcardType) {
     return getTypeName(((PsiCapturedWildcardType) type).getWildcard(), withIndices);
   } else if (type instanceof PsiDisjunctionType) {
     return getTypeName(((PsiDisjunctionType) type).getLeastUpperBound(), withIndices);
   } else {
     return null;
   }
 }
  public static boolean areSignaturesEqualLightweight(
      @NotNull MethodSignature sig1, @NotNull MethodSignature sig2) {
    final boolean isConstructor1 = sig1.isConstructor();
    final boolean isConstructor2 = sig2.isConstructor();
    if (isConstructor1 != isConstructor2) return false;

    if (!isConstructor1
        || !(sig1 instanceof HierarchicalMethodSignature
            || sig2 instanceof HierarchicalMethodSignature)) {
      final String name1 = sig1.getName();
      final String name2 = sig2.getName();
      if (!name1.equals(name2)) return false;
    }

    final PsiType[] parameterTypes1 = sig1.getParameterTypes();
    final PsiType[] parameterTypes2 = sig2.getParameterTypes();
    if (parameterTypes1.length != parameterTypes2.length) return false;

    // optimization: check for really different types in method parameters
    for (int i = 0; i < parameterTypes1.length; i++) {
      final PsiType type1 = parameterTypes1[i];
      final PsiType type2 = parameterTypes2[i];
      if (type1 instanceof PsiPrimitiveType != type2 instanceof PsiPrimitiveType) return false;
      if (type1 instanceof PsiPrimitiveType && !type1.equals(type2)) return false;
    }

    return true;
  }
예제 #25
0
  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;
  }
예제 #26
0
  public static String[] getParameterString(ExtractInfoHelper helper, boolean useCanonicalText) {
    int i = 0;
    ParameterInfo[] infos = helper.getParameterInfos();
    int number = 0;
    for (ParameterInfo info : infos) {
      if (info.passAsParameter()) number++;
    }
    ArrayList<String> params = new ArrayList<String>();
    for (ParameterInfo info : infos) {
      if (info.passAsParameter()) {
        PsiType paramType = info.getType();
        final PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(paramType);
        if (unboxed != null) paramType = unboxed;
        String paramTypeText;

        if (paramType == null || paramType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
          paramTypeText = "";
        } else {
          paramTypeText =
              (useCanonicalText ? paramType.getCanonicalText() : paramType.getPresentableText())
                  + " ";
        }
        params.add(paramTypeText + info.getName() + (i < number - 1 ? ", " : ""));
        i++;
      }
    }
    return ArrayUtil.toStringArray(params);
  }
 @Override
 public PsiType visitEllipsisType(PsiEllipsisType ellipsisType) {
   final PsiType componentType = ellipsisType.getComponentType();
   final PsiType substitutedComponentType = componentType.accept(this);
   if (substitutedComponentType == null) return null;
   if (substitutedComponentType == componentType) return ellipsisType; // optimization
   return new PsiEllipsisType(substitutedComponentType);
 }
 public void testInferWithBounds1() throws Exception {
   PsiReferenceExpression ref = configure();
   JavaResolveResult resolveResult = ref.advancedResolve(false);
   PsiSubstitutor substitutor = resolveResult.getSubstitutor();
   PsiMethod method = (PsiMethod) resolveResult.getElement();
   PsiType type = substitutor.substitute(method.getTypeParameters()[0]);
   assertEquals("java.lang.String", type.getCanonicalText());
 }
 @Override
 public PsiType visitArrayType(PsiArrayType arrayType) {
   final PsiType componentType = arrayType.getComponentType();
   final PsiType substitutedComponentType = componentType.accept(this);
   if (substitutedComponentType == null) return null;
   if (substitutedComponentType == componentType) return arrayType; // optimization
   return new PsiArrayType(substitutedComponentType);
 }
 @Override
 public boolean isValid() {
   Collection<PsiType> substitutorValues = mySubstitutionMap.values();
   for (PsiType type : substitutorValues) {
     if (type != null && !type.isValid()) return false;
   }
   return true;
 }