@Nullable
  public static PsiQualifiedReference getClassReferenceToShorten(
      @NotNull final PsiClass refClass,
      final boolean addImports,
      @NotNull final PsiQualifiedReference reference) {
    PsiClass parentClass = refClass.getContainingClass();
    if (parentClass != null) {
      JavaPsiFacade facade = JavaPsiFacade.getInstance(parentClass.getProject());
      final PsiResolveHelper resolveHelper = facade.getResolveHelper();
      if (resolveHelper.isAccessible(refClass, reference, null)
          && isSafeToShortenReference(reference.getReferenceName(), reference, refClass)) {
        return reference;
      }

      if (!CodeStyleSettingsManager.getSettings(reference.getProject())
          .INSERT_INNER_CLASS_IMPORTS) {
        final PsiElement qualifier = reference.getQualifier();
        if (qualifier instanceof PsiQualifiedReference) {
          return getClassReferenceToShorten(
              parentClass, addImports, (PsiQualifiedReference) qualifier);
        }
        return null;
      }
    }

    if (addImports && !((PsiImportHolder) reference.getContainingFile()).importClass(refClass))
      return null;
    if (!isSafeToShortenReference(reference, refClass)) return null;
    return reference;
  }
 @Nullable
 private static PsiClass findClass(PsiNewExpression newExpression) {
   final PsiJavaCodeReferenceElement classReference =
       newExpression.getClassOrAnonymousClassReference();
   if (classReference != null) {
     final String text = classReference.getReferenceName();
     if (text != null) {
       final Project project = newExpression.getProject();
       final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
       final PsiResolveHelper resolveHelper = facade.getResolveHelper();
       final PsiExpression newExpressionQualifier = newExpression.getQualifier();
       final PsiElement qualifierElement = classReference.getQualifier();
       final String qualifier = qualifierElement != null ? qualifierElement.getText() : "";
       final String qualifiedName = StringUtil.getQualifiedName(qualifier, text);
       if (newExpressionQualifier != null) {
         final PsiClass aClass =
             PsiUtil.resolveClassInClassTypeOnly(newExpressionQualifier.getType());
         if (aClass != null) {
           return aClass.findInnerClassByName(qualifiedName, false);
         }
       }
       return resolveHelper.resolveReferencedClass(qualifiedName, newExpression);
     } else {
       return null;
     }
   }
   return null;
 }
  /* Guesswork
   */
  @Nullable
  private static PsiSubstitutor getInheritorSubstitutorForNewExpression(
      final PsiClass baseClass,
      final PsiClass inheritor,
      final PsiSubstitutor baseSubstitutor,
      final PsiElement context) {
    final Project project = baseClass.getProject();
    JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
    final PsiResolveHelper resolveHelper = facade.getResolveHelper();
    PsiSubstitutor superSubstitutor =
        TypeConversionUtil.getClassSubstitutor(baseClass, inheritor, PsiSubstitutor.EMPTY);
    if (superSubstitutor == null) return null;
    PsiSubstitutor inheritorSubstitutor = PsiSubstitutor.EMPTY;
    for (PsiTypeParameter inheritorParameter : PsiUtil.typeParametersIterable(inheritor)) {
      for (PsiTypeParameter baseParameter : PsiUtil.typeParametersIterable(baseClass)) {
        final PsiType substituted = superSubstitutor.substitute(baseParameter);
        PsiType arg = baseSubstitutor.substitute(baseParameter);
        if (arg instanceof PsiWildcardType) arg = ((PsiWildcardType) arg).getBound();
        PsiType substitution =
            resolveHelper.getSubstitutionForTypeParameter(
                inheritorParameter, substituted, arg, true, PsiUtil.getLanguageLevel(context));
        if (PsiType.NULL.equals(substitution)) continue;
        if (substitution == null) {
          return facade.getElementFactory().createRawSubstitutor(inheritor);
        }
        inheritorSubstitutor = inheritorSubstitutor.put(inheritorParameter, substitution);
        break;
      }
    }

    return inheritorSubstitutor;
  }
  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 "";
  }
