@Nullable
  public static PsiFile resolveFile(XmlAttribute location, PsiFile baseFile) {
    if (location == null) return null;
    final XmlAttributeValue valueElement = location.getValueElement();
    if (valueElement == null) return null;

    // prefer direct relative path
    final String value = valueElement.getValue();
    final PsiFile file = resolveFile(value, baseFile);
    if (file != baseFile && file instanceof XmlFile) {
      return file;
    }

    final PsiReference[] references = valueElement.getReferences();
    for (PsiReference reference : references) {
      final PsiElement target = reference.resolve();
      if (target == null && reference instanceof PsiPolyVariantReference) {
        final ResolveResult[] results = ((PsiPolyVariantReference) reference).multiResolve(false);
        for (ResolveResult result : results) {
          if (result.isValidResult()) {
            // TODO: how to weigh/prioritize the results?
            final PsiElement element = result.getElement();
            if (element != baseFile && element instanceof XmlFile) {
              return (PsiFile) target;
            }
          }
        }
      } else if (target != baseFile && target instanceof XmlFile) {
        return (PsiFile) target;
      }
    }
    return null;
  }
  private Collection<JSQualifiedNamedElement> getCandidates(Editor editor, PsiFile file) {
    final Collection<JSQualifiedNamedElement> candidates;

    if (myReference instanceof JSReferenceExpression
        && ((JSReferenceExpression) myReference).getQualifier() == null) {
      Collection<JSQualifiedNamedElement> c =
          getCandidates(editor, file, myReference.getCanonicalText());
      filterCandidates(c);
      candidates = new THashSet<>(c, JSPsiImplUtils.QUALIFIED_NAME_HASHING_STRATEGY);
    } else {
      JSQualifiedNamedElement invalidResult = null;

      for (ResolveResult r : myReference.multiResolve(false)) {
        PsiElement element = r.getElement();
        if (element instanceof JSQualifiedNamedElement) {
          invalidResult = (JSQualifiedNamedElement) element;
        }
      }
      if (invalidResult != null) {
        if (myReference.getElement().getParent() instanceof JSNewExpression
            && invalidResult instanceof JSFunction
            && ((JSFunction) invalidResult).isConstructor()) {
          invalidResult = (JSClass) invalidResult.getParent();
        }
        candidates = new SmartList<>();
        candidates.add(invalidResult);
      } else {
        candidates = Collections.emptyList();
      }
    }
    return candidates;
  }
 @NotNull
 private Set<PsiPackage> getContext() {
   if (myIndex == 0) return myReferenceSet.getInitialContext();
   Set<PsiPackage> psiPackages = new HashSet<>();
   for (ResolveResult resolveResult : myReferenceSet.getReference(myIndex - 1).doMultiResolve()) {
     PsiElement psiElement = resolveResult.getElement();
     if (psiElement instanceof PsiPackage) {
       psiPackages.add((PsiPackage) psiElement);
     }
   }
   return psiPackages;
 }
 @NotNull
 public QualifiedResolveResult followAssignmentsChain(PyResolveContext resolveContext) {
   PyReferenceExpression seeker = this;
   QualifiedResolveResult ret = null;
   List<PyExpression> qualifiers = new ArrayList<PyExpression>();
   PyExpression qualifier = seeker.getQualifier();
   if (qualifier != null) {
     qualifiers.add(qualifier);
   }
   Set<PsiElement> visited = new HashSet<PsiElement>();
   visited.add(this);
   SEARCH:
   while (ret == null) {
     ResolveResult[] targets = seeker.getReference(resolveContext).multiResolve(false);
     for (ResolveResult target : targets) {
       PsiElement elt = target.getElement();
       if (elt instanceof PyTargetExpression) {
         PsiElement assigned_from = null;
         final PyTargetExpression expr = (PyTargetExpression) elt;
         final TypeEvalContext context = resolveContext.getTypeEvalContext();
         if (context.maySwitchToAST(expr) || expr.getStub() == null) {
           assigned_from = expr.findAssignedValue();
         }
         // TODO: Maybe findAssignedValueByStub() should become a part of the PyTargetExpression
         // interface
         else if (elt instanceof PyTargetExpressionImpl) {
           assigned_from = ((PyTargetExpressionImpl) elt).findAssignedValueByStub(context);
         }
         if (assigned_from instanceof PyReferenceExpression) {
           if (visited.contains(assigned_from)) {
             break;
           }
           visited.add(assigned_from);
           seeker = (PyReferenceExpression) assigned_from;
           if (seeker.getQualifier() != null) {
             qualifiers.add(seeker.getQualifier());
           }
           continue SEARCH;
         } else if (assigned_from != null)
           ret = new QualifiedResolveResultImpl(assigned_from, qualifiers, false);
       } else if (ret == null && elt instanceof PyElement && target.isValidResult()) {
         // remember this result, but a further reference may be the next resolve result
         ret =
             new QualifiedResolveResultImpl(
                 elt, qualifiers, target instanceof ImplicitResolveResult);
       }
     }
     // all resolve results checked, reassignment not detected, nothing more to do
     break;
   }
   if (ret == null) ret = EMPTY_RESULT;
   return ret;
 }
  @Deprecated
  public static PsiElement[] getClassInterfacePsiElements(
      Project project, String FQNClassOrInterfaceName) {

    // convert ResolveResult to PsiElement
    List<PsiElement> results = new ArrayList<PsiElement>();
    for (ResolveResult result : getClassInterfaceResolveResult(project, FQNClassOrInterfaceName)) {
      results.add(result.getElement());
    }

    return results.toArray(new PsiElement[results.size()]);
  }
  public void testOnClickNavigation() throws Throwable {
    copyOnClickClasses();
    final VirtualFile file = copyFileToProject(getTestName(true) + ".xml");
    myFixture.configureFromExistingVirtualFile(file);

    final PsiReference reference =
        TargetElementUtil.findReference(myFixture.getEditor(), myFixture.getCaretOffset());
    assertNotNull(reference);
    assertInstanceOf(reference, PsiPolyVariantReference.class);
    final ResolveResult[] results = ((PsiPolyVariantReference) reference).multiResolve(false);
    assertEquals(2, results.length);
    for (ResolveResult result : results) {
      assertInstanceOf(result.getElement(), PsiMethod.class);
    }
  }
  public boolean isAvailable(
      @NotNull final Project project, final Editor editor, final PsiFile file) {
    if (!myReference.getElement().isValid()) return false;
    final long modL =
        myReference.getElement().getManager().getModificationTracker().getModificationCount();

    if (!isAvailableCalculated || modL != modificationCount) {
      final ResolveResult[] results = myReference.multiResolve(false);
      boolean hasValidResult = false;

      for (ResolveResult r : results) {
        if (r.isValidResult()) {
          hasValidResult = true;
          break;
        }
      }

      if (!hasValidResult) {
        final Collection<JSQualifiedNamedElement> candidates = getCandidates(editor, file);

        isAvailableCalculated = true;
        isAvailable = candidates.size() > 0;
        String text;

        if (isAvailable) {
          final JSQualifiedNamedElement element = candidates.iterator().next();
          text = element.getQualifiedName() + "?";
          if (candidates.size() > 1) text += " (multiple choices...)";
          if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
            text += " Alt+Enter";
          }
        } else {
          text = "";
        }
        myText = text;
      } else {
        isAvailableCalculated = true;
        isAvailable = false;
        myText = "";
      }

      modificationCount = modL;
    }

    return isAvailable;
  }
