@Override
  public String generateDocumentationContentStub(PsiComment contextComment) {
    if (!(contextComment instanceof GrDocComment)) {
      return null;
    }

    final GrDocCommentOwner owner = GrDocCommentUtil.findDocOwner((GrDocComment) contextComment);
    if (owner == null) return null;

    Project project = contextComment.getProject();
    final CodeDocumentationAwareCommenter commenter =
        (CodeDocumentationAwareCommenter)
            LanguageCommenters.INSTANCE.forLanguage(owner.getLanguage());

    StringBuilder builder = StringBuilderSpinAllocator.alloc();
    try {
      if (owner instanceof GrMethod) {
        final GrMethod method = (GrMethod) owner;
        JavaDocumentationProvider.generateParametersTakingDocFromSuperMethods(
            project, builder, commenter, method);

        final PsiType returnType = method.getInferredReturnType();
        if ((returnType != null || method.getModifierList().hasModifierProperty(GrModifier.DEF))
            && !PsiType.VOID.equals(returnType)) {
          builder.append(
              CodeDocumentationUtil.createDocCommentLine(RETURN_TAG, project, commenter));
          builder.append(LINE_SEPARATOR);
        }

        final PsiClassType[] references = method.getThrowsList().getReferencedTypes();
        for (PsiClassType reference : references) {
          builder.append(
              CodeDocumentationUtil.createDocCommentLine(THROWS_TAG, project, commenter));
          builder.append(reference.getClassName());
          builder.append(LINE_SEPARATOR);
        }
      } else if (owner instanceof GrTypeDefinition) {
        final PsiTypeParameterList typeParameterList = ((PsiClass) owner).getTypeParameterList();
        if (typeParameterList != null) {
          JavaDocumentationProvider.createTypeParamsListComment(
              builder, project, commenter, typeParameterList);
        }
      }
      return builder.length() > 0 ? builder.toString() : null;
    } finally {
      StringBuilderSpinAllocator.dispose(builder);
    }
  }
 @Override
 public boolean hasDocumentationFor(PsiElement element, PsiElement originalElement) {
   PsiElement docElement = getDocumentationElement(element, originalElement);
   if (docElement != null
       && docElement.getUserData(NonCodeMembersHolder.DOCUMENTATION_URL) != null) return true;
   return JavaDocumentationProvider.hasUrlFor(element);
 }
 @Nullable
 public List<String> getUrlFor(PsiElement element, PsiElement originalElement) {
   List<String> result = new ArrayList<String>();
   PsiElement docElement = getDocumentationElement(element, originalElement);
   if (docElement != null) {
     ContainerUtil.addIfNotNull(
         result, docElement.getUserData(NonCodeMembersHolder.DOCUMENTATION_URL));
   }
   List<String> list = JavaDocumentationProvider.getExternalJavaDocUrl(element);
   if (list != null) {
     result.addAll(list);
   }
   return result.isEmpty() ? null : result;
 }
  private static String generateClassInfo(PsiClass aClass) {
    StringBuilder buffer = new StringBuilder();
    GroovyFile file = (GroovyFile) aClass.getContainingFile();

    String packageName = file.getPackageName();
    if (!packageName.isEmpty()) {
      buffer.append(packageName).append("\n");
    }

    final String classString =
        aClass.isInterface()
            ? "interface"
            : aClass instanceof PsiTypeParameter
                ? "type parameter"
                : aClass.isEnum() ? "enum" : "class";
    buffer.append(classString).append(" ").append(aClass.getName());

    JavaDocumentationProvider.generateTypeParameters(aClass, buffer);

    JavaDocumentationProvider.writeExtends(aClass, buffer, aClass.getExtendsListTypes());
    JavaDocumentationProvider.writeImplements(aClass, buffer, aClass.getImplementsListTypes());

    return buffer.toString();
  }
 @Override
 public String fetchExternalDocumentation(
     final Project project, PsiElement element, final List<String> docUrls) {
   return JavaDocumentationProvider.fetchExternalJavadoc(element, project, docUrls);
 }
  @Override
  @Nullable
  public String generateDoc(PsiElement element, PsiElement originalElement) {
    if (element instanceof CustomMembersGenerator.GdslNamedParameter) {
      CustomMembersGenerator.GdslNamedParameter parameter =
          (CustomMembersGenerator.GdslNamedParameter) element;
      String result = "<pre><b>" + parameter.getName() + "</b>";
      if (parameter.myParameterTypeText != null) {
        result += ": " + parameter.myParameterTypeText;
      }
      result += "</pre>";
      if (parameter.docString != null) {
        result += "<p>" + parameter.docString;
      }
      return result;
    }

    if (element instanceof GrReferenceExpression) {
      return getMethodCandidateInfo((GrReferenceExpression) element);
    }

    element = getDocumentationElement(element, originalElement);

    if (element == null) return null;

    String standard =
        element.getNavigationElement() instanceof PsiDocCommentOwner
            ? JavaDocumentationProvider.generateExternalJavadoc(element)
            : null;

    if (element instanceof GrVariable
        && ((GrVariable) element).getTypeElementGroovy() == null
        && standard != null) {
      final String truncated = StringUtil.trimEnd(standard, BODY_HTML);

      StringBuilder buffer = new StringBuilder(truncated);
      buffer.append("<p>");
      if (originalElement != null) {
        appendInferredType(originalElement, (GrVariable) element, buffer);
      } else if (element.getParent() instanceof GrVariableDeclaration) {
        appendInferredType(element.getParent(), (GrVariable) element, buffer);
      }

      if (!truncated.equals(standard)) {
        buffer.append(BODY_HTML);
      }
      standard = buffer.toString();
    }

    String gdslDoc = element.getUserData(NonCodeMembersHolder.DOCUMENTATION);
    if (gdslDoc != null) {
      if (standard != null) {
        String truncated = StringUtil.trimEnd(standard, BODY_HTML);
        String appended = truncated + "<p>" + gdslDoc;
        if (truncated.equals(standard)) {
          return appended;
        }
        return appended + BODY_HTML;
      }
      return gdslDoc;
    }

    return standard;
  }