Пример #5
0
  private static boolean changeClassTypeArgument(
      PsiMethod myMethod,
      Project project,
      PsiType superReturnType,
      PsiClass superClass,
      Editor editor,
      PsiType returnType) {
    if (superClass == null || !superClass.hasTypeParameters()) return true;
    final PsiClass superReturnTypeClass = PsiUtil.resolveClassInType(superReturnType);
    if (superReturnTypeClass == null
        || !(superReturnTypeClass instanceof PsiTypeParameter
            || superReturnTypeClass.hasTypeParameters())) return true;

    final PsiClass derivedClass = myMethod.getContainingClass();
    if (derivedClass == null) return true;

    final PsiReferenceParameterList referenceParameterList =
        findTypeArgumentsList(superClass, derivedClass);
    if (referenceParameterList == null) return true;

    final PsiElement resolve =
        ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve();
    if (!(resolve instanceof PsiClass)) return true;
    final PsiClass baseClass = (PsiClass) resolve;

    if (returnType instanceof PsiPrimitiveType) {
      returnType = ((PsiPrimitiveType) returnType).getBoxedType(derivedClass);
    }

    final PsiSubstitutor superClassSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, baseClass, PsiSubstitutor.EMPTY);
    final PsiType superReturnTypeInBaseClassType =
        superClassSubstitutor.substitute(superReturnType);
    final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
    final PsiSubstitutor psiSubstitutor =
        resolveHelper.inferTypeArguments(
            PsiTypesUtil.filterUnusedTypeParameters(
                superReturnTypeInBaseClassType, baseClass.getTypeParameters()),
            new PsiType[] {superReturnTypeInBaseClassType},
            new PsiType[] {returnType},
            PsiUtil.getLanguageLevel(superClass));

    final TypeMigrationRules rules = new TypeMigrationRules();
    final PsiSubstitutor compoundSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, derivedClass, PsiSubstitutor.EMPTY)
            .putAll(psiSubstitutor);
    rules.setBoundScope(new LocalSearchScope(derivedClass));
    TypeMigrationProcessor.runHighlightingTypeMigration(
        project,
        editor,
        rules,
        referenceParameterList,
        JavaPsiFacade.getElementFactory(project).createType(baseClass, compoundSubstitutor));

    return false;
  }
  public static boolean variableNameResolvesToTarget(
      @NotNull String variableName, @NotNull PsiVariable target, @NotNull PsiElement context) {

    final Project project = context.getProject();
    final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
    final PsiResolveHelper resolveHelper = psiFacade.getResolveHelper();
    final PsiVariable variable =
        resolveHelper.resolveAccessibleReferencedVariable(variableName, context);
    return target.equals(variable);
  }
 @Nullable
 private static PsiMethod findConstructor(
     PsiClass containingClass, PsiNewExpression newExpression) {
   final PsiExpressionList argumentList = newExpression.getArgumentList();
   final Project project = newExpression.getProject();
   final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
   final PsiResolveHelper resolveHelper = facade.getResolveHelper();
   final JavaResolveResult result =
       resolveHelper.resolveConstructor(
           facade.getElementFactory().createType(containingClass), argumentList, argumentList);
   return (PsiMethod) result.getElement();
 }
 private static boolean isSafeToShortenReference(
     final String referenceText, final PsiElement psiReference, final PsiClass refClass) {
   final PsiManager manager = refClass.getManager();
   final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
   final PsiResolveHelper helper = facade.getResolveHelper();
   if (manager.areElementsEquivalent(
       refClass, helper.resolveReferencedClass(referenceText, psiReference))) {
     PsiElement parent = psiReference.getParent();
     if (parent instanceof PsiJavaCodeReferenceElement
         && parent.getParent() instanceof PsiNewExpression) return true;
     return helper.resolveReferencedVariable(referenceText, psiReference) == null;
   }
   return false;
 }
 private static PsiSubstitutor inferTypeParametersForStaticFactory(
     @NotNull PsiMethod staticFactoryMethod, PsiNewExpression expression, PsiElement parent) {
   final JavaPsiFacade facade = JavaPsiFacade.getInstance(staticFactoryMethod.getProject());
   final PsiResolveHelper resolveHelper = facade.getResolveHelper();
   final PsiParameter[] parameters = staticFactoryMethod.getParameterList().getParameters();
   final PsiExpressionList argumentList = expression.getArgumentList();
   final PsiExpression[] expressions = argumentList.getExpressions();
   return resolveHelper.inferTypeArguments(
       staticFactoryMethod.getTypeParameters(),
       parameters,
       expressions,
       PsiSubstitutor.EMPTY,
       parent,
       DefaultParameterTypeInferencePolicy.INSTANCE);
 }
  private static boolean superConstructorHasParameters(PsiMethod method) {
    final PsiClass psiClass = method.getContainingClass();
    if (psiClass == null) {
      return false;
    }

    final PsiClass superClass = psiClass.getSuperClass();
    if (superClass != null) {
      for (final PsiMethod psiMethod : superClass.getConstructors()) {
        final PsiResolveHelper resolveHelper =
            JavaPsiFacade.getInstance(method.getProject()).getResolveHelper();
        if (resolveHelper.isAccessible(psiMethod, method, null)
            && psiMethod.getParameterList().getParameters().length > 0) {
          return true;
        }
      }
    }
    return false;
  }
 public static boolean containsConflictingDeclarations(
     PsiCodeBlock block, PsiCodeBlock parentBlock) {
   final PsiStatement[] statements = block.getStatements();
   if (statements.length == 0) {
     return false;
   }
   final List<PsiCodeBlock> followingBlocks = new ArrayList<>();
   collectFollowingBlocks(block.getParent().getNextSibling(), followingBlocks);
   final Project project = block.getProject();
   final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
   final PsiResolveHelper resolveHelper = facade.getResolveHelper();
   for (final PsiStatement statement : statements) {
     if (!(statement instanceof PsiDeclarationStatement)) {
       continue;
     }
     final PsiDeclarationStatement declaration = (PsiDeclarationStatement) statement;
     final PsiElement[] variables = declaration.getDeclaredElements();
     for (PsiElement variable : variables) {
       if (!(variable instanceof PsiLocalVariable)) {
         continue;
       }
       final PsiLocalVariable localVariable = (PsiLocalVariable) variable;
       final String variableName = localVariable.getName();
       if (variableName == null) {
         continue;
       }
       final PsiVariable target =
           resolveHelper.resolveAccessibleReferencedVariable(variableName, parentBlock);
       if (target instanceof PsiLocalVariable) {
         return true;
       }
       for (PsiCodeBlock codeBlock : followingBlocks) {
         final PsiVariable target1 =
             resolveHelper.resolveAccessibleReferencedVariable(variableName, codeBlock);
         if (target1 instanceof PsiLocalVariable) {
           return true;
         }
       }
     }
   }
   return false;
 }
  @Nullable
  public EncapsulateFieldUsageInfo createUsage(
      @NotNull EncapsulateFieldsDescriptor descriptor,
      @NotNull FieldDescriptor fieldDescriptor,
      @NotNull PsiReference reference) {
    if (!(reference instanceof PsiReferenceExpression)) return null;

    boolean findSet = descriptor.isToEncapsulateSet();
    boolean findGet = descriptor.isToEncapsulateGet();
    PsiReferenceExpression ref = (PsiReferenceExpression) reference;
    // [Jeka] to avoid recursion in the field's accessors
    if (findGet
        && isUsedInExistingAccessor(
            descriptor.getTargetClass(), fieldDescriptor.getGetterPrototype(), ref)) return null;
    if (findSet
        && isUsedInExistingAccessor(
            descriptor.getTargetClass(), fieldDescriptor.getSetterPrototype(), ref)) return null;
    if (!findGet) {
      if (!PsiUtil.isAccessedForWriting(ref)) return null;
    }
    if (!findSet || fieldDescriptor.getField().hasModifierProperty(PsiModifier.FINAL)) {
      if (!PsiUtil.isAccessedForReading(ref)) return null;
    }
    if (!descriptor.isToUseAccessorsWhenAccessible()) {
      PsiModifierList newModifierList = createNewModifierList(descriptor);

      PsiClass accessObjectClass = null;
      PsiExpression qualifier = ref.getQualifierExpression();
      if (qualifier != null) {
        accessObjectClass = (PsiClass) PsiUtil.getAccessObjectClass(qualifier).getElement();
      }
      final PsiResolveHelper helper =
          JavaPsiFacade.getInstance(((PsiReferenceExpression) reference).getProject())
              .getResolveHelper();
      if (helper.isAccessible(
          fieldDescriptor.getField(), newModifierList, ref, accessObjectClass, null)) {
        return null;
      }
    }
    return new EncapsulateFieldUsageInfo(ref, fieldDescriptor);
  }