Beispiel #8
0
  private static List<PsiElement> resolve(final PsiReference ref) {
    // IDEA-56727 try resolve first as in GotoDeclarationAction
    PsiElement resolvedElement = ref.resolve();

    if (resolvedElement == null && ref instanceof PsiPolyVariantReference) {
      List<PsiElement> result = new ArrayList<PsiElement>();
      final ResolveResult[] psiElements = ((PsiPolyVariantReference) ref).multiResolve(false);
      for (ResolveResult resolveResult : psiElements) {
        if (resolveResult.getElement() != null) {
          result.add(resolveResult.getElement());
        }
      }
      return result;
    }
    return resolvedElement == null
        ? Collections.<PsiElement>emptyList()
        : Collections.singletonList(resolvedElement);
  }
    @NotNull
    @Override
    public ResolveResult[] resolve(
        @NotNull CSharpReferenceExpressionImpl ref,
        boolean incompleteCode,
        boolean resolveFromParent) {
      if (!incompleteCode) {
        return ref.multiResolveImpl(ref.kind(), resolveFromParent);
      } else {
        ResolveResult[] resolveResults = ref.multiResolve(false, resolveFromParent);

        List<ResolveResult> filter = new SmartList<ResolveResult>();
        for (ResolveResult resolveResult : resolveResults) {
          if (resolveResult.isValidResult()) {
            filter.add(resolveResult);
          }
        }
        return ContainerUtil.toArray(filter, ResolveResult.EMPTY_ARRAY);
      }
    }
 /**
  * Returns number of different parameters in i18n message. For example, for string <i>Class {0}
  * info: Class {0} extends class {1} and implements interface {2}</i> number of parameters is 3.
  *
  * @param expression i18n literal
  * @return number of parameters
  */
 public static int getPropertyValueParamsMaxCount(final PsiLiteralExpression expression) {
   int maxCount = -1;
   for (PsiReference reference : expression.getReferences()) {
     if (reference instanceof PsiPolyVariantReference) {
       for (ResolveResult result : ((PsiPolyVariantReference) reference).multiResolve(false)) {
         if (result.isValidResult() && result.getElement() instanceof IProperty) {
           String value = ((IProperty) result.getElement()).getValue();
           MessageFormat format;
           try {
             format = new MessageFormat(value);
           } catch (Exception e) {
             continue; // ignore syntax error
           }
           try {
             int count = format.getFormatsByArgumentIndex().length;
             maxCount = Math.max(maxCount, count);
           } catch (IllegalArgumentException ignored) {
           }
         }
       }
     }
   }
   return maxCount;
 }
    @Override
    public void visitXmlAttributeValue(XmlAttributeValue value) {
      for (PsiReference reference : value.getReferences()) {
        if (!(reference instanceof OnClickConverter.MyReference)) {
          continue;
        }
        final OnClickConverter.MyReference ref = (OnClickConverter.MyReference) reference;
        final String methodName = ref.getValue();

        if (methodName.isEmpty()) {
          continue;
        }
        final ResolveResult[] results = ref.multiResolve(false);
        final Set<PsiClass> resolvedClasses = new HashSet<PsiClass>();
        final Set<PsiClass> resolvedClassesWithMistake = new HashSet<PsiClass>();

        for (ResolveResult result : results) {
          if (result instanceof OnClickConverter.MyResolveResult) {
            final PsiElement element = result.getElement();

            if (element != null) {
              final PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);

              if (aClass != null) {
                resolvedClasses.add(aClass);

                if (!((OnClickConverter.MyResolveResult) result).hasCorrectSignature()) {
                  resolvedClassesWithMistake.add(aClass);
                }
              }
            }
          }
        }
        PsiClass activity = null;
        for (PsiClass relatedActivity : myRelatedActivities) {
          if (!containsOrExtends(resolvedClasses, relatedActivity)) {
            activity = relatedActivity;
            break;
          } else if (activity == null
              && containsOrExtends(resolvedClassesWithMistake, relatedActivity)) {
            activity = relatedActivity;
          }
        }

        if (activity != null) {
          reportMissingOnClickProblem(
              ref, activity, methodName, resolvedClassesWithMistake.contains(activity));
        } else if (results.length == 0) {
          myResult.add(
              myInspectionManager.createProblemDescriptor(
                  value,
                  reference.getRangeInElement(),
                  ProblemsHolder.unresolvedReferenceMessage(reference),
                  ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
                  myOnTheFly));
        } else if (resolvedClassesWithMistake.size() > 0) {
          reportMissingOnClickProblem(
              ref, resolvedClassesWithMistake.iterator().next(), methodName, true);
        }
      }
    }
  @Override
  public void doCollectInformation(@NotNull final ProgressIndicator progress) {
    @SuppressWarnings("unchecked")
    HighlightUsagesHandlerBase<PsiElement> handler =
        HighlightUsagesHandler.createCustomHandler(myEditor, myFile);
    if (handler != null) {
      List<PsiElement> targets = handler.getTargets();
      handler.computeUsages(targets);
      final List<TextRange> readUsages = handler.getReadUsages();
      for (TextRange readUsage : readUsages) {
        LOG.assertTrue(readUsage != null, "null text range from " + handler);
      }
      myReadAccessRanges.addAll(readUsages);
      final List<TextRange> writeUsages = handler.getWriteUsages();
      for (TextRange writeUsage : writeUsages) {
        LOG.assertTrue(writeUsage != null, "null text range from " + handler);
      }
      myWriteAccessRanges.addAll(writeUsages);
      if (!handler.highlightReferences()) return;
    }

    int flags =
        TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED;
    PsiElement myTarget;
    try {
      myTarget = TargetElementUtil.getInstance().findTargetElement(myEditor, flags, myCaretOffset);
    } catch (IndexNotReadyException e) {
      return;
    }

    if (myTarget == null) {
      if (!PsiDocumentManager.getInstance(myProject).isUncommited(myEditor.getDocument())) {
        // when document is committed, try to check injected stuff - it's fast
        Editor injectedEditor =
            InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(
                myEditor, myFile, myCaretOffset);
        myTarget =
            TargetElementUtil.getInstance()
                .findTargetElement(
                    injectedEditor, flags, injectedEditor.getCaretModel().getOffset());
      }
    }

    if (myTarget != null) {
      highlightTargetUsages(myTarget);
    } else {
      PsiReference ref = TargetElementUtil.findReference(myEditor);
      if (ref instanceof PsiPolyVariantReference) {
        if (!ref.getElement().isValid()) {
          throw new PsiInvalidElementAccessException(
              ref.getElement(),
              "Invalid element in " + ref + " of " + ref.getClass() + "; editor=" + myEditor);
        }
        ResolveResult[] results = ((PsiPolyVariantReference) ref).multiResolve(false);
        if (results.length > 0) {
          for (ResolveResult result : results) {
            PsiElement target = result.getElement();
            if (target != null) {
              if (!target.isValid()) {
                throw new PsiInvalidElementAccessException(
                    target,
                    "Invalid element returned from "
                        + ref
                        + " of "
                        + ref.getClass()
                        + "; editor="
                        + myEditor);
              }
              highlightTargetUsages(target);
            }
          }
        }
      }
    }
  }
  @Override
  protected boolean acceptsForMembersVisibility(
      @NotNull JSPsiElementBase element, @NotNull SinkResolveProcessor resolveProcessor) {
    if (!(element instanceof JSAttributeListOwner)) return true;
    final JSAttributeList attributeList = ((JSAttributeListOwner) element).getAttributeList();

    if (JSResolveUtil.getClassOfContext(place) != JSResolveUtil.getClassOfContext(element)) {
      if (!acceptPrivateMembers) {
        if (attributeList != null
            && attributeList.getAccessType() == JSAttributeList.AccessType.PRIVATE) {
          resolveProcessor.addPossibleCandidateResult(
              element, JSResolveResult.PRIVATE_MEMBER_IS_NOT_ACCESSIBLE);
          return false;
        }
      }

      if (!acceptProtectedMembers) {
        if (attributeList != null
            && attributeList.getAccessType() == JSAttributeList.AccessType.PROTECTED) {
          // we are resolving in context of the class or element within context of the class
          if ((myClassScopeTypeName != null || isParentClassContext(element))) {
            resolveProcessor.addPossibleCandidateResult(
                element, JSResolveResult.PROTECTED_MEMBER_IS_NOT_ACCESSIBLE);
            return false;
          } // if element / context out of class then protected element is ok due to includes
        }
      }
    }

    PsiElement elt = JSResolveUtil.findParent(element);

    if (processStatics) {
      if ((attributeList == null
          || !attributeList.hasModifier(JSAttributeList.ModifierType.STATIC))) {
        if (JSResolveUtil.PROTOTYPE_FIELD_NAME.equals(resolveProcessor.getName())) return true;
        resolveProcessor.addPossibleCandidateResult(
            element, JSResolveResult.INSTANCE_MEMBER_INACCESSIBLE);
        return false;
      }
      if (myTypeName != null
          && elt instanceof JSClass
          && !myTypeName.equals(((JSClass) elt).getQualifiedName())) {
        // static members are inherited in TypeScript classes
        resolveProcessor.addPossibleCandidateResult(
            element, JSResolveResult.STATIC_MEMBER_INACCESSIBLE);
        return false;
      }
    } else if (myClassDeclarationStarted && !allowUnqualifiedStaticsFromInstance) {
      // ActionScript only?
      if (attributeList != null && attributeList.hasModifier(JSAttributeList.ModifierType.STATIC)) {
        boolean referencingClass = false;

        if (place instanceof JSReferenceExpression) {
          JSExpression qualifier = ((JSReferenceExpression) place).getQualifier();
          if (qualifier instanceof JSReferenceExpression) {
            List<JSElement> expressions =
                JSSymbolUtil.calcRefExprValues((JSReferenceExpression) qualifier);
            expressions:
            for (JSElement expression : expressions) {
              if (expression instanceof JSReferenceExpression) {
                for (ResolveResult r : ((JSReferenceExpression) expression).multiResolve(false)) {
                  PsiElement rElement = r.getElement();
                  if (rElement instanceof JSClass) {
                    referencingClass = true;
                    break expressions;
                  }
                }
              }
            }
          }
        }
        if (!referencingClass) {
          resolveProcessor.addPossibleCandidateResult(
              element, JSResolveResult.STATIC_MEMBER_INACCESSIBLE);
          return false;
        }
      }
    }

    if (processActionScriptNotAllowedNsAttributes(element, resolveProcessor, attributeList))
      return false;
    return true;
  }