| /******************************************************************************* |
| * Copyright (c) 2014 Christian Pontesegger and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * Contributors: |
| * Christian Pontesegger - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ease.helpgenerator; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| |
| import com.sun.javadoc.AnnotationDesc; |
| import com.sun.javadoc.AnnotationDesc.ElementValuePair; |
| import com.sun.javadoc.ClassDoc; |
| import com.sun.javadoc.FieldDoc; |
| import com.sun.javadoc.MethodDoc; |
| import com.sun.javadoc.ParamTag; |
| import com.sun.javadoc.Parameter; |
| import com.sun.javadoc.ProgramElementDoc; |
| import com.sun.javadoc.Tag; |
| import com.sun.javadoc.ThrowsTag; |
| import com.sun.javadoc.Type; |
| |
| public class HTMLWriter { |
| |
| private class Overview implements Comparable<Overview> { |
| private final String fTitle; |
| private final String fLinkID; |
| private final String fDescription; |
| private final boolean fDeprecated; |
| |
| public Overview(final String title, final String linkID, final String description, final boolean deprecated) { |
| fTitle = title; |
| fLinkID = linkID; |
| fDescription = description; |
| fDeprecated = deprecated; |
| } |
| |
| @Override |
| public int compareTo(final Overview arg0) { |
| return fTitle.compareTo(arg0.fTitle); |
| } |
| }; |
| |
| private interface CommentExtractor { |
| String extract(MethodDoc method); |
| }; |
| |
| private static final String WRAP_TO_SCRIPT = "WrapToScript"; |
| private static final String QUALIFIED_WRAP_TO_SCRIPT = "org.eclipse.ease.modules." + WRAP_TO_SCRIPT; |
| private static final Object SCRIPT_PARAMETER = "ScriptParameter"; |
| private static final Object QUALIFIED_SCRIPT_PARAMETER = "org.eclipse.ease.modules." + SCRIPT_PARAMETER; |
| |
| private static final String LINE_DELIMITER = "\n"; |
| |
| private final LinkProvider fLinkProvider; |
| private final ClassDoc fClazz; |
| private final IMemento[] fDependencies; |
| |
| private final Collection<String> fDocumentationErrors = new ArrayList<>(); |
| |
| public HTMLWriter(final ClassDoc clazz, final LinkProvider linkProvider, final IMemento[] dependencies) { |
| fClazz = clazz; |
| fLinkProvider = linkProvider; |
| fDependencies = dependencies; |
| } |
| |
| public String createContents(final String name) { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| addLine(buffer, "<html>"); |
| addLine(buffer, "<head>"); |
| addLine(buffer, " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>"); |
| addLine(buffer, " <link rel=\"stylesheet\" type=\"text/css\" href=\"../../org.eclipse.ease.help/help/css/modules_reference.css\" />"); |
| addLine(buffer, "</head>"); |
| addLine(buffer, "<body>"); |
| addText(buffer, " <div class=\"module\" title=\""); |
| addText(buffer, name); |
| addLine(buffer, " Module\">"); |
| |
| // header |
| addText(buffer, " <h1>"); |
| addText(buffer, name); |
| addLine(buffer, " Module</h1>"); |
| |
| // class description |
| addText(buffer, " <p class=\"description\">"); |
| final String classComment = fClazz.commentText(); |
| if ((classComment != null) && (!classComment.isEmpty())) |
| addText(buffer, fLinkProvider.insertLinks(fClazz, fClazz.commentText())); |
| |
| else |
| addDocumentationError("Missing class comment for " + fClazz.name()); |
| |
| addLine(buffer, "</p>"); |
| |
| // dependencies |
| addLine(buffer, createDependenciesSection()); |
| |
| // end title div |
| addLine(buffer, " </div>"); |
| |
| // constants |
| addLine(buffer, createConstantsSection()); |
| |
| // function overview |
| addLine(buffer, createOverviewSection()); |
| |
| // function details |
| addLine(buffer, createDetailSection()); |
| |
| addLine(buffer, "</body>"); |
| addLine(buffer, "</html>"); |
| |
| return buffer.toString(); |
| } |
| |
| private String createDependenciesSection() { |
| |
| if (fDependencies.length > 0) { |
| |
| final StringBuffer buffer = new StringBuffer(); |
| addLine(buffer, "\t<h3>Dependencies</h3>"); |
| addLine(buffer, "\t<p>This module depends on following other modules which will automatically be loaded.</p>"); |
| addLine(buffer, "\t<ul class=\"dependency\">"); |
| |
| for (final IMemento dependency : fDependencies) |
| addLine(buffer, "\t\t<li>{@module " + dependency.getString("module") + "}</li>"); |
| |
| addLine(buffer, "\t</ul>"); |
| |
| return fLinkProvider.insertLinks(fClazz, buffer.toString()); |
| } |
| |
| return ""; |
| } |
| |
| private Object createDetailSection() { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| addLine(buffer, "\t<h2>Methods</h2>"); |
| |
| for (final MethodDoc method : getExportedMethods()) { |
| // heading |
| addText(buffer, "\t<div class=\"command"); |
| if (isDeprecated(method)) |
| addText(buffer, " deprecated"); |
| addText(buffer, "\" data-method=\""); |
| addText(buffer, method.name()); |
| addLine(buffer, "\">"); |
| |
| addLine(buffer, |
| "\t\t<h3" + (isDeprecated(method) ? " class=\"deprecatedText\"" : "") + "><a id=\"" + method.name() + "\">" + method.name() + "</a></h3>"); |
| |
| final Parameter[] parameters = method.parameters(); |
| if (parameters.length > 0) { |
| // Add a link anchor to method name + parameters |
| final StringBuilder anchorBuilder = new StringBuilder(); |
| anchorBuilder.append(method.name()).append('-'); |
| for (final Parameter parameter : parameters) { |
| anchorBuilder.append(LinkProvider.removeGenericsTags(parameter.typeName())).append('-'); |
| } |
| addLine(buffer, "\t\t<a id=\"" + anchorBuilder.toString() + "\"></a>"); |
| } |
| |
| // synopsis |
| addLine(buffer, createSynopsis(method)); |
| |
| // main description |
| addLine(buffer, "\t\t<p class=\"description\">" + fLinkProvider.insertLinks(fClazz, getMethodComment(fClazz, method)) + "</p>"); |
| |
| if (isDeprecated(method)) { |
| String deprecationText = method.tags("deprecated")[0].text(); |
| if (deprecationText.isEmpty()) |
| deprecationText = "This method is deprecated and might be removed in future versions."; |
| |
| addLine(buffer, "\t\t<p class=\"warning\"><b>Deprecation warning:</b> " + fLinkProvider.insertLinks(fClazz, deprecationText) + "</p>"); |
| } |
| |
| // aliases |
| addLine(buffer, createAliases(method)); |
| |
| // parameters |
| addLine(buffer, createParametersArea(method)); |
| |
| // return value |
| addLine(buffer, createReturnValueArea(method)); |
| |
| // declared exceptions |
| addLine(buffer, createExceptionArea(method)); |
| |
| // examples |
| addLine(buffer, createExampleArea(method)); |
| |
| addLine(buffer, "\t</div>"); |
| } |
| |
| return buffer; |
| } |
| |
| private StringBuffer createExampleArea(final MethodDoc method) { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| final Tag[] tags = method.tags("scriptExample"); |
| if (tags.length > 0) { |
| addLine(buffer, " <dl class=\"examples\">"); |
| |
| for (final Tag tag : tags) { |
| final String fullText = tag.text(); |
| |
| // extract end position of example code |
| int pos = fullText.indexOf('('); |
| if (pos > 0) { |
| int open = 1; |
| for (int index = pos + 1; index < fullText.length(); index++) { |
| if (fullText.charAt(index) == ')') |
| open--; |
| else if (fullText.charAt(index) == '(') |
| open++; |
| |
| if (open == 0) { |
| pos = index + 1; |
| break; |
| } |
| } |
| } |
| final String codeText = (pos > 0) ? fullText.substring(0, pos) : fullText; |
| final String description = ((pos > 0) ? fullText.substring(pos).trim() : ""); |
| |
| addLine(buffer, " <dt>" + codeText + "</dt>"); |
| addText(buffer, " <dd class=\"description\">" + fLinkProvider.insertLinks(fClazz, description)); |
| addLine(buffer, "</dd>"); |
| } |
| |
| addLine(buffer, " </dl>"); |
| } |
| |
| return buffer; |
| } |
| |
| private StringBuffer createReturnValueArea(final MethodDoc method) { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| if (!"void".equals(method.returnType().qualifiedTypeName())) { |
| addText(buffer, " <p class=\"return\">"); |
| |
| final Tag[] tags = method.tags("return"); |
| if (tags.length > 0) { |
| if (tags[0].text().isEmpty()) |
| addDocumentationError("Missing return statement documentation for " + method.containingClass().name() + "." + method.name() + "()"); |
| |
| addText(buffer, fLinkProvider.insertLinks(fClazz, tags[0].text())); |
| } |
| |
| addLine(buffer, "</p>"); |
| } |
| |
| return buffer; |
| } |
| |
| private StringBuffer createParametersArea(final MethodDoc method) { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| if (method.parameters().length > 0) { |
| |
| addLine(buffer, " <dl class=\"parameters\">"); |
| |
| for (final Parameter parameter : method.parameters()) { |
| addLine(buffer, " <dt>" + parameter.name() + "</dt>"); |
| addText(buffer, " <dd class=\"description\" data-parameter=\"" + parameter.name() + "\">" |
| + fLinkProvider.insertLinks(fClazz, getParameterComment(method, parameter.name()))); |
| |
| final AnnotationDesc parameterAnnotation = getScriptParameterAnnotation(parameter); |
| if (parameterAnnotation != null) { |
| addText(buffer, "<span class=\"optional\"><b>Optional:</b> defaults to <<i>"); |
| for (final ElementValuePair pair : parameterAnnotation.elementValues()) { |
| if ("org.eclipse.ease.modules.ScriptParameter.defaultValue()".equals(pair.element().toString())) { |
| String defaultValue = pair.value().toString(); |
| |
| if ((!String.class.getName().equals(parameter.type().qualifiedTypeName())) && (defaultValue.length() > 2)) |
| // remove quotes from default |
| // value |
| defaultValue = defaultValue.substring(1, defaultValue.length() - 1); |
| |
| if (defaultValue.contains("org.eclipse.ease.modules.ScriptParameter.null")) |
| addText(buffer, "null"); |
| |
| else |
| addText(buffer, escapeText(defaultValue)); |
| } |
| } |
| addText(buffer, "</i>>.</span>"); |
| } |
| addLine(buffer, "</dd>"); |
| } |
| addLine(buffer, " </dl>"); |
| } |
| |
| return buffer; |
| } |
| |
| private StringBuffer createExceptionArea(final MethodDoc method) { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| if (method.thrownExceptionTypes().length > 0) { |
| |
| addLine(buffer, " <dl class=\"exceptions\">"); |
| |
| for (final Type exceptionType : method.thrownExceptionTypes()) { |
| addLine(buffer, " <dt>" + exceptionType.simpleTypeName() + "</dt>"); |
| addText(buffer, " <dd class=\"description\" data-exception=\"" + exceptionType.simpleTypeName() + "\">" |
| + fLinkProvider.insertLinks(fClazz, getExceptionComment(method, exceptionType))); |
| |
| addLine(buffer, "</dd>"); |
| } |
| |
| addLine(buffer, " </dl>"); |
| } |
| |
| return buffer; |
| } |
| |
| private String getExceptionComment(MethodDoc method, Type exceptionType) { |
| final String comment = extractComment(method, method1 -> { |
| |
| for (final ThrowsTag tag : method1.throwsTags()) { |
| if ((exceptionType.simpleTypeName().equals(tag.exceptionName())) || (exceptionType.typeName().equals(tag.exceptionName()))) |
| return tag.exceptionComment(); |
| } |
| |
| return ""; |
| }); |
| |
| if (comment.isEmpty()) |
| addDocumentationError( |
| "Missing exception documentation for " + method.containingClass().name() + "." + method.name() + "() - " + exceptionType.simpleTypeName()); |
| |
| return comment; |
| } |
| |
| private StringBuffer createAliases(final MethodDoc method) { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| final Collection<String> aliases = getFunctionAliases(method); |
| if (!aliases.isEmpty()) { |
| addLine(buffer, " <p class=\"synonyms\"><em>Alias:</em>"); |
| |
| for (final String alias : aliases) |
| addText(buffer, " " + alias + "(),"); |
| |
| // remove last comma |
| buffer.deleteCharAt(buffer.length() - 1); |
| |
| addLine(buffer, "</p>"); |
| } |
| |
| return buffer; |
| } |
| |
| private StringBuffer createSynopsis(final MethodDoc method) { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| addText(buffer, " <p class=\"synopsis\">"); |
| addText(buffer, fLinkProvider.createClassText(LinkProvider.resolveClassName(method.returnType().qualifiedTypeName(), fClazz))); |
| addText(buffer, " "); |
| addText(buffer, method.name()); |
| addText(buffer, "("); |
| for (final Parameter parameter : method.parameters()) { |
| final AnnotationDesc parameterAnnotation = getScriptParameterAnnotation(parameter); |
| if (parameterAnnotation != null) |
| addText(buffer, "["); |
| |
| addText(buffer, fLinkProvider.createClassText(LinkProvider.resolveClassName(parameter.type().qualifiedTypeName(), fClazz))); |
| addText(buffer, " "); |
| addText(buffer, parameter.name()); |
| if (parameterAnnotation != null) |
| addText(buffer, "]"); |
| |
| addText(buffer, ", "); |
| } |
| if (method.parameters().length > 0) |
| buffer.delete(buffer.length() - 2, buffer.length()); |
| |
| addText(buffer, ")"); |
| addLine(buffer, "</p>"); |
| |
| return buffer; |
| } |
| |
| private StringBuffer createOverviewSection() { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| addLine(buffer, " <h2>Method Overview</h2>"); |
| addLine(buffer, " <table class=\"functions\">"); |
| addLine(buffer, " <tr>"); |
| addLine(buffer, " <th>Method</th>"); |
| addLine(buffer, " <th>Description</th>"); |
| addLine(buffer, " </tr>"); |
| |
| final List<Overview> overview = new ArrayList<>(); |
| |
| for (final MethodDoc method : getExportedMethods()) { |
| overview.add(new Overview(method.name(), method.name(), getMethodComment(fClazz, method), isDeprecated(method))); |
| for (final String alias : getFunctionAliases(method)) |
| overview.add( |
| new Overview(alias, method.name(), "Alias for <a href=\"#" + method.name() + "\">" + method.name() + "</a>.", isDeprecated(method))); |
| } |
| |
| Collections.sort(overview); |
| |
| for (final Overview entry : overview) { |
| addLine(buffer, " <tr>"); |
| if (!entry.fDeprecated) { |
| addLine(buffer, " <td><a href=\"#" + entry.fLinkID + "\">" + entry.fTitle + "</a>()</td>"); |
| addLine(buffer, " <td>" + fLinkProvider.insertLinks(fClazz, getFirstSentence(entry.fDescription)) + "</td>"); |
| |
| } else { |
| addLine(buffer, " <td class=\"deprecatedText\"><a href=\"#" + entry.fLinkID + "\">" + entry.fTitle + "</a>()</td>"); |
| addLine(buffer, " <td class=\"deprecatedDescription\"><b>Deprecated:</b> " |
| + fLinkProvider.insertLinks(fClazz, getFirstSentence(entry.fDescription)) + "</td>"); |
| } |
| addLine(buffer, " </tr>"); |
| } |
| |
| addLine(buffer, " </table>"); |
| addLine(buffer, ""); |
| |
| return buffer; |
| } |
| |
| private String getMethodComment(ClassDoc baseClass, MethodDoc method) { |
| final String comment = extractComment(method, method1 -> method1.commentText()); |
| |
| if (comment.isEmpty()) |
| addDocumentationError("Missing comment for " + method.containingClass().name() + "." + method.name() + "()"); |
| |
| return comment; |
| } |
| |
| private StringBuffer createConstantsSection() { |
| final StringBuffer buffer = new StringBuffer(); |
| |
| final List<FieldDoc> fields = getExportedFields(); |
| if (!fields.isEmpty()) { |
| addLine(buffer, ""); |
| addLine(buffer, " <h2>Constants</h2>"); |
| addLine(buffer, " <table class=\"constants\">"); |
| addLine(buffer, " <tr>"); |
| addLine(buffer, " <th>Constant</th>"); |
| addLine(buffer, " <th>Description</th>"); |
| addLine(buffer, " </tr>"); |
| |
| for (final FieldDoc field : fields) { |
| addLine(buffer, "\t\t<tr>"); |
| |
| if (field.commentText().isEmpty()) |
| addDocumentationError("Field domentation missing for " + fClazz.name() + "." + field.name()); |
| |
| if (!isDeprecated(field)) { |
| addLine(buffer, " <td><a id=\"" + field.name() + "\">" + field.name() + "</a></td>"); |
| addLine(buffer, " <td class=\"description\" data-field=\"" + field.name() + "\">" |
| + fLinkProvider.insertLinks(fClazz, field.commentText()) + "</td>"); |
| |
| } else { |
| addLine(buffer, " <td><a id=\"" + field.name() + "\" class=\"deprecatedText\">" + field.name() + "</a></td>"); |
| addText(buffer, " <td>" + fLinkProvider.insertLinks(fClazz, field.commentText())); |
| String deprecationText = field.tags("deprecated")[0].text(); |
| if (deprecationText.isEmpty()) |
| deprecationText = "This constant is deprecated and might be removed in future versions."; |
| |
| addText(buffer, " <div class=\"warning\"><b>Deprecation warning:</b> " + fLinkProvider.insertLinks(fClazz, deprecationText) |
| + "</div>"); |
| addLine(buffer, "</td>"); |
| } |
| |
| addLine(buffer, " </tr>"); |
| } |
| |
| addLine(buffer, " </table>"); |
| addLine(buffer, ""); |
| } |
| |
| return buffer; |
| } |
| |
| private Collection<String> getFunctionAliases(final MethodDoc method) { |
| final Collection<String> aliases = new HashSet<>(); |
| final AnnotationDesc annotation = getWrapAnnotation(method); |
| if (annotation != null) { |
| for (final ElementValuePair pair : annotation.elementValues()) { |
| if ("alias".equals(pair.element().name())) { |
| String candidates = pair.value().toString(); |
| candidates = candidates.substring(1, candidates.length() - 1); |
| for (final String token : candidates.split("[,;]")) { |
| if (!token.trim().isEmpty()) |
| aliases.add(token.trim()); |
| } |
| } |
| } |
| } |
| |
| return aliases; |
| } |
| |
| private static String getFirstSentence(final String description) { |
| final int pos = description.indexOf('.'); |
| |
| return (pos > 0) ? description.substring(0, pos + 1) : description; |
| } |
| |
| private static void addText(final StringBuffer buffer, final Object text) { |
| buffer.append(text); |
| } |
| |
| private static void addLine(final StringBuffer buffer, final Object text) { |
| buffer.append(text).append(LINE_DELIMITER); |
| } |
| |
| private static boolean isDeprecated(final MethodDoc method) { |
| final Tag[] tags = method.tags("deprecated"); |
| return (tags != null) && (tags.length > 0); |
| } |
| |
| private static boolean isDeprecated(final FieldDoc field) { |
| final Tag[] tags = field.tags("deprecated"); |
| return (tags != null) && (tags.length > 0); |
| } |
| |
| private static AnnotationDesc getScriptParameterAnnotation(final Parameter parameter) { |
| for (final AnnotationDesc annotation : parameter.annotations()) { |
| if (isScriptParameterAnnotation(annotation)) |
| return annotation; |
| } |
| |
| return null; |
| } |
| |
| private static boolean isScriptParameterAnnotation(final AnnotationDesc annotation) { |
| return (QUALIFIED_SCRIPT_PARAMETER.equals(annotation.annotationType().qualifiedName())) |
| || (SCRIPT_PARAMETER.equals(annotation.annotationType().qualifiedName())); |
| } |
| |
| private String getParameterComment(final MethodDoc method, final String name) { |
| final String comment = extractComment(method, method1 -> { |
| for (final ParamTag paramTags : method1.paramTags()) { |
| if (name.equals(paramTags.parameterName())) |
| return paramTags.parameterComment(); |
| } |
| |
| return ""; |
| }); |
| |
| if (comment.isEmpty()) |
| addDocumentationError("Missing parameter documentation for " + method.containingClass().name() + "." + method.name() + "(" + name + ")"); |
| |
| return comment; |
| } |
| |
| private String extractComment(MethodDoc method, CommentExtractor extractor) { |
| String comment = extractor.extract(method); |
| if ((comment != null) && (!comment.isEmpty())) |
| return comment; |
| |
| // try to look up interfaces |
| for (final ClassDoc iface : method.containingClass().interfaces()) { |
| for (final MethodDoc ifaceMethod : iface.methods()) { |
| if (method.overrides(ifaceMethod)) { |
| comment = extractComment(ifaceMethod, extractor); |
| if ((comment != null) && (!comment.isEmpty())) |
| return comment; |
| } |
| } |
| } |
| |
| // not found, retry with super class |
| final ClassDoc parent = method.containingClass().superclass(); |
| if (parent != null) { |
| for (final MethodDoc superMethod : parent.methods()) { |
| if (method.overrides(superMethod)) |
| return (extractComment(superMethod, extractor)); |
| } |
| } |
| |
| return ""; |
| } |
| |
| private List<MethodDoc> getExportedMethods() { |
| final List<MethodDoc> methods = new ArrayList<>(); |
| final boolean hasAnnotation = hasWrapToScriptAnnotation(fClazz); |
| |
| ClassDoc clazzDoc = fClazz; |
| while ((clazzDoc != null) && (!Object.class.getName().equals(clazzDoc.qualifiedName()))) { |
| for (final MethodDoc method : clazzDoc.methods()) { |
| if ((!hasAnnotation) || (getWrapAnnotation(method) != null)) |
| methods.add(method); |
| } |
| |
| clazzDoc = clazzDoc.superclass(); |
| } |
| |
| // sort methods alphabetically |
| Collections.sort(methods, (o1, o2) -> o1.name().compareTo(o2.name())); |
| |
| return methods; |
| } |
| |
| private List<FieldDoc> getExportedFields() { |
| final List<FieldDoc> fields = new ArrayList<>(); |
| |
| final boolean hasAnnotation = hasWrapToScriptAnnotation(fClazz); |
| |
| final ArrayList<ClassDoc> candidates = new ArrayList<>(); |
| candidates.add(fClazz); |
| while (!candidates.isEmpty()) { |
| final ClassDoc clazzDoc = candidates.remove(0); |
| |
| for (final FieldDoc field : clazzDoc.fields()) { |
| if ((!hasAnnotation) || (getWrapAnnotation(field) != null)) |
| fields.add(field); |
| } |
| |
| // add interfaces |
| candidates.addAll(Arrays.asList(clazzDoc.interfaces())); |
| |
| // add super class/interface |
| final ClassDoc nextCandidate = clazzDoc.superclass(); |
| if ((nextCandidate != null) && (!Object.class.getName().equals(nextCandidate.qualifiedName()))) |
| candidates.add(nextCandidate); |
| } |
| |
| // sort fields alphabetically |
| Collections.sort(fields, (o1, o2) -> o1.name().compareTo(o2.name())); |
| |
| return fields; |
| } |
| |
| private static boolean hasWrapToScriptAnnotation(ClassDoc clazzDoc) { |
| while (clazzDoc != null) { |
| for (final MethodDoc method : clazzDoc.methods()) { |
| if (getWrapAnnotation(method) != null) |
| return true; |
| } |
| |
| for (final FieldDoc field : clazzDoc.fields()) { |
| if (getWrapAnnotation(field) != null) |
| return true; |
| } |
| |
| clazzDoc = clazzDoc.superclass(); |
| } |
| |
| return false; |
| } |
| |
| private static AnnotationDesc getWrapAnnotation(final ProgramElementDoc method) { |
| for (final AnnotationDesc annotation : method.annotations()) { |
| if (isWrapToScriptAnnotation(annotation)) |
| return annotation; |
| } |
| |
| return null; |
| } |
| |
| private static boolean isWrapToScriptAnnotation(final AnnotationDesc annotation) { |
| return (QUALIFIED_WRAP_TO_SCRIPT.equals(annotation.annotationType().qualifiedName())) |
| || (WRAP_TO_SCRIPT.equals(annotation.annotationType().qualifiedName())); |
| } |
| |
| public static String escapeText(String text) { |
| return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">"); |
| } |
| |
| public Collection<String> getDocumentationErrors() { |
| return fDocumentationErrors; |
| } |
| |
| private void addDocumentationError(String message) { |
| fDocumentationErrors.add(message); |
| } |
| } |