Пример #1
0
 public String[] knownNamespaces() {
   final PsiElement parentElement = getParent();
   BidirectionalMap<String, String> map = initNamespaceMaps(parentElement);
   Set<String> known = Collections.emptySet();
   if (map != null) {
     known = new HashSet<String>(map.values());
   }
   if (parentElement instanceof XmlTag) {
     if (known.isEmpty()) return ((XmlTag) parentElement).knownNamespaces();
     ContainerUtil.addAll(known, ((XmlTag) parentElement).knownNamespaces());
   } else {
     XmlExtension xmlExtension = XmlExtension.getExtensionByElement(this);
     if (xmlExtension != null) {
       final XmlFile xmlFile = xmlExtension.getContainingFile(this);
       if (xmlFile != null) {
         final XmlTag rootTag = xmlFile.getRootTag();
         if (rootTag != null && rootTag != this) {
           if (known.isEmpty()) return rootTag.knownNamespaces();
           ContainerUtil.addAll(known, rootTag.knownNamespaces());
         }
       }
     }
   }
   return ArrayUtil.toStringArray(known);
 }
 @NotNull
 private static List<PsiMethod> findMethodsBySignature(
     @NotNull PsiClass aClass,
     @NotNull PsiMethod patternMethod,
     boolean checkBases,
     boolean stopOnFirst) {
   final PsiMethod[] methodsByName = aClass.findMethodsByName(patternMethod.getName(), checkBases);
   if (methodsByName.length == 0) return Collections.emptyList();
   final List<PsiMethod> methods = new SmartList<PsiMethod>();
   final MethodSignature patternSignature = patternMethod.getSignature(PsiSubstitutor.EMPTY);
   for (final PsiMethod method : methodsByName) {
     final PsiClass superClass = method.getContainingClass();
     final PsiSubstitutor substitutor;
     if (checkBases && !aClass.equals(superClass)) {
       substitutor =
           TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY);
     } else {
       substitutor = PsiSubstitutor.EMPTY;
     }
     final MethodSignature signature = method.getSignature(substitutor);
     if (signature.equals(patternSignature)) {
       methods.add(method);
       if (stopOnFirst) {
         break;
       }
     }
   }
   return methods;
 }
 @Nullable
 public static List<? extends PsiElement> getAllPsiElements(final LookupElement item) {
   List<PsiMethod> allMethods = getAllMethods(item);
   if (allMethods != null) return allMethods;
   if (item.getObject() instanceof PsiElement)
     return Collections.singletonList((PsiElement) item.getObject());
   return null;
 }
 @NotNull
 public static List<Pair<PsiMethod, PsiSubstitutor>> findMethodsAndTheirSubstitutorsByName(
     @NotNull PsiClass psiClass, String name, boolean checkBases) {
   if (!checkBases) {
     final PsiMethod[] methodsByName = psiClass.findMethodsByName(name, false);
     final List<Pair<PsiMethod, PsiSubstitutor>> ret =
         new ArrayList<Pair<PsiMethod, PsiSubstitutor>>(methodsByName.length);
     for (final PsiMethod method : methodsByName) {
       ret.add(new Pair<PsiMethod, PsiSubstitutor>(method, PsiSubstitutor.EMPTY));
     }
     return ret;
   }
   Map<String, List<Pair<PsiMember, PsiSubstitutor>>> map = getMap(psiClass, MemberType.METHOD);
   @SuppressWarnings("unchecked")
   List<Pair<PsiMethod, PsiSubstitutor>> list = (List) map.get(name);
   return list == null
       ? Collections.<Pair<PsiMethod, PsiSubstitutor>>emptyList()
       : Collections.unmodifiableList(list);
 }
 @Nullable
 private PyType createCoroutineType(@Nullable PyType returnType) {
   final PyBuiltinCache cache = PyBuiltinCache.getInstance(this);
   if (returnType instanceof PyClassLikeType
       && PyNames.FAKE_COROUTINE.equals(((PyClassLikeType) returnType).getClassQName())) {
     return returnType;
   }
   final PyClass generator = cache.getClass(PyNames.FAKE_COROUTINE);
   return generator != null
       ? new PyCollectionTypeImpl(generator, false, Collections.singletonList(returnType))
       : null;
 }
  @Override
  public List<RefEntity> getChildren() {
    List<RefEntity> superChildren = super.getChildren();
    if (myParameters == null) return superChildren;
    if (superChildren == null || superChildren.isEmpty())
      return Arrays.<RefEntity>asList(myParameters);

    List<RefEntity> allChildren =
        new ArrayList<RefEntity>(superChildren.size() + myParameters.length);
    allChildren.addAll(superChildren);
    Collections.addAll(allChildren, myParameters);
    return allChildren;
  }
  private static List<? extends LookupElement> createLookupElements(
      CompletionElement completionElement, PsiJavaReference reference) {
    Object completion = completionElement.getElement();
    assert !(completion instanceof LookupElement);

    if (reference instanceof PsiJavaCodeReferenceElement) {
      if (completion instanceof PsiMethod
          && ((PsiJavaCodeReferenceElement) reference).getParent()
              instanceof PsiImportStaticStatement) {
        return Collections.singletonList(
            JavaLookupElementBuilder.forMethod((PsiMethod) completion, PsiSubstitutor.EMPTY));
      }

      if (completion instanceof PsiClass) {
        return JavaClassNameCompletionContributor.createClassLookupItems(
            (PsiClass) completion,
            JavaClassNameCompletionContributor.AFTER_NEW.accepts(reference),
            JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER,
            Conditions.<PsiClass>alwaysTrue());
      }
    }

    if (reference instanceof PsiMethodReferenceExpression
        && completion instanceof PsiMethod
        && ((PsiMethod) completion).isConstructor()) {
      return Collections.singletonList(
          JavaLookupElementBuilder.forMethod(
              (PsiMethod) completion, "new", PsiSubstitutor.EMPTY, null));
    }

    LookupElement _ret = LookupItemUtil.objectToLookupItem(completion);
    if (_ret instanceof LookupItem) {
      final PsiSubstitutor substitutor = completionElement.getSubstitutor();
      if (substitutor != null) {
        ((LookupItem<?>) _ret).setAttribute(LookupItem.SUBSTITUTOR, substitutor);
      }
    }
    return Collections.singletonList(_ret);
  }
  @NotNull
  private static List<PsiMember> findByMap(
      @NotNull PsiClass aClass, String name, boolean checkBases, @NotNull MemberType type) {
    if (name == null) return Collections.emptyList();

    if (checkBases) {
      Map<String, List<Pair<PsiMember, PsiSubstitutor>>> allMethodsMap = getMap(aClass, type);
      List<Pair<PsiMember, PsiSubstitutor>> list = allMethodsMap.get(name);
      if (list == null) return Collections.emptyList();
      List<PsiMember> ret = new ArrayList<PsiMember>(list.size());
      for (final Pair<PsiMember, PsiSubstitutor> info : list) {
        ret.add(info.getFirst());
      }

      return ret;
    } else {
      PsiMember[] members = null;
      switch (type) {
        case METHOD:
          members = aClass.getMethods();
          break;
        case CLASS:
          members = aClass.getInnerClasses();
          break;
        case FIELD:
          members = aClass.getFields();
          break;
      }

      List<PsiMember> list = new ArrayList<PsiMember>();
      for (PsiMember member : members) {
        if (name.equals(member.getName())) {
          list.add(member);
        }
      }
      return list;
    }
  }
  private static void addGetterSetterElements(
      CompletionResultSet result, PsiClass parent, Set<MethodSignature> addedSignatures) {
    int count = 0;
    for (PsiField field : parent.getFields()) {
      if (field instanceof PsiEnumConstant) continue;

      List<PsiMethod> prototypes = ContainerUtil.newSmartList();
      Collections.addAll(
          prototypes, GetterSetterPrototypeProvider.generateGetterSetters(field, true));
      Collections.addAll(
          prototypes, GetterSetterPrototypeProvider.generateGetterSetters(field, false));
      for (final PsiMethod prototype : prototypes) {
        if (parent.findMethodBySignature(prototype, false) == null
            && addedSignatures.add(prototype.getSignature(PsiSubstitutor.EMPTY))) {
          Icon icon = prototype.getIcon(Iconable.ICON_FLAG_VISIBILITY);
          result.addElement(
              createGenerateMethodElement(
                  prototype,
                  PsiSubstitutor.EMPTY,
                  icon,
                  "",
                  new InsertHandler<LookupElement>() {
                    @Override
                    public void handleInsert(InsertionContext context, LookupElement item) {
                      removeLookupString(context);

                      insertGenerationInfos(
                          context,
                          Collections.singletonList(new PsiGenerationInfo<PsiMethod>(prototype)));
                    }
                  }));

          if (count++ > 100) return;
        }
      }
    }
  }
