@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; }
@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()]); }
/** * 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); } } } } } }