public static boolean proveArrayTypeDistinct(Project project, PsiArrayType type, PsiType bound) {
    final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
    final GlobalSearchScope searchScope = GlobalSearchScope.allScope(project);
    final Set<PsiClass> possibleClasses = new HashSet<PsiClass>();
    possibleClasses.add(facade.findClass(CommonClassNames.JAVA_IO_SERIALIZABLE, searchScope));
    possibleClasses.add(facade.findClass(CommonClassNames.JAVA_LANG_CLONEABLE, searchScope));
    possibleClasses.add(facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, searchScope));

    if (type.getArrayDimensions() == bound.getArrayDimensions()) {
      final PsiType componentType = type.getComponentType();
      final PsiType boundComponentType = ((PsiArrayType) bound).getComponentType();
      if (boundComponentType instanceof PsiClassType && componentType instanceof PsiClassType) {
        return proveExtendsBoundsDistinct(
            boundComponentType,
            componentType,
            ((PsiClassType) boundComponentType).resolve(),
            ((PsiClassType) componentType).resolve());
      } else {
        return !bound.equals(type);
      }
    } else if (bound.getArrayDimensions() + 1 == type.getArrayDimensions()
        && bound.getDeepComponentType() instanceof PsiClassType) {
      return !possibleClasses.contains(((PsiClassType) bound.getDeepComponentType()).resolve());
    } else if (bound.getArrayDimensions() == type.getArrayDimensions() + 1
        && type.getDeepComponentType() instanceof PsiClassType) {
      return !possibleClasses.contains(((PsiClassType) type.getDeepComponentType()).resolve());
    } else if (bound instanceof PsiClassType) {
      return !possibleClasses.contains(((PsiClassType) bound).resolve());
    } else if (bound instanceof PsiWildcardType) {
      final PsiType boundBound = ((PsiWildcardType) bound).getBound();
      return boundBound != null && !boundBound.equals(type);
    }
    return true;
  }
Exemple #2
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;
   }
 }