Пример #13
0
 @NotNull
 public static PsiSubstitutor inferFromReturnType(
     @NotNull PsiTypeParameter[] typeParameters,
     final PsiType returnType,
     @Nullable final PsiType interfaceMethodReturnType,
     @NotNull PsiSubstitutor psiSubstitutor,
     final LanguageLevel languageLevel,
     final Project project) {
   if (interfaceMethodReturnType == null) return psiSubstitutor;
   final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
   final PsiSubstitutor substitutor =
       resolveHelper.inferTypeArguments(
           typeParameters,
           new PsiType[] {interfaceMethodReturnType},
           new PsiType[] {returnType},
           languageLevel);
   for (PsiTypeParameter typeParameter : typeParameters) {
     final PsiType inferredType = substitutor.substitute(typeParameter);
     if (PsiUtil.resolveClassInType(inferredType) != typeParameter) {
       psiSubstitutor = psiSubstitutor.put(typeParameter, inferredType);
     }
   }
   return psiSubstitutor;
 }
 private static PsiSubstitutor getSuperClassSubstitutor(
     final PsiType superClassType,
     final PsiClassType targetClassType,
     final PsiResolveHelper resolveHelper,
     PsiClass targetClass) {
   PsiSubstitutor subst = PsiSubstitutor.EMPTY;
   for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(targetClass)) {
     subst =
         subst.put(
             typeParameter,
             resolveHelper.getSubstitutionForTypeParameter(
                 typeParameter,
                 targetClassType,
                 superClassType,
                 false,
                 PsiUtil.getLanguageLevel(targetClass)));
   }
   return subst;
 }