Пример #10
0
 public static List<PsiExpression> getReturnExpressions(PsiLambdaExpression lambdaExpression) {
   final PsiElement body = lambdaExpression.getBody();
   if (body instanceof PsiExpression) {
     // if (((PsiExpression)body).getType() != PsiType.VOID) return Collections.emptyList();
     return Collections.singletonList((PsiExpression) body);
   }
   final List<PsiExpression> result = new ArrayList<PsiExpression>();
   for (PsiReturnStatement returnStatement : getReturnStatements(lambdaExpression)) {
     final PsiExpression returnValue = returnStatement.getReturnValue();
     if (returnValue != null) {
       result.add(returnValue);
     }
   }
   return result;
 }
Пример #11
0
 @Nullable
 private static List<MethodSignature> hasSubsignature(List<MethodSignature> signatures) {
   for (MethodSignature signature : signatures) {
     boolean subsignature = true;
     for (MethodSignature methodSignature : signatures) {
       if (!signature.equals(methodSignature)) {
         if (!MethodSignatureUtil.isSubsignature(signature, methodSignature)) {
           subsignature = false;
           break;
         }
       }
     }
     if (subsignature) return Collections.singletonList(signature);
   }
   return signatures;
 }
Пример #12
0
 private static Collection<String> extractAnnotationValuesFromJavaDoc(
     PsiDocTag tag, String parameter) {
   if (tag == null) return Collections.emptyList();
   Collection<String> results = new ArrayList<>();
   Matcher matcher =
       Pattern.compile("\\@testng.test(?:.*)" + parameter + "\\s*=\\s*\"(.*?)\".*")
           .matcher(tag.getText());
   if (matcher.matches()) {
     String[] groups = matcher.group(1).split("[,\\s]");
     for (String group : groups) {
       final String trimmed = group.trim();
       if (trimmed.length() > 0) {
         results.add(trimmed);
       }
     }
   }
   return results;
 }