Exemple #3
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;
  }
  @Nullable
  private static PsiClassType getComponentType(PsiType type) {
    type = type.getDeepComponentType();
    if (type instanceof PsiClassType) return (PsiClassType) type;

    return null;
  }
  @Nullable
  public static HighlightInfo checkMissingReturnStatement(PsiCodeBlock body, PsiType returnType) {
    if (body == null
        || returnType == null
        || PsiType.VOID.equals(returnType.getDeepComponentType())) {
      return null;
    }

    // do not compute constant expressions for if() statement condition
    // see JLS 14.20 Unreachable Statements
    try {
      ControlFlow controlFlow = getControlFlowNoConstantEvaluate(body);
      if (!ControlFlowUtil.returnPresent(controlFlow)) {
        PsiJavaToken rBrace = body.getRBrace();
        PsiElement context = rBrace == null ? body.getLastChild() : rBrace;
        String message = JavaErrorMessages.message("missing.return.statement");
        HighlightInfo info =
            HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
                .range(context)
                .descriptionAndTooltip(message)
                .create();
        PsiElement parent = body.getParent();
        if (parent instanceof PsiMethod) {
          PsiMethod method = (PsiMethod) parent;
          QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createAddReturnFix(method));
          QuickFixAction.registerQuickFixAction(
              info, QUICK_FIX_FACTORY.createMethodReturnFix(method, PsiType.VOID, true));
        }
        return info;
      }
    } catch (AnalysisCanceledException ignored) {
    }

    return null;
  }
  @Override
  public String handleEmptyLookup(
      @NotNull final CompletionParameters parameters, final Editor editor) {
    if (!(parameters.getOriginalFile() instanceof PsiJavaFile)) return null;

    final String ad = advertise(parameters);
    final String suffix = ad == null ? "" : "; " + StringUtil.decapitalize(ad);
    if (parameters.getCompletionType() == CompletionType.SMART) {
      if (!ApplicationManager.getApplication().isUnitTestMode()) {

        final Project project = parameters.getPosition().getProject();
        final PsiFile file = parameters.getOriginalFile();

        PsiExpression expression =
            PsiTreeUtil.getContextOfType(parameters.getPosition(), PsiExpression.class, true);
        if (expression != null && expression.getParent() instanceof PsiExpressionList) {
          int lbraceOffset = expression.getParent().getTextRange().getStartOffset();
          ShowParameterInfoHandler.invoke(project, editor, file, lbraceOffset, null);
        }

        if (expression instanceof PsiLiteralExpression) {
          return LangBundle.message("completion.no.suggestions") + suffix;
        }

        if (expression instanceof PsiInstanceOfExpression) {
          final PsiInstanceOfExpression instanceOfExpression = (PsiInstanceOfExpression) expression;
          if (PsiTreeUtil.isAncestor(
              instanceOfExpression.getCheckType(), parameters.getPosition(), false)) {
            return LangBundle.message("completion.no.suggestions") + suffix;
          }
        }
      }

      final Set<PsiType> expectedTypes = JavaCompletionUtil.getExpectedTypes(parameters);
      if (expectedTypes != null) {
        PsiType type = expectedTypes.size() == 1 ? expectedTypes.iterator().next() : null;
        if (type != null) {
          final PsiType deepComponentType = type.getDeepComponentType();
          if (deepComponentType instanceof PsiClassType) {
            if (((PsiClassType) deepComponentType).resolve() != null) {
              return CompletionBundle.message(
                      "completion.no.suggestions.of.type", type.getPresentableText())
                  + suffix;
            }
            return CompletionBundle.message("completion.unknown.type", type.getPresentableText())
                + suffix;
          }
          if (!PsiType.NULL.equals(type)) {
            return CompletionBundle.message(
                    "completion.no.suggestions.of.type", type.getPresentableText())
                + suffix;
          }
        }
      }
    }
    return LangBundle.message("completion.no.suggestions") + suffix;
  }
 @Override
 public void visitForStatement(@NotNull PsiForStatement statement) {
   super.visitForStatement(statement);
   final PsiStatement initialization = statement.getInitialization();
   if (!(initialization instanceof PsiDeclarationStatement)) {
     return;
   }
   final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization;
   final PsiElement[] declaredElements = declaration.getDeclaredElements();
   if (declaredElements.length != 1) {
     return;
   }
   final PsiElement declaredElement = declaredElements[0];
   if (!(declaredElement instanceof PsiLocalVariable)) {
     return;
   }
   final PsiLocalVariable variable = (PsiLocalVariable) declaredElement;
   final PsiExpression initialValue = variable.getInitializer();
   if (initialValue == null) {
     return;
   }
   final PsiExpression condition = statement.getCondition();
   if (!ExpressionUtils.isVariableLessThanComparison(condition, variable)) {
     return;
   }
   final PsiStatement update = statement.getUpdate();
   if (!VariableAccessUtils.variableIsIncremented(variable, update)) {
     return;
   }
   final PsiArrayAccessExpression arrayAccessExpression = getArrayAccessExpression(statement);
   if (arrayAccessExpression == null) {
     return;
   }
   final PsiExpression arrayExpression = arrayAccessExpression.getArrayExpression();
   final PsiType type = arrayExpression.getType();
   if (!(type instanceof PsiArrayType)
       || type.getDeepComponentType() instanceof PsiPrimitiveType) {
     return;
   }
   final PsiStatement body = statement.getBody();
   if (!bodyIsArrayToCollectionCopy(body, variable, true)) {
     return;
   }
   registerStatementError(statement);
 }
  @Override
  public void addTypeReference(PsiElement psiElement, PsiType psiType, RefManager refManager) {
    RefClass ownerClass = getOwnerClass(refManager, psiElement);

    if (ownerClass != null) {
      psiType = psiType.getDeepComponentType();

      if (psiType instanceof PsiClassType) {
        PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
        if (psiClass != null && refManager.belongsToScope(psiClass)) {
          RefClassImpl refClass = (RefClassImpl) refManager.getReference(psiClass);
          if (refClass != null) {
            refClass.addTypeReference(ownerClass);
          }
        }
      }
    }
  }
  private static void generateNamesForArrayType(
      PsiType type, Set<String> possibleNames, NameValidator validator) {
    int arrayDim = type.getArrayDimensions();
    if (arrayDim == 0) return;
    PsiType deepType = type.getDeepComponentType();
    String candidateName = cleanTypeName(deepType.getPresentableText());
    if (deepType instanceof PsiClassType) {
      PsiClass clazz = ((PsiClassType) deepType).resolve();
      if (clazz == null) return;
      candidateName = GroovyNamesUtil.fromLowerLetter(clazz.getName());
    }
    candidateName = StringUtil.pluralize(GroovyNamesUtil.fromLowerLetter(candidateName));
    generateCamelNames(possibleNames, validator, candidateName);

    ArrayList<String> camelizedName = GroovyNamesUtil.camelizeString(candidateName);
    candidateName = camelizedName.get(camelizedName.size() - 1);
    candidateName = "arrayOf" + fromUpperLetter(candidateName);
    possibleNames.add(validator.validateName(candidateName, true));
  }
  private static void changeNewOperatorType(
      PsiNewExpression originalExpression, PsiType toType, final Editor editor)
      throws IncorrectOperationException {
    PsiNewExpression newExpression;
    PsiElementFactory factory =
        JavaPsiFacade.getInstance(originalExpression.getProject()).getElementFactory();
    int caretOffset;
    TextRange selection;
    if (toType instanceof PsiArrayType) {
      final PsiExpression[] originalExpressionArrayDimensions =
          originalExpression.getArrayDimensions();
      caretOffset = 0;
      @NonNls String text = "new " + toType.getDeepComponentType().getCanonicalText() + "[";
      if (originalExpressionArrayDimensions.length > 0) {
        text += originalExpressionArrayDimensions[0].getText();
      } else {
        text += "0";
        caretOffset = -2;
      }
      text += "]";
      for (int i = 1; i < toType.getArrayDimensions(); i++) {
        text += "[";
        String arrayDimension = "";
        if (originalExpressionArrayDimensions.length > i) {
          arrayDimension = originalExpressionArrayDimensions[i].getText();
          text += arrayDimension;
        }
        text += "]";
        if (caretOffset < 0) {
          caretOffset -= arrayDimension.length() + 2;
        }
      }

      newExpression = (PsiNewExpression) factory.createExpressionFromText(text, originalExpression);
      if (caretOffset < 0) {
        selection = new TextRange(caretOffset, caretOffset + 1);
      } else {
        selection = null;
      }
    } else {
      final PsiAnonymousClass anonymousClass = originalExpression.getAnonymousClass();
      newExpression =
          (PsiNewExpression)
              factory.createExpressionFromText(
                  "new " + toType.getCanonicalText() + "()" + (anonymousClass != null ? "{}" : ""),
                  originalExpression);
      PsiExpressionList argumentList = originalExpression.getArgumentList();
      if (argumentList == null) return;
      newExpression.getArgumentList().replace(argumentList);
      if (anonymousClass == null) { // just to prevent useless inference
        if (PsiDiamondTypeUtil.canCollapseToDiamond(newExpression, originalExpression, toType)) {
          final PsiElement paramList =
              PsiDiamondTypeUtil.replaceExplicitWithDiamond(
                  newExpression.getClassOrAnonymousClassReference().getParameterList());
          newExpression = PsiTreeUtil.getParentOfType(paramList, PsiNewExpression.class);
        }
      }

      if (anonymousClass != null) {
        final PsiAnonymousClass newAnonymousClass =
            (PsiAnonymousClass) newExpression.getAnonymousClass().replace(anonymousClass);
        final PsiClass aClass = PsiUtil.resolveClassInType(toType);
        assert aClass != null;
        newAnonymousClass
            .getBaseClassReference()
            .replace(factory.createClassReferenceElement(aClass));
      }
      selection = null;
      caretOffset = -1;
    }
    PsiElement element = originalExpression.replace(newExpression);
    editor.getCaretModel().moveToOffset(element.getTextRange().getEndOffset() + caretOffset);
    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
    if (selection != null) {
      selection = selection.shiftRight(element.getTextRange().getEndOffset());
      editor.getSelectionModel().setSelection(selection.getStartOffset(), selection.getEndOffset());
    }
  }
  public static void processSubTypes(
      PsiType psiType,
      final PsiElement context,
      boolean getRawSubtypes,
      @NotNull final PrefixMatcher matcher,
      Consumer<PsiType> consumer) {
    int arrayDim = psiType.getArrayDimensions();

    psiType = psiType.getDeepComponentType();
    if (!(psiType instanceof PsiClassType)) return;

    final Condition<String> shortNameCondition =
        new Condition<String>() {
          @Override
          public boolean value(String s) {
            return matcher.prefixMatches(s);
          }
        };

    final PsiClassType baseType = (PsiClassType) psiType;
    final PsiClassType.ClassResolveResult baseResult =
        ApplicationManager.getApplication()
            .runReadAction(
                new Computable<PsiClassType.ClassResolveResult>() {
                  @Override
                  public PsiClassType.ClassResolveResult compute() {
                    return JavaCompletionUtil.originalize(baseType).resolveGenerics();
                  }
                });
    final PsiClass baseClass = baseResult.getElement();
    final PsiSubstitutor baseSubstitutor = baseResult.getSubstitutor();
    if (baseClass == null) return;

    final GlobalSearchScope scope =
        ApplicationManager.getApplication()
            .runReadAction(
                new Computable<GlobalSearchScope>() {
                  @Override
                  public GlobalSearchScope compute() {
                    return context.getResolveScope();
                  }
                });

    final Processor<PsiClass> inheritorsProcessor =
        createInheritorsProcessor(
            context, baseType, arrayDim, getRawSubtypes, consumer, baseClass, baseSubstitutor);
    if (matcher.getPrefix().length() > 2) {
      AllClassesGetter.processJavaClasses(
          matcher,
          context.getProject(),
          scope,
          new Processor<PsiClass>() {
            @Override
            public boolean process(PsiClass psiClass) {
              if (psiClass.isInheritor(baseClass, true)) {
                return inheritorsProcessor.process(psiClass);
              }
              return true;
            }
          });
    } else {
      final Query<PsiClass> baseQuery =
          ClassInheritorsSearch.search(
              new ClassInheritorsSearch.SearchParameters(
                  baseClass, scope, true, false, false, shortNameCondition));
      final Query<PsiClass> query =
          new FilteredQuery<PsiClass>(
              baseQuery,
              new Condition<PsiClass>() {
                @Override
                public boolean value(final PsiClass psiClass) {
                  return !(psiClass instanceof PsiTypeParameter);
                }
              });
      query.forEach(inheritorsProcessor);
    }
  }
  @Nullable
  public static PsiType getVariableTypeByExpressionType(
      @Nullable PsiType type, final boolean openCaptured) {
    if (type == null) return null;
    if (type instanceof PsiCapturedWildcardType) {
      type = ((PsiCapturedWildcardType) type).getWildcard();
    }
    PsiType transformed =
        type.accept(
            new PsiTypeVisitor<PsiType>() {
              @Override
              public PsiType visitArrayType(PsiArrayType arrayType) {
                PsiType componentType = arrayType.getComponentType();
                PsiType type = componentType.accept(this);
                if (type == componentType) return arrayType;
                return type.createArrayType();
              }

              @Override
              public PsiType visitType(PsiType type) {
                return type;
              }

              @Override
              public PsiType visitWildcardType(final PsiWildcardType wildcardType) {
                final PsiType bound = wildcardType.getBound();
                PsiManager manager = wildcardType.getManager();
                if (bound != null) {
                  final PsiType acceptedBound = bound.accept(this);
                  if (acceptedBound instanceof PsiWildcardType) {
                    if (((PsiWildcardType) acceptedBound).isExtends() != wildcardType.isExtends())
                      return PsiWildcardType.createUnbounded(manager);
                    return acceptedBound;
                  }
                  if (wildcardType.isExtends()
                      && acceptedBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT))
                    return PsiWildcardType.createUnbounded(manager);
                  if (acceptedBound.equals(bound)) return wildcardType;
                  return wildcardType.isExtends()
                      ? PsiWildcardType.createExtends(manager, acceptedBound)
                      : PsiWildcardType.createSuper(manager, acceptedBound);
                }
                return wildcardType;
              }

              @Override
              public PsiType visitCapturedWildcardType(
                  PsiCapturedWildcardType capturedWildcardType) {
                return openCaptured
                    ? capturedWildcardType.getWildcard().accept(this)
                    : capturedWildcardType;
              }

              @Override
              public PsiType visitClassType(PsiClassType classType) {
                PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
                PsiClass aClass = resolveResult.getElement();
                if (aClass == null) return classType;
                boolean toExtend = false;
                PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
                for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) {
                  PsiType typeArgument = resolveResult.getSubstitutor().substitute(typeParameter);
                  if (typeArgument instanceof PsiCapturedWildcardType) toExtend = true;
                  if (typeArgument instanceof PsiWildcardType
                      && ((PsiWildcardType) typeArgument).getBound()
                          instanceof PsiIntersectionType) {
                    toExtend = true;
                  }
                  PsiType toPut;
                  if (typeArgument == null) {
                    toPut = null;
                  } else {
                    final PsiType accepted = typeArgument.accept(this);
                    if (typeArgument instanceof PsiIntersectionType) {
                      toPut = PsiWildcardType.createExtends(typeParameter.getManager(), accepted);
                    } else {
                      toPut = accepted;
                    }
                  }
                  LOG.assertTrue(toPut == null || toPut.isValid(), toPut);
                  substitutor = substitutor.put(typeParameter, toPut);
                }
                final PsiAnnotation[] applicableAnnotations = classType.getApplicableAnnotations();
                if (substitutor == PsiSubstitutor.EMPTY
                    && !toExtend
                    && applicableAnnotations.length == 0
                    && !(aClass instanceof PsiTypeParameter)) return classType;
                PsiManager manager = aClass.getManager();
                PsiType result =
                    JavaPsiFacade.getInstance(manager.getProject())
                        .getElementFactory()
                        .createType(
                            aClass,
                            substitutor,
                            PsiUtil.getLanguageLevel(aClass),
                            applicableAnnotations);
                if (toExtend) result = PsiWildcardType.createExtends(manager, result);
                return result;
              }
            });

    PsiType componentType = transformed != null ? transformed.getDeepComponentType() : null;
    if (componentType instanceof PsiWildcardType) {
      componentType = ((PsiWildcardType) componentType).getExtendsBound();
      int dims = transformed.getArrayDimensions();
      for (int i = 0; i < dims; i++) componentType = componentType.createArrayType();
      return componentType;
    }

    return transformed;
  }