Пример #15
0
  @Override
  public ASTNode process(
      @NotNull ASTNode element,
      boolean addImports,
      boolean incompleteCode,
      boolean useFqInJavadoc,
      boolean useFqInCode) {
    IElementType elementType = element.getElementType();
    if ((elementType == JavaElementType.JAVA_CODE_REFERENCE
            || elementType == JavaElementType.REFERENCE_EXPRESSION)
        && !isAnnotated(element)) {
      IElementType parentType = element.getTreeParent().getElementType();
      if (elementType == JavaElementType.JAVA_CODE_REFERENCE
          || incompleteCode
          || parentType == JavaElementType.REFERENCE_EXPRESSION
          || parentType == JavaElementType.METHOD_REF_EXPRESSION) {
        PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) element.getPsi();

        PsiReferenceParameterList parameterList = ref.getParameterList();
        if (parameterList != null) {
          PsiTypeElement[] typeParameters = parameterList.getTypeParameterElements();
          for (PsiTypeElement typeParameter : typeParameters) {
            process(
                typeParameter.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode);
          }
        }

        boolean rightKind = true;
        if (elementType == JavaElementType.JAVA_CODE_REFERENCE) {
          PsiJavaCodeReferenceElementImpl impl = (PsiJavaCodeReferenceElementImpl) element;
          int kind = impl.getKind(impl.getContainingFile());
          rightKind =
              kind == PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND
                  || kind == PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND;
        }

        if (rightKind) {
          // annotations may jump out of reference (see PsiJavaCodeReferenceImpl#setAnnotations())
          // so they should be processed first
          List<PsiAnnotation> annotations =
              PsiTreeUtil.getChildrenOfTypeAsList(ref, PsiAnnotation.class);
          for (PsiAnnotation annotation : annotations) {
            process(annotation.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode);
          }

          boolean isInsideDocComment =
              TreeUtil.findParent(element, JavaDocElementType.DOC_COMMENT) != null;
          boolean isShort = !ref.isQualified();
          if (isInsideDocComment ? !useFqInJavadoc : !useFqInCode) {
            if (isShort) return element; // short name already, no need to change
          }

          PsiElement refElement;
          if (!incompleteCode) {
            refElement = ref.resolve();
          } else {
            PsiResolveHelper helper =
                JavaPsiFacade.getInstance(ref.getManager().getProject()).getResolveHelper();
            final SourceJavaCodeReference reference = (SourceJavaCodeReference) element;
            refElement = helper.resolveReferencedClass(reference.getClassNameText(), ref);
          }

          if (refElement instanceof PsiClass) {
            PsiClass psiClass = (PsiClass) refElement;
            if (isInsideDocComment ? useFqInJavadoc : useFqInCode) {
              String qName = psiClass.getQualifiedName();
              if (qName == null) return element;

              PsiFile file = ref.getContainingFile();
              if (file instanceof PsiJavaFile) {
                if (ImportHelper.isImplicitlyImported(qName, (PsiJavaFile) file)) {
                  if (isShort) return element;
                  return makeShortReference((CompositeElement) element, psiClass, addImports);
                }

                String thisPackageName = ((PsiJavaFile) file).getPackageName();
                if (ImportHelper.hasPackage(qName, thisPackageName)) {
                  if (!isShort) {
                    return makeShortReference((CompositeElement) element, psiClass, addImports);
                  }
                }
              }

              return replaceReferenceWithFQ(element, psiClass);
            } else {
              int oldLength = element.getTextLength();
              ASTNode treeElement =
                  makeShortReference((CompositeElement) element, psiClass, addImports);
              if (treeElement.getTextLength() == oldLength
                  && psiClass.getContainingClass() != null) {
                PsiElement qualifier = ref.getQualifier();
                if (qualifier instanceof PsiJavaCodeReferenceElement
                    && ((PsiJavaCodeReferenceElement) qualifier).resolve() instanceof PsiClass) {
                  process(
                      qualifier.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode);
                }
              }
              return treeElement;
            }
          }
        }
      }
    }

    for (ASTNode child = element.getFirstChildNode(); child != null; child = child.getTreeNext()) {
      //noinspection AssignmentToForLoopParameter
      child = process(child, addImports, incompleteCode, useFqInJavadoc, useFqInCode);
    }

    return element;
  }
 @NotNull
 private List<PsiMethod> getMethodsToImport() {
   PsiShortNamesCache cache = PsiShortNamesCache.getInstance(myMethodCall.getProject());
   PsiMethodCallExpression element = myMethodCall.getElement();
   PsiReferenceExpression reference = element.getMethodExpression();
   PsiExpressionList argumentList = element.getArgumentList();
   String name = reference.getReferenceName();
   List<PsiMethod> list = new ArrayList<PsiMethod>();
   if (name == null) return list;
   GlobalSearchScope scope = element.getResolveScope();
   PsiMethod[] methods = cache.getMethodsByNameIfNotMoreThan(name, scope, 20);
   List<PsiMethod> applicableList = new ArrayList<PsiMethod>();
   final PsiResolveHelper resolveHelper =
       JavaPsiFacade.getInstance(element.getProject()).getResolveHelper();
   for (PsiMethod method : methods) {
     ProgressManager.checkCanceled();
     if (JavaCompletionUtil.isInExcludedPackage(method)) continue;
     if (!method.hasModifierProperty(PsiModifier.STATIC)) continue;
     PsiFile file = method.getContainingFile();
     if (file instanceof PsiJavaFile
         // do not show methods from default package
         && ((PsiJavaFile) file).getPackageName().length() != 0
         && PsiUtil.isAccessible(method, element, method.getContainingClass())) {
       list.add(method);
       PsiSubstitutor substitutorForMethod =
           resolveHelper.inferTypeArguments(
               method.getTypeParameters(),
               method.getParameterList().getParameters(),
               argumentList.getExpressions(),
               PsiSubstitutor.EMPTY,
               element.getParent(),
               DefaultParameterTypeInferencePolicy.INSTANCE);
       if (PsiUtil.isApplicable(method, substitutorForMethod, argumentList)) {
         applicableList.add(method);
       }
     }
   }
   List<PsiMethod> result = applicableList.isEmpty() ? list : applicableList;
   for (int i = result.size() - 1; i >= 0; i--) {
     ProgressManager.checkCanceled();
     PsiMethod method = result.get(i);
     PsiClass containingClass = method.getContainingClass();
     for (int j = i + 1; j < result.size(); j++) {
       PsiMethod exMethod = result.get(j);
       if (!Comparing.strEqual(exMethod.getName(), method.getName())) continue;
       PsiClass exContainingClass = exMethod.getContainingClass();
       if (containingClass != null
           && exContainingClass != null
           && !Comparing.equal(
               containingClass.getQualifiedName(), exContainingClass.getQualifiedName())) continue;
       // same named methods, drop one
       result.remove(i);
       break;
     }
     // check for manually excluded
     if (isExcluded(method)) {
       result.remove(i);
     }
   }
   Collections.sort(result, new PsiProximityComparator(argumentList));
   return result;
 }
  public TreeElement process(TreeElement element, boolean addImports, boolean uncompleteCode) {
    IElementType elementType = element.getElementType();
    if (elementType == JavaElementType.JAVA_CODE_REFERENCE
        || elementType == JavaElementType.REFERENCE_EXPRESSION) {
      final IElementType parentElementType = element.getTreeParent().getElementType();
      if (elementType == JavaElementType.JAVA_CODE_REFERENCE
          || parentElementType == JavaElementType.REFERENCE_EXPRESSION
          || parentElementType == JavaElementType.METHOD_REF_EXPRESSION
          || uncompleteCode) {
        final PsiJavaCodeReferenceElement ref =
            (PsiJavaCodeReferenceElement) SourceTreeToPsiMap.treeElementToPsi(element);
        final PsiReferenceParameterList parameterList = ref.getParameterList();
        if (parameterList != null) {
          final PsiTypeElement[] typeParameters = parameterList.getTypeParameterElements();
          for (PsiTypeElement typeParameter : typeParameters) {
            process(
                (TreeElement) SourceTreeToPsiMap.psiElementToTree(typeParameter),
                addImports,
                uncompleteCode);
          }
        }

        boolean rightKind = true;
        if (elementType == JavaElementType.JAVA_CODE_REFERENCE) {
          int kind = ((PsiJavaCodeReferenceElementImpl) element).getKind();
          rightKind =
              kind == PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND
                  || kind == PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND;
        }

        if (rightKind) {
          boolean isInsideDocComment =
              TreeUtil.findParent(element, JavaDocElementType.DOC_COMMENT) != null;
          boolean isShort = !((SourceJavaCodeReference) element).isQualified();
          if (!makeFQ(isInsideDocComment)) {
            if (isShort) return element; // short name already, no need to change
          }
          PsiElement refElement;
          if (!uncompleteCode) {
            refElement = ref.resolve();
          } else {
            PsiResolveHelper helper =
                JavaPsiFacade.getInstance(element.getManager().getProject()).getResolveHelper();
            refElement =
                helper.resolveReferencedClass(
                    ((SourceJavaCodeReference) element).getClassNameText(),
                    SourceTreeToPsiMap.treeElementToPsi(element));
          }
          if (refElement instanceof PsiClass) {
            if (makeFQ(isInsideDocComment)) {
              String qName = ((PsiClass) refElement).getQualifiedName();
              if (qName == null) return element;
              PsiImportHolder file =
                  (PsiImportHolder)
                      SourceTreeToPsiMap.treeElementToPsi(element).getContainingFile();
              if (file instanceof PsiJavaFile
                  && ImportHelper.isImplicitlyImported(qName, (PsiJavaFile) file)) {
                if (isShort) return element;
                return (TreeElement)
                    makeShortReference(
                        (CompositeElement) element, (PsiClass) refElement, addImports);
              }
              if (file instanceof PsiJavaFile) {
                String thisPackageName = ((PsiJavaFile) file).getPackageName();
                if (ImportHelper.hasPackage(qName, thisPackageName)) {
                  if (!isShort) {
                    return (TreeElement)
                        makeShortReference(
                            (CompositeElement) element, (PsiClass) refElement, addImports);
                  }
                }
              }
              return (TreeElement) replaceReferenceWithFQ(element, (PsiClass) refElement);
            } else {
              int oldLength = element.getTextLength();
              TreeElement treeElement =
                  (TreeElement)
                      makeShortReference(
                          (CompositeElement) element, (PsiClass) refElement, addImports);
              if (treeElement.getTextLength() == oldLength
                  && ((PsiClass) refElement).getContainingClass() != null) {
                PsiElement qualifier = ref.getQualifier();
                if (qualifier instanceof PsiJavaCodeReferenceElement
                    && ((PsiJavaCodeReferenceElement) qualifier).resolve() instanceof PsiClass) {
                  process((TreeElement) qualifier.getNode(), addImports, uncompleteCode);
                }
              }
              return treeElement;
            }
          }
        }
      }
    }

    for (TreeElement child = element.getFirstChildNode();
        child != null;
        child = child.getTreeNext()) {
      child = process(child, addImports, uncompleteCode);
    }

    return element;
  }