Пример #13
0
  @NotNull
  private Map<String, CachedValue<XmlNSDescriptor>> computeNsDescriptorMap() {
    Map<String, CachedValue<XmlNSDescriptor>> map = null;
    // XSD aware attributes processing

    final String noNamespaceDeclaration =
        getAttributeValue("noNamespaceSchemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI);
    final String schemaLocationDeclaration =
        getAttributeValue("schemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI);

    if (noNamespaceDeclaration != null) {
      map = initializeSchema(XmlUtil.EMPTY_URI, null, noNamespaceDeclaration, map);
    }
    if (schemaLocationDeclaration != null) {
      final StringTokenizer tokenizer = new StringTokenizer(schemaLocationDeclaration);
      while (tokenizer.hasMoreTokens()) {
        final String uri = tokenizer.nextToken();
        if (tokenizer.hasMoreTokens()) {
          map = initializeSchema(uri, null, tokenizer.nextToken(), map);
        }
      }
    }
    // namespace attributes processing (XSD declaration via ExternalResourceManager)

    if (hasNamespaceDeclarations()) {
      for (final XmlAttribute attribute : getAttributes()) {
        if (attribute.isNamespaceDeclaration()) {
          String ns = attribute.getValue();
          if (ns == null) ns = XmlUtil.EMPTY_URI;
          ns = getRealNs(ns);

          if (map == null || !map.containsKey(ns)) {
            map = initializeSchema(ns, getNSVersion(ns, this), getNsLocation(ns), map);
          }
        }
      }
    }
    return map == null ? Collections.<String, CachedValue<XmlNSDescriptor>>emptyMap() : map;
  }
 @NotNull
 public static List<MethodSignatureBackedByPsiMethod> findSuperMethodSignaturesIncludingStatic(
     PsiMethod method, boolean checkAccess) {
   if (!canHaveSuperMethod(method, checkAccess, true)) return Collections.emptyList();
   return findSuperMethodSignatures(method, null, true);
 }
 @NotNull
 public Iterable<PyElement> iterateNames() {
   return Collections.<PyElement>singleton(this);
 }
Пример #16
0
  public static boolean hasTest(
      PsiModifierListOwner element,
      boolean checkHierarchy,
      boolean checkDisabled,
      boolean checkJavadoc) {
    // LanguageLevel effectiveLanguageLevel = element.getManager().getEffectiveLanguageLevel();
    // boolean is15 = effectiveLanguageLevel != LanguageLevel.JDK_1_4 && effectiveLanguageLevel !=
    // LanguageLevel.JDK_1_3;
    boolean hasAnnotation =
        AnnotationUtil.isAnnotated(element, TEST_ANNOTATION_FQN, checkHierarchy, true);
    if (hasAnnotation) {
      if (checkDisabled) {
        PsiAnnotation annotation =
            AnnotationUtil.findAnnotation(element, true, TEST_ANNOTATION_FQN);
        if (annotation != null) {
          if (isDisabled(annotation)) return false;
        }
      }
      return true;
    }
    if (element instanceof PsiDocCommentOwner
        && checkJavadoc
        && getTextJavaDoc((PsiDocCommentOwner) element) != null) return true;
    // now we check all methods for the test annotation
    if (element instanceof PsiClass) {
      PsiClass psiClass = (PsiClass) element;
      for (PsiMethod method : psiClass.getAllMethods()) {
        PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, true, TEST_ANNOTATION_FQN);
        if (annotation != null) {
          if (checkDisabled) {
            if (isDisabled(annotation)) continue;
          }
          return true;
        }
        if (AnnotationUtil.isAnnotated(method, FACTORY_ANNOTATION_FQN, false, true)) return true;
        if (checkJavadoc && getTextJavaDoc(method) != null) return true;
      }
      return false;
    } else if (element instanceof PsiMethod) {
      // even if it has a global test, we ignore private and static methods
      if (element.hasModifierProperty(PsiModifier.PRIVATE)
          || element.hasModifierProperty(PsiModifier.STATIC)) {
        return false;
      }

      // if it's a method, we check if the class it's in has a global @Test annotation
      PsiClass psiClass = ((PsiMethod) element).getContainingClass();
      if (psiClass != null) {
        final PsiAnnotation annotation =
            checkHierarchy
                ? AnnotationUtil.findAnnotationInHierarchy(
                    psiClass, Collections.singleton(TEST_ANNOTATION_FQN))
                : AnnotationUtil.findAnnotation(psiClass, true, TEST_ANNOTATION_FQN);
        if (annotation != null) {
          if (checkDisabled && isDisabled(annotation)) return false;
          return !hasConfig(element);
        } else if (checkJavadoc && getTextJavaDoc(psiClass) != null) return true;
      }
    }
    return false;
  }
/** @author max Date: Oct 21, 2001 */
public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
  private static final List<RefMethod> EMPTY_METHOD_LIST = Collections.emptyList();
  private static final RefParameter[] EMPTY_PARAMS_ARRAY = new RefParameter[0];

  private static final int IS_APPMAIN_MASK = 0x10000;
  private static final int IS_LIBRARY_OVERRIDE_MASK = 0x20000;
  private static final int IS_CONSTRUCTOR_MASK = 0x40000;
  private static final int IS_ABSTRACT_MASK = 0x80000;
  private static final int IS_BODY_EMPTY_MASK = 0x100000;
  private static final int IS_ONLY_CALLS_SUPER_MASK = 0x200000;
  private static final int IS_RETURN_VALUE_USED_MASK = 0x400000;

  private static final int IS_TEST_METHOD_MASK = 0x4000000;
  private static final int IS_CALLED_ON_SUBCLASS_MASK = 0x8000000;

  private static final String RETURN_VALUE_UNDEFINED = "#";

  private List<RefMethod> mySuperMethods;
  private List<RefMethod> myDerivedMethods;
  private List<String> myUnThrownExceptions;

  private RefParameter[] myParameters;
  private String myReturnValueTemplate;
  protected final RefClass myOwnerClass;

  RefMethodImpl(@NotNull RefClass ownerClass, PsiMethod method, RefManager manager) {
    super(method, manager);

    ((RefClassImpl) ownerClass).add(this);

    myOwnerClass = ownerClass;
  }

  // To be used only from RefImplicitConstructor.
  protected RefMethodImpl(@NotNull String name, @NotNull RefClass ownerClass) {
    super(name, ownerClass);
    myOwnerClass = ownerClass;
    ((RefClassImpl) ownerClass).add(this);

    addOutReference(getOwnerClass());
    ((RefClassImpl) getOwnerClass()).addInReference(this);

    setConstructor(true);
  }

  @Override
  public void add(@NotNull RefEntity child) {
    if (child instanceof RefParameter) {
      return;
    }
    super.add(child);
  }

  @Override
  public List<RefEntity> getChildren() {
    List<RefEntity> superChildren = super.getChildren();
    if (myParameters == null) return superChildren;
    if (superChildren == null || superChildren.isEmpty())
      return Arrays.<RefEntity>asList(myParameters);

    List<RefEntity> allChildren =
        new ArrayList<RefEntity>(superChildren.size() + myParameters.length);
    allChildren.addAll(superChildren);
    Collections.addAll(allChildren, myParameters);
    return allChildren;
  }

  @Override
  protected void initialize() {
    final PsiMethod method = (PsiMethod) getElement();
    LOG.assertTrue(method != null);
    setConstructor(method.isConstructor());
    final PsiType returnType = method.getReturnType();
    setFlag(
        returnType == null
            || PsiType.VOID.equals(returnType)
            || returnType.equalsToText(CommonClassNames.JAVA_LANG_VOID),
        IS_RETURN_VALUE_USED_MASK);

    if (!isReturnValueUsed()) {
      myReturnValueTemplate = RETURN_VALUE_UNDEFINED;
    }

    if (isConstructor()) {
      addReference(getOwnerClass(), getOwnerClass().getElement(), method, false, true, null);
    }

    if (getOwnerClass().isInterface()) {
      setAbstract(false);
    } else {
      setAbstract(method.hasModifierProperty(PsiModifier.ABSTRACT));
    }

    setAppMain(isAppMain(method, this));
    setLibraryOverride(method.hasModifierProperty(PsiModifier.NATIVE));

    initializeSuperMethods(method);
    if (isExternalOverride()) {
      ((RefClassImpl) getOwnerClass()).addLibraryOverrideMethod(this);
    }

    @NonNls final String name = method.getName();
    if (getOwnerClass().isTestCase() && name.startsWith("test")) {
      setTestMethod(true);
    }

    PsiParameter[] paramList = method.getParameterList().getParameters();
    if (paramList.length > 0) {
      myParameters = new RefParameterImpl[paramList.length];
      for (int i = 0; i < paramList.length; i++) {
        PsiParameter parameter = paramList[i];
        myParameters[i] = getRefJavaManager().getParameterReference(parameter, i);
      }
    }

    if (method.hasModifierProperty(PsiModifier.NATIVE)) {
      updateReturnValueTemplate(null);
      updateThrowsList(null);
    }
    collectUncaughtExceptions(method);
  }

  private static boolean isAppMain(PsiMethod psiMethod, RefMethod refMethod) {
    if (!refMethod.isStatic()) return false;
    if (!PsiType.VOID.equals(psiMethod.getReturnType())) return false;

    PsiMethod appMainPattern = ((RefMethodImpl) refMethod).getRefJavaManager().getAppMainPattern();
    if (MethodSignatureUtil.areSignaturesEqual(psiMethod, appMainPattern)) return true;

    PsiMethod appPremainPattern =
        ((RefMethodImpl) refMethod).getRefJavaManager().getAppPremainPattern();
    if (MethodSignatureUtil.areSignaturesEqual(psiMethod, appPremainPattern)) return true;

    PsiMethod appAgentmainPattern =
        ((RefMethodImpl) refMethod).getRefJavaManager().getAppAgentmainPattern();
    return MethodSignatureUtil.areSignaturesEqual(psiMethod, appAgentmainPattern);
  }

  private void checkForSuperCall(PsiMethod method) {
    if (isConstructor()) {
      PsiCodeBlock body = method.getBody();
      if (body == null) return;
      PsiStatement[] statements = body.getStatements();
      boolean isBaseExplicitlyCalled = false;
      if (statements.length > 0) {
        PsiStatement first = statements[0];
        if (first instanceof PsiExpressionStatement) {
          PsiExpression firstExpression = ((PsiExpressionStatement) first).getExpression();
          if (firstExpression instanceof PsiMethodCallExpression) {
            PsiExpression qualifierExpression =
                ((PsiMethodCallExpression) firstExpression)
                    .getMethodExpression()
                    .getQualifierExpression();
            if (qualifierExpression instanceof PsiReferenceExpression) {
              @NonNls String text = qualifierExpression.getText();
              if ("super".equals(text) || text.equals("this")) {
                isBaseExplicitlyCalled = true;
              }
            }
          }
        }
      }

      if (!isBaseExplicitlyCalled) {
        for (RefClass superClass : getOwnerClass().getBaseClasses()) {
          RefMethodImpl superDefaultConstructor =
              (RefMethodImpl) superClass.getDefaultConstructor();

          if (superDefaultConstructor != null) {
            superDefaultConstructor.addInReference(this);
            addOutReference(superDefaultConstructor);
          }
        }
      }
    }
  }

  @Override
  @NotNull
  public Collection<RefMethod> getSuperMethods() {
    if (mySuperMethods == null) return EMPTY_METHOD_LIST;
    if (mySuperMethods.size() > 10) {
      LOG.info("method: " + getName() + " owner:" + getOwnerClass().getQualifiedName());
    }
    if (getRefManager().isOfflineView()) {
      LOG.debug("Should not traverse graph offline");
    }
    return mySuperMethods;
  }

  @Override
  @NotNull
  public Collection<RefMethod> getDerivedMethods() {
    if (myDerivedMethods == null) return EMPTY_METHOD_LIST;
    return myDerivedMethods;
  }

  @Override
  public boolean isBodyEmpty() {
    return checkFlag(IS_BODY_EMPTY_MASK);
  }

  @Override
  public boolean isOnlyCallsSuper() {
    return checkFlag(IS_ONLY_CALLS_SUPER_MASK);
  }

  @Override
  public boolean hasBody() {
    return !isAbstract() && !getOwnerClass().isInterface() || !isBodyEmpty();
  }

  private void initializeSuperMethods(PsiMethod method) {
    if (getRefManager().isOfflineView()) return;
    for (PsiMethod psiSuperMethod : method.findSuperMethods()) {
      if (getRefManager().belongsToScope(psiSuperMethod)) {
        RefMethodImpl refSuperMethod = (RefMethodImpl) getRefManager().getReference(psiSuperMethod);
        if (refSuperMethod != null) {
          addSuperMethod(refSuperMethod);
          refSuperMethod.markExtended(this);
        }
      } else {
        setLibraryOverride(true);
      }
    }
  }

  public void addSuperMethod(RefMethodImpl refSuperMethod) {
    if (!getSuperMethods().contains(refSuperMethod)
        && !refSuperMethod.getSuperMethods().contains(this)) {
      if (mySuperMethods == null) {
        mySuperMethods = new ArrayList<RefMethod>(1);
      }
      mySuperMethods.add(refSuperMethod);
    }
  }

  public void markExtended(RefMethodImpl method) {
    if (!getDerivedMethods().contains(method) && !method.getDerivedMethods().contains(this)) {
      if (myDerivedMethods == null) {
        myDerivedMethods = new ArrayList<RefMethod>(1);
      }
      myDerivedMethods.add(method);
    }
  }

  @Override
  @NotNull
  public RefParameter[] getParameters() {
    if (myParameters == null) return EMPTY_PARAMS_ARRAY;
    return myParameters;
  }

  @Override
  public void buildReferences() {
    // Work on code block to find what we're referencing...
    PsiMethod method = (PsiMethod) getElement();
    if (method == null) return;
    PsiCodeBlock body = method.getBody();
    final RefJavaUtil refUtil = RefJavaUtil.getInstance();
    refUtil.addReferences(method, this, body);
    refUtil.addReferences(method, this, method.getModifierList());
    checkForSuperCall(method);
    setOnlyCallsSuper(refUtil.isMethodOnlyCallsSuper(method));

    setBodyEmpty(
        isOnlyCallsSuper()
            || !isExternalOverride() && (body == null || body.getStatements().length == 0));

    refUtil.addTypeReference(method, method.getReturnType(), getRefManager(), this);

    for (RefParameter parameter : getParameters()) {
      refUtil.setIsFinal(parameter, parameter.getElement().hasModifierProperty(PsiModifier.FINAL));
    }

    getRefManager().fireBuildReferences(this);
  }

  private void collectUncaughtExceptions(@NotNull PsiMethod method) {
    if (isExternalOverride()) return;
    if (getRefManager().isOfflineView()) return;
    @NonNls final String name = method.getName();
    if (getOwnerClass().isTestCase() && name.startsWith("test")) return;

    if (getSuperMethods().isEmpty()) {
      PsiClassType[] throwsList = method.getThrowsList().getReferencedTypes();
      if (throwsList.length > 0) {
        myUnThrownExceptions =
            throwsList.length == 1
                ? new SmartList<String>()
                : new ArrayList<String>(throwsList.length);
        for (final PsiClassType type : throwsList) {
          PsiClass aClass = type.resolve();
          String fqn = aClass == null ? null : aClass.getQualifiedName();
          if (fqn != null) {
            myUnThrownExceptions.add(fqn);
          }
        }
      }
    }

    final PsiCodeBlock body = method.getBody();
    if (body == null) return;

    final Collection<PsiClassType> exceptionTypes =
        ExceptionUtil.collectUnhandledExceptions(body, method, false);
    for (final PsiClassType exceptionType : exceptionTypes) {
      updateThrowsList(exceptionType);
    }
  }

  public void removeUnThrownExceptions(PsiClass unThrownException) {
    if (myUnThrownExceptions != null) {
      myUnThrownExceptions.remove(unThrownException.getQualifiedName());
    }
  }

  @Override
  public void accept(@NotNull final RefVisitor visitor) {
    if (visitor instanceof RefJavaVisitor) {
      ApplicationManager.getApplication()
          .runReadAction(
              new Runnable() {
                @Override
                public void run() {
                  ((RefJavaVisitor) visitor).visitMethod(RefMethodImpl.this);
                }
              });
    } else {
      super.accept(visitor);
    }
  }

  @Override
  public boolean isExternalOverride() {
    return isLibraryOverride(new HashSet<RefMethod>());
  }

  private boolean isLibraryOverride(@NotNull Collection<RefMethod> processed) {
    if (!processed.add(this)) return false;

    if (checkFlag(IS_LIBRARY_OVERRIDE_MASK)) return true;
    for (RefMethod superMethod : getSuperMethods()) {
      if (((RefMethodImpl) superMethod).isLibraryOverride(processed)) {
        setFlag(true, IS_LIBRARY_OVERRIDE_MASK);
        return true;
      }
    }

    return false;
  }

  @Override
  public boolean isAppMain() {
    return checkFlag(IS_APPMAIN_MASK);
  }

  @Override
  public boolean isAbstract() {
    return checkFlag(IS_ABSTRACT_MASK);
  }

  @Override
  public boolean hasSuperMethods() {
    return !getSuperMethods().isEmpty() || isExternalOverride();
  }

  @Override
  public boolean isReferenced() {
    // Directly called from somewhere..
    for (RefElement refCaller : getInReferences()) {
      if (!getDerivedMethods().contains(refCaller)) return true;
    }

    // Library override probably called from library code.
    return isExternalOverride();
  }

  @Override
  public boolean hasSuspiciousCallers() {
    // Directly called from somewhere..
    for (RefElement refCaller : getInReferences()) {
      if (((RefElementImpl) refCaller).isSuspicious() && !getDerivedMethods().contains(refCaller))
        return true;
    }

    // Library override probably called from library code.
    if (isExternalOverride()) return true;

    // Class isn't instantiated. Most probably we have problem with class, not method.
    if (!isStatic() && !isConstructor()) {
      if (((RefClassImpl) getOwnerClass()).isSuspicious()) return true;

      // Is an override. Probably called via reference to base class.
      for (RefMethod refSuper : getSuperMethods()) {
        if (((RefMethodImpl) refSuper).isSuspicious()) return true;
      }
    }

    return false;
  }

  @Override
  public boolean isConstructor() {
    return checkFlag(IS_CONSTRUCTOR_MASK);
  }

  @Override
  public RefClass getOwnerClass() {
    return (RefClass) getOwner();
  }

  @NotNull
  @Override
  public String getName() {
    if (isValid()) {
      final String[] result = new String[1];
      final Runnable runnable =
          new Runnable() {
            @Override
            public void run() {
              PsiMethod psiMethod = (PsiMethod) getElement();
              if (psiMethod instanceof SyntheticElement) {
                result[0] = psiMethod.getName();
              } else {
                result[0] =
                    PsiFormatUtil.formatMethod(
                        psiMethod,
                        PsiSubstitutor.EMPTY,
                        PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
                        PsiFormatUtilBase.SHOW_TYPE);
              }
            }
          };

      ApplicationManager.getApplication().runReadAction(runnable);

      return result[0];
    } else {
      return super.getName();
    }
  }

  @Override
  public String getExternalName() {
    final String[] result = new String[1];
    final Runnable runnable =
        new Runnable() {
          @Override
          public void run() {
            final PsiMethod psiMethod = (PsiMethod) getElement();
            LOG.assertTrue(psiMethod != null);
            result[0] = PsiFormatUtil.getExternalName(psiMethod, true, Integer.MAX_VALUE);
          }
        };

    ApplicationManager.getApplication().runReadAction(runnable);

    return result[0];
  }

  @Nullable
  public static RefMethod methodFromExternalName(RefManager manager, String externalName) {
    return (RefMethod)
        manager.getReference(
            findPsiMethod(PsiManager.getInstance(manager.getProject()), externalName));
  }

  @Nullable
  public static PsiMethod findPsiMethod(PsiManager manager, String externalName) {
    final int spaceIdx = externalName.indexOf(' ');
    final String className = externalName.substring(0, spaceIdx);
    final PsiClass psiClass = ClassUtil.findPsiClass(manager, className);
    if (psiClass == null) return null;
    try {
      PsiElementFactory factory =
          JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory();
      String methodSignature = externalName.substring(spaceIdx + 1);
      PsiMethod patternMethod = factory.createMethodFromText(methodSignature, psiClass);
      return psiClass.findMethodBySignature(patternMethod, false);
    } catch (IncorrectOperationException e) {
      // Do nothing. Returning null is acceptable in this case.
      return null;
    }
  }

  @Override
  public void referenceRemoved() {
    if (getOwnerClass() != null) {
      ((RefClassImpl) getOwnerClass()).methodRemoved(this);
    }

    super.referenceRemoved();

    for (RefMethod superMethod : getSuperMethods()) {
      superMethod.getDerivedMethods().remove(this);
    }

    for (RefMethod subMethod : getDerivedMethods()) {
      subMethod.getSuperMethods().remove(this);
    }

    ArrayList<RefElement> deletedRefs = new ArrayList<RefElement>();
    for (RefParameter parameter : getParameters()) {
      getRefManager().removeRefElement(parameter, deletedRefs);
    }
  }

  @Override
  public boolean isSuspicious() {
    if (isConstructor()
        && PsiModifier.PRIVATE.equals(getAccessModifier())
        && getParameters().length == 0
        && getOwnerClass().getConstructors().size() == 1) return false;
    return super.isSuspicious();
  }

  public void setReturnValueUsed(boolean value) {
    if (checkFlag(IS_RETURN_VALUE_USED_MASK) == value) return;
    setFlag(value, IS_RETURN_VALUE_USED_MASK);
    for (RefMethod refSuper : getSuperMethods()) {
      ((RefMethodImpl) refSuper).setReturnValueUsed(value);
    }
  }

  @Override
  public boolean isReturnValueUsed() {
    return checkFlag(IS_RETURN_VALUE_USED_MASK);
  }

  public void updateReturnValueTemplate(PsiExpression expression) {
    if (myReturnValueTemplate == null) return;

    if (!getSuperMethods().isEmpty()) {
      for (final RefMethod refMethod : getSuperMethods()) {
        RefMethodImpl refSuper = (RefMethodImpl) refMethod;
        refSuper.updateReturnValueTemplate(expression);
      }
    } else {
      String newTemplate = null;
      final RefJavaUtil refUtil = RefJavaUtil.getInstance();
      if (expression instanceof PsiLiteralExpression) {
        PsiLiteralExpression psiLiteralExpression = (PsiLiteralExpression) expression;
        newTemplate = psiLiteralExpression.getText();
      } else if (expression instanceof PsiReferenceExpression) {
        PsiReferenceExpression referenceExpression = (PsiReferenceExpression) expression;
        PsiElement resolved = referenceExpression.resolve();
        if (resolved instanceof PsiField) {
          PsiField psiField = (PsiField) resolved;
          if (psiField.hasModifierProperty(PsiModifier.STATIC)
              && psiField.hasModifierProperty(PsiModifier.FINAL)
              && refUtil.compareAccess(refUtil.getAccessModifier(psiField), getAccessModifier())
                  >= 0) {
            newTemplate =
                PsiFormatUtil.formatVariable(
                    psiField,
                    PsiFormatUtilBase.SHOW_NAME
                        | PsiFormatUtilBase.SHOW_CONTAINING_CLASS
                        | PsiFormatUtilBase.SHOW_FQ_NAME,
                    PsiSubstitutor.EMPTY);
          }
        }
      } else if (refUtil.isCallToSuperMethod(expression, (PsiMethod) getElement())) return;

      //noinspection StringEquality
      if (myReturnValueTemplate == RETURN_VALUE_UNDEFINED) {
        myReturnValueTemplate = newTemplate;
      } else if (!Comparing.equal(myReturnValueTemplate, newTemplate)) {
        myReturnValueTemplate = null;
      }
    }
  }

  public void updateParameterValues(PsiExpression[] args) {
    if (isExternalOverride()) return;

    if (!getSuperMethods().isEmpty()) {
      for (RefMethod refSuper : getSuperMethods()) {
        ((RefMethodImpl) refSuper).updateParameterValues(args);
      }
    } else {
      final RefParameter[] params = getParameters();
      if (params.length <= args.length && params.length > 0) {
        for (int i = 0; i < args.length; i++) {
          RefParameter refParameter;
          if (params.length <= i) {
            refParameter = params[params.length - 1];
          } else {
            refParameter = params[i];
          }
          ((RefParameterImpl) refParameter).updateTemplateValue(args[i]);
        }
      }
    }
  }

  @Override
  public String getReturnValueIfSame() {
    //noinspection StringEquality
    if (myReturnValueTemplate == RETURN_VALUE_UNDEFINED) return null;
    return myReturnValueTemplate;
  }

  public void updateThrowsList(PsiClassType exceptionType) {
    if (!getSuperMethods().isEmpty()) {
      for (RefMethod refSuper : getSuperMethods()) {
        ((RefMethodImpl) refSuper).updateThrowsList(exceptionType);
      }
    } else if (myUnThrownExceptions != null) {
      if (exceptionType == null) {
        myUnThrownExceptions = null;
        return;
      }
      PsiClass exceptionClass = exceptionType.resolve();
      JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
      for (int i = myUnThrownExceptions.size() - 1; i >= 0; i--) {
        String exceptionFqn = myUnThrownExceptions.get(i);
        PsiClass classType =
            facade.findClass(
                exceptionFqn, GlobalSearchScope.allScope(getRefManager().getProject()));
        if (InheritanceUtil.isInheritorOrSelf(exceptionClass, classType, true)
            || InheritanceUtil.isInheritorOrSelf(classType, exceptionClass, true)) {
          myUnThrownExceptions.remove(i);
        }
      }

      if (myUnThrownExceptions.isEmpty()) myUnThrownExceptions = null;
    }
  }

  @Override
  @Nullable
  public PsiClass[] getUnThrownExceptions() {
    if (getRefManager().isOfflineView()) {
      LOG.debug("Should not traverse graph offline");
    }
    if (myUnThrownExceptions == null) return null;
    JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
    List<PsiClass> result = new ArrayList<PsiClass>(myUnThrownExceptions.size());
    for (String exception : myUnThrownExceptions) {
      PsiClass element =
          facade.findClass(exception, GlobalSearchScope.allScope(myManager.getProject()));
      if (element != null) result.add(element);
    }
    return result.toArray(new PsiClass[result.size()]);
  }

  public void setLibraryOverride(boolean libraryOverride) {
    setFlag(libraryOverride, IS_LIBRARY_OVERRIDE_MASK);
  }

  private void setAppMain(boolean appMain) {
    setFlag(appMain, IS_APPMAIN_MASK);
  }

  private void setAbstract(boolean anAbstract) {
    setFlag(anAbstract, IS_ABSTRACT_MASK);
  }

  public void setBodyEmpty(boolean bodyEmpty) {
    setFlag(bodyEmpty, IS_BODY_EMPTY_MASK);
  }

  private void setOnlyCallsSuper(boolean onlyCallsSuper) {
    setFlag(onlyCallsSuper, IS_ONLY_CALLS_SUPER_MASK);
  }

  private void setConstructor(boolean constructor) {
    setFlag(constructor, IS_CONSTRUCTOR_MASK);
  }

  @Override
  public boolean isTestMethod() {
    return checkFlag(IS_TEST_METHOD_MASK);
  }

  private void setTestMethod(boolean testMethod) {
    setFlag(testMethod, IS_TEST_METHOD_MASK);
  }

  @Override
  public PsiModifierListOwner getElement() {
    return (PsiModifierListOwner) super.getElement();
  }

  @Override
  public boolean isCalledOnSubClass() {
    return checkFlag(IS_CALLED_ON_SUBCLASS_MASK);
  }

  public void setCalledOnSubClass(boolean isCalledOnSubClass) {
    setFlag(isCalledOnSubClass, IS_CALLED_ON_SUBCLASS_MASK);
  }
}
Пример #18
0
 /** @return (super method, sub class) or null if can't find any siblings */
 @Nullable
 public static SiblingInfo getSiblingInfoInheritedViaSubClass(@NotNull final PsiMethod method) {
   return getSiblingInheritanceInfos(Collections.singletonList(method)).get(method);
 }
