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
  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;
  }