Пример #18
0
  /**
   * Adds import if it is needed.
   *
   * @return false when the FQ-name have to be used in code (e.g. when conflicting imports already
   *     exist)
   */
  public boolean addImport(@NotNull PsiJavaFile file, @NotNull PsiClass refClass) {
    final JavaPsiFacade facade = JavaPsiFacade.getInstance(file.getProject());
    PsiElementFactory factory = facade.getElementFactory();
    PsiResolveHelper helper = facade.getResolveHelper();

    String className = refClass.getQualifiedName();
    if (className == null) return true;
    String packageName = getPackageOrClassName(className);
    String shortName = PsiNameHelper.getShortClassName(className);

    PsiClass conflictSingleRef = findSingleImportByShortName(file, shortName);
    if (conflictSingleRef != null) {
      return className.equals(conflictSingleRef.getQualifiedName());
    }

    PsiClass curRefClass = helper.resolveReferencedClass(shortName, file);
    if (file.getManager().areElementsEquivalent(refClass, curRefClass)) {
      return true;
    }

    boolean useOnDemand = true;
    if (packageName.length() == 0) {
      useOnDemand = false;
    }

    PsiElement conflictPackageRef = findImportOnDemand(file, packageName);
    if (conflictPackageRef != null) {
      useOnDemand = false;
    }

    List<PsiElement> classesToReimport = new ArrayList<PsiElement>();

    List<PsiJavaCodeReferenceElement> importRefs = getImportsFromPackage(file, packageName);
    if (useOnDemand) {
      if (mySettings.USE_SINGLE_CLASS_IMPORTS
          && importRefs.size() + 1 < mySettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND
          && !mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.contains(packageName)) {
        useOnDemand = false;
      }
      // name of class we try to import is the same as of the class defined in this file
      if (curRefClass != null) {
        useOnDemand = true;
      }
      // check conflicts
      if (useOnDemand) {
        PsiElement[] onDemandRefs = file.getOnDemandImports(false, true);
        if (onDemandRefs.length > 0) {
          PsiPackage aPackage = facade.findPackage(packageName);
          if (aPackage != null) {
            PsiDirectory[] dirs = aPackage.getDirectories();
            for (PsiDirectory dir : dirs) {
              PsiFile[] files = dir.getFiles(); // do not iterate classes - too slow when not loaded
              for (PsiFile aFile : files) {
                if (aFile instanceof PsiJavaFile) {
                  String name = aFile.getVirtualFile().getNameWithoutExtension();
                  for (PsiElement ref : onDemandRefs) {
                    String refName =
                        ref instanceof PsiClass
                            ? ((PsiClass) ref).getQualifiedName()
                            : ((PsiPackage) ref).getQualifiedName();
                    String conflictClassName = refName + "." + name;
                    GlobalSearchScope resolveScope = file.getResolveScope();
                    PsiClass conflictClass = facade.findClass(conflictClassName, resolveScope);
                    if (conflictClass != null && helper.isAccessible(conflictClass, file, null)) {
                      String conflictClassName2 = aPackage.getQualifiedName() + "." + name;
                      PsiClass conflictClass2 = facade.findClass(conflictClassName2, resolveScope);
                      if (conflictClass2 != null
                          && helper.isAccessible(conflictClass2, file, null)) {
                        if (ReferencesSearch.search(
                                    conflictClass, new LocalSearchScope(file), false)
                                .findFirst()
                            != null) {
                          classesToReimport.add(conflictClass);
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

    try {
      PsiImportList importList = file.getImportList();
      PsiImportStatement statement;
      if (useOnDemand) {
        statement = factory.createImportStatementOnDemand(packageName);
      } else {
        statement = factory.createImportStatement(refClass);
      }
      importList.add(statement);
      if (useOnDemand) {
        for (PsiJavaCodeReferenceElement ref : importRefs) {
          LOG.assertTrue(ref.getParent() instanceof PsiImportStatement);
          if (!ref.isValid()) continue; // todo[dsl] Q?
          classesToReimport.add(ref.resolve());
          PsiImportStatement importStatement = (PsiImportStatement) ref.getParent();
          importStatement.delete();
        }
      }

      for (PsiElement aClassesToReimport : classesToReimport) {
        PsiClass aClass = (PsiClass) aClassesToReimport;
        if (aClass != null) {
          addImport(file, aClass);
        }
      }
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
    return true;
  }