Пример #19
0
  private String[] suggestVariableNameByType(
      final PsiType type,
      final VariableKind variableKind,
      final boolean correctKeywords,
      boolean skipIndices) {
    String longTypeName = skipIndices ? type.getCanonicalText() : getLongTypeName(type);
    CodeStyleSettings.TypeToNameMap map = getMapByVariableKind(variableKind);
    if (map != null && longTypeName != null) {
      if (type.equals(PsiType.NULL)) {
        longTypeName = CommonClassNames.JAVA_LANG_OBJECT;
      }
      String name = map.nameByType(longTypeName);
      if (name != null && isIdentifier(name)) {
        return new String[] {name};
      }
    }

    final Collection<String> suggestions = new LinkedHashSet<String>();

    final PsiClass psiClass =
        !skipIndices && type instanceof PsiClassType ? ((PsiClassType) type).resolve() : null;

    if (!skipIndices) {
      suggestNamesForCollectionInheritors(type, variableKind, suggestions, correctKeywords);

      if (psiClass != null
          && CommonClassNames.JAVA_UTIL_OPTIONAL.equals(psiClass.getQualifiedName())
          && ((PsiClassType) type).getParameterCount() == 1) {
        PsiType optionalContent = ((PsiClassType) type).getParameters()[0];
        Collections.addAll(
            suggestions,
            suggestVariableNameByType(optionalContent, variableKind, correctKeywords, false));
      }

      suggestNamesFromGenericParameters(type, variableKind, suggestions, correctKeywords);
    }

    String typeName = getTypeName(type, !skipIndices);

    if (typeName != null) {
      typeName = normalizeTypeName(typeName);
      ContainerUtil.addAll(
          suggestions,
          getSuggestionsByName(
              typeName, variableKind, type instanceof PsiArrayType, correctKeywords));
    }

    if (psiClass != null && psiClass.getContainingClass() != null) {
      InheritanceUtil.processSupers(
          psiClass,
          false,
          new Processor<PsiClass>() {
            @Override
            public boolean process(PsiClass superClass) {
              if (PsiTreeUtil.isAncestor(superClass, psiClass, true)) {
                ContainerUtil.addAll(
                    suggestions,
                    getSuggestionsByName(
                        superClass.getName(), variableKind, false, correctKeywords));
              }
              return false;
            }
          });
    }

    return ArrayUtil.toStringArray(suggestions);
  }