public static List<? extends PsiElement> resolveSimpleReference( PsiElement scopeElement, String name) { final List<DartComponentName> result = new ArrayList<DartComponentName>(); // local final ResolveScopeProcessor resolveScopeProcessor = new ResolveScopeProcessor(result, name, DartResolveUtil.isLValue(scopeElement)); PsiTreeUtil.treeWalkUp(resolveScopeProcessor, scopeElement, null, new ResolveState()); // supers final DartClass dartClass = PsiTreeUtil.getParentOfType(scopeElement, DartClass.class); final boolean inClass = PsiTreeUtil.getParentOfType(scopeElement, DartClassBody.class, false) != null; if (result.isEmpty() && dartClass != null && inClass) { final DartComponent field = filterAccess(scopeElement, dartClass.findMembersByName(name)); if (field != null) { return toResult(field.getComponentName()); } } // global if (result.isEmpty()) { final List<VirtualFile> libraryFiles = DartResolveUtil.findLibrary(scopeElement.getContainingFile()); DartResolveUtil.processTopLevelDeclarations( scopeElement, resolveScopeProcessor, libraryFiles, name); } // dart:core if (result.isEmpty() && !"void".equals(name)) { final List<VirtualFile> libraryFiles = DartLibraryIndex.findLibraryClass(scopeElement, "dart:core"); DartResolveUtil.processTopLevelDeclarations( scopeElement, resolveScopeProcessor, libraryFiles, name); } return result; }
private static List<? extends PsiElement> resolveSimpleReference( @NotNull DartReference reference) { final List<? extends PsiElement> result = resolveSimpleReference(reference, reference.getCanonicalText()); final PsiElement parent = reference.getParent(); final PsiElement superParent = parent.getParent(); final boolean isSimpleConstructor = parent instanceof DartType && superParent instanceof DartNewExpression && ((DartNewExpression) superParent).getReferenceExpression() == null; if (!isSimpleConstructor || result.isEmpty()) { return result; } final List<PsiElement> filteredResult = new ArrayList<PsiElement>(result.size()); for (PsiElement element : result) { final PsiElement elementParent = element.getParent(); if (element instanceof DartComponentName && elementParent instanceof DartClass) { final DartComponent component = ((DartClass) elementParent).findNamedConstructor(reference.getCanonicalText()); if (component != null && DartComponentType.typeOf(component) == DartComponentType.CONSTRUCTOR) { filteredResult.add(component.getComponentName()); continue; } } filteredResult.add(element); } return filteredResult; }
private static void appendSignature( final DartComponent namedComponent, final StringBuilder builder) { if (namedComponent instanceof DartClass) { appendClassSignature(builder, (DartClass) namedComponent); } else if (namedComponent instanceof DartFunctionDeclarationWithBodyOrNative) { appendFunctionSignature( builder, namedComponent, ((DartFunctionDeclarationWithBodyOrNative) namedComponent).getReturnType()); } else if (namedComponent instanceof DartFunctionTypeAlias) { builder.append("typedef "); appendFunctionSignature( builder, namedComponent, ((DartFunctionTypeAlias) namedComponent).getReturnType()); } else if (namedComponent.isConstructor()) { appendConstructorSignature( builder, namedComponent, PsiTreeUtil.getParentOfType(namedComponent, DartClass.class)); } else if (namedComponent instanceof DartMethodDeclaration) { appendFunctionSignature( builder, namedComponent, ((DartMethodDeclaration) namedComponent).getReturnType()); } else if (namedComponent instanceof DartVarAccessDeclaration) { appendVariableSignature( builder, namedComponent, ((DartVarAccessDeclaration) namedComponent).getType()); } else if (namedComponent instanceof DartGetterDeclaration) { builder.append("get "); appendFunctionSignature( builder, namedComponent, ((DartGetterDeclaration) namedComponent).getReturnType()); } else if (namedComponent instanceof DartSetterDeclaration) { builder.append("set "); appendFunctionSignature( builder, namedComponent, ((DartSetterDeclaration) namedComponent).getReturnType()); } else if (namedComponent instanceof DartEnumConstantDeclaration) { builder.append(((DartEnumDefinition) namedComponent.getParent()).getName()).append(" "); builder.append("<b>").append(namedComponent.getName()).append("</b>"); } }
@Nullable @Override public List<? extends PsiElement> resolve( @NotNull DartReference reference, boolean incompleteCode) { if (reference instanceof DartThisExpression) { return toResult(PsiTreeUtil.getParentOfType(reference, DartClass.class)); } if (reference instanceof DartParameterNameReferenceExpression) { final DartCallExpression callExpression = PsiTreeUtil.getParentOfType(reference, DartCallExpression.class); final DartExpression expression = callExpression != null ? callExpression.getExpression() : null; final PsiElement target = expression instanceof DartReference ? ((DartReference) expression).resolve() : null; final DartFormalParameterList parameters = PsiTreeUtil.getChildOfType( target != null ? target.getParent() : null, DartFormalParameterList.class); return toResult(DartResolveUtil.findParameterByName(parameters, reference.getText())); } if (DartResolveUtil.aloneOrFirstInChain(reference)) { return resolveSimpleReference(reference); } final DartReference leftReference = DartResolveUtil.getLeftReference(reference); // reference [node, node] final DartReference[] references = PsiTreeUtil.getChildrenOfType(reference, DartReference.class); if (references != null && references.length == 2) { // prefix final List<DartComponentName> names = DartResolveUtil.findComponentsInLibraryByPrefix( reference, references[0].getCanonicalText(), references[1].getCanonicalText()); if (!names.isEmpty()) { return toResult(names); } return toResult(references[1].resolve()); } else if (leftReference != null) { final DartClassResolveResult classResolveResult = leftReference.resolveDartClass(); final DartClass dartClass = classResolveResult.getDartClass(); if (dartClass != null) { final String name = reference.getCanonicalText(); final DartComponent subComponent = leftReference instanceof DartType ? dartClass.findNamedConstructor(name) : filterAccess(reference, dartClass.findMembersByName(name)); return toResult(subComponent == null ? null : subComponent.getComponentName()); } // prefix final List<DartComponentName> names = DartResolveUtil.findComponentsInLibraryByPrefix( reference, leftReference.getCanonicalText(), reference.getCanonicalText()); if (!names.isEmpty()) { return toResult(names); } } return null; }
private static void appendFunctionSignature( final StringBuilder builder, final DartComponent function, final String returnType) { builder.append("<b>").append(function.getName()).append("</b>"); if (!function.isGetter()) { builder.append('('); builder.append( StringUtil.escapeXml( DartPresentableUtil.getPresentableParameterList( function, new DartGenericSpecialization(), true, true))); builder.append(')'); } builder.append(' '); builder.append(DartPresentableUtil.RIGHT_ARROW); builder.append(' '); builder.append(returnType); }
private static void appendVariableSignature( final StringBuilder builder, final DartComponent component, final DartType type) { if (type == null) { builder.append("var "); } else { builder.append(type.getReferenceExpression().getText()); appendTypeArguments(builder, type); builder.append(" "); } builder.append("<b>").append(component.getName()).append("</b>"); }
@Nullable private static String getDocumentationText(final DartComponent dartComponent) { // PSI is not perfect currently, doc comment may be not part of the corresponding DartComponent // element, so docs are searched for in several places: // - direct child of this DartComponent // - previous sibling (or previous sibling of parent element if this element is first child of // its parent DartClassMembers) // Consequent line doc comments (///) are joined // 1. Look for multiline doc comment as direct child final DartDocComment multilineComment = PsiTreeUtil.getChildOfType(dartComponent, DartDocComment.class); if (multilineComment != null) return getMultilineDocCommentText(multilineComment); // 2. Look for single line doc comments as direct children final PsiComment[] childComments = PsiTreeUtil.getChildrenOfType(dartComponent, PsiComment.class); if (childComments != null) { // final String docText = getSingleLineDocCommentsText(childComments); if (docText != null) return docText; } PsiElement anchorElement = dartComponent; final PsiElement parent = dartComponent.getParent(); if (parent instanceof DartClassMembers && parent.getFirstChild() == dartComponent || dartComponent instanceof DartVarAccessDeclaration) { anchorElement = parent; } // 3. Look for multiline doc comment or line doc comments as previous siblings final List<PsiComment> siblingComments = new ArrayList<PsiComment>(); PsiElement previous = anchorElement; while ((previous = UsefulPsiTreeUtil.getPrevSiblingSkipWhiteSpaces(previous, true)) instanceof PsiComment) { if (previous instanceof DartDocComment) { return getMultilineDocCommentText((DartDocComment) previous); } siblingComments.add(0, (PsiComment) previous); } if (!siblingComments.isEmpty()) { return getSingleLineDocCommentsText( siblingComments.toArray(new PsiComment[siblingComments.size()])); } return null; }