duke@1: /*
jjg@1490: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1: *
duke@1: * This code is free software; you can redistribute it and/or modify it
duke@1: * under the terms of the GNU General Public License version 2 only, as
ohair@554: * published by the Free Software Foundation. Oracle designates this
duke@1: * particular file as subject to the "Classpath" exception as provided
ohair@554: * by Oracle in the LICENSE file that accompanied this code.
duke@1: *
duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1: * version 2 for more details (a copy is included in the LICENSE file that
duke@1: * accompanied this code).
duke@1: *
duke@1: * You should have received a copy of the GNU General Public License version
duke@1: * 2 along with this work; if not, write to the Free Software Foundation,
duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1: *
ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554: * or visit www.oracle.com if you need additional information or have any
ohair@554: * questions.
duke@1: */
duke@1:
duke@1: package com.sun.tools.javadoc;
duke@1:
jjg@911: import java.io.DataInputStream;
jjg@1357: import java.io.IOException;
duke@1: import java.io.InputStream;
duke@1: import java.text.CollationKey;
jjg@1357: import java.util.regex.Matcher;
jjg@1357: import java.util.regex.Pattern;
jjg@1357:
jjg@197: import javax.tools.FileObject;
jjg@197:
jjg@197: import com.sun.javadoc.*;
jjg@1443: import com.sun.source.util.TreePath;
jjg@1443: import com.sun.tools.javac.tree.JCTree;
jjg@1443: import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
duke@1: import com.sun.tools.javac.util.Position;
duke@1:
duke@1: /**
duke@1: * abstract base class of all Doc classes. Doc item's are representations
duke@1: * of java language constructs (class, package, method,...) which have
duke@1: * comments and have been processed by this run of javadoc. All Doc items
duke@1: * are unique, that is, they are == comparable.
duke@1: *
jjg@1359: *
This is NOT part of any supported API.
jjg@1359: * If you write code that depends on this, you do so at your own risk.
jjg@1359: * This code and its internal interfaces are subject to change or
jjg@1359: * deletion without notice.
jjg@1359: *
duke@1: * @since 1.2
duke@1: * @author Robert Field
duke@1: * @author Atul M Dambalkar
duke@1: * @author Neal Gafter (rewrite)
duke@1: */
jjg@197: public abstract class DocImpl implements Doc, Comparable {
duke@1:
duke@1: /**
duke@1: * Doc environment
duke@1: */
duke@1: protected final DocEnv env; //### Rename this everywhere to 'docenv' ?
duke@1:
duke@1: /**
jjg@1443: * Back pointer to the tree node for this doc item.
jjg@1443: * May be null if there is no associated tree.
jjg@1443: */
jjg@1443: protected TreePath treePath;
jjg@1443:
jjg@1443: /**
duke@1: * The complex comment object, lazily initialized.
duke@1: */
duke@1: private Comment comment;
duke@1:
duke@1: /**
duke@1: * The cached sort key, to take care of Natural Language Text sorting.
duke@1: */
duke@1: private CollationKey collationkey = null;
duke@1:
duke@1: /**
duke@1: * Raw documentation string.
duke@1: */
duke@1: protected String documentation; // Accessed in PackageDocImpl, RootDocImpl
duke@1:
duke@1: /**
duke@1: * Cached first sentence.
duke@1: */
duke@1: private Tag[] firstSentence;
duke@1:
duke@1: /**
duke@1: * Cached inline tags.
duke@1: */
duke@1: private Tag[] inlineTags;
duke@1:
duke@1: /**
duke@1: * Constructor.
duke@1: */
jjg@1443: DocImpl(DocEnv env, TreePath treePath) {
jjg@1443: this.treePath = treePath;
jjg@1443: this.documentation = getCommentText(treePath);
duke@1: this.env = env;
duke@1: }
duke@1:
jjg@1443: private static String getCommentText(TreePath p) {
jjg@1443: if (p == null)
jjg@1443: return null;
jjg@1443:
jjg@1443: JCCompilationUnit topLevel = (JCCompilationUnit) p.getCompilationUnit();
jjg@1443: JCTree tree = (JCTree) p.getLeaf();
jjg@1443: return topLevel.docComments.getCommentText(tree);
jjg@1443: }
jjg@1443:
duke@1: /**
duke@1: * So subclasses have the option to do lazy initialization of
duke@1: * "documentation" string.
duke@1: */
ksrini@1051: protected String documentation() {
duke@1: if (documentation == null) documentation = "";
duke@1: return documentation;
duke@1: }
duke@1:
duke@1: /**
duke@1: * For lazy initialization of comment.
duke@1: */
duke@1: Comment comment() {
duke@1: if (comment == null) {
jjg@1490: String d = documentation();
jjg@1490: if (env.doclint != null
jjg@1490: && treePath != null
jjg@1490: && d.equals(getCommentText(treePath))) {
jjg@1490: env.doclint.scan(treePath);
jjg@1490: }
jjg@1490: comment = new Comment(this, d);
duke@1: }
duke@1: return comment;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return the text of the comment for this doc item.
duke@1: * TagImpls have been removed.
duke@1: */
duke@1: public String commentText() {
duke@1: return comment().commentText();
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return all tags in this Doc item.
duke@1: *
duke@1: * @return an array of TagImpl containing all tags on this Doc item.
duke@1: */
duke@1: public Tag[] tags() {
duke@1: return comment().tags();
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return tags of the specified kind in this Doc item.
duke@1: *
duke@1: * @param tagname name of the tag kind to search for.
duke@1: * @return an array of TagImpl containing all tags whose 'kind()'
duke@1: * matches 'tagname'.
duke@1: */
duke@1: public Tag[] tags(String tagname) {
duke@1: return comment().tags(tagname);
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return the see also tags in this Doc item.
duke@1: *
jjg@1326: * @return an array of SeeTag containing all @see tags.
duke@1: */
duke@1: public SeeTag[] seeTags() {
duke@1: return comment().seeTags();
duke@1: }
duke@1:
duke@1: public Tag[] inlineTags() {
duke@1: if (inlineTags == null) {
duke@1: inlineTags = Comment.getInlineTags(this, commentText());
duke@1: }
duke@1: return inlineTags;
duke@1: }
duke@1:
duke@1: public Tag[] firstSentenceTags() {
duke@1: if (firstSentence == null) {
duke@1: //Parse all sentences first to avoid duplicate warnings.
duke@1: inlineTags();
duke@1: try {
duke@1: env.setSilent(true);
duke@1: firstSentence = Comment.firstSentenceTags(this, commentText());
duke@1: } finally {
duke@1: env.setSilent(false);
duke@1: }
duke@1: }
duke@1: return firstSentence;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Utility for subclasses which read HTML documentation files.
duke@1: */
jjg@197: String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException {
jjg@911: byte[] filecontents = new byte[input.available()];
jjg@911: try {
jjg@911: DataInputStream dataIn = new DataInputStream(input);
jjg@911: dataIn.readFully(filecontents);
jjg@911: } finally {
jjg@911: input.close();
jjg@911: }
duke@1: String encoding = env.getEncoding();
duke@1: String rawDoc = (encoding!=null)
duke@1: ? new String(filecontents, encoding)
duke@1: : new String(filecontents);
jjg@911: Pattern bodyPat = Pattern.compile("(?is).*]*>(.*)
duke@1: * Default is name().
duke@1: */
duke@1: CollationKey generateKey() {
duke@1: String k = name();
duke@1: // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
duke@1: return env.doclocale.collator.getCollationKey(k);
duke@1: }
duke@1:
duke@1: /**
duke@1: * Returns a string representation of this Doc item.
duke@1: */
jjg@911: @Override
duke@1: public String toString() {
duke@1: return qualifiedName();
duke@1: }
duke@1:
duke@1: /**
duke@1: * Returns the name of this Doc item.
duke@1: *
duke@1: * @return the name
duke@1: */
duke@1: public abstract String name();
duke@1:
duke@1: /**
duke@1: * Returns the qualified name of this Doc item.
duke@1: *
duke@1: * @return the name
duke@1: */
duke@1: public abstract String qualifiedName();
duke@1:
duke@1: /**
duke@1: * Compares this Object with the specified Object for order. Returns a
duke@1: * negative integer, zero, or a positive integer as this Object is less
duke@1: * than, equal to, or greater than the given Object.
duke@1: *
duke@1: * Included so that Doc item are java.lang.Comparable.
duke@1: *
jjg@1358: * @param obj the {@code Object} to be compared.
duke@1: * @return a negative integer, zero, or a positive integer as this Object
duke@1: * is less than, equal to, or greater than the given Object.
duke@1: * @exception ClassCastException the specified Object's type prevents it
duke@1: * from being compared to this Object.
duke@1: */
duke@1: public int compareTo(Object obj) {
duke@1: // System.out.println("COMPARE \"" + this + "\" to \"" + obj + "\" = " + key().compareTo(((DocImpl)obj).key()));
duke@1: return key().compareTo(((DocImpl)obj).key());
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item a field? False until overridden.
duke@1: *
duke@1: * @return true if it represents a field
duke@1: */
duke@1: public boolean isField() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item an enum constant? False until overridden.
duke@1: *
duke@1: * @return true if it represents an enum constant
duke@1: */
duke@1: public boolean isEnumConstant() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item a constructor? False until overridden.
duke@1: *
duke@1: * @return true if it represents a constructor
duke@1: */
duke@1: public boolean isConstructor() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item a method (but not a constructor or annotation
duke@1: * type element)?
duke@1: * False until overridden.
duke@1: *
duke@1: * @return true if it represents a method
duke@1: */
duke@1: public boolean isMethod() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item an annotation type element?
duke@1: * False until overridden.
duke@1: *
duke@1: * @return true if it represents an annotation type element
duke@1: */
duke@1: public boolean isAnnotationTypeElement() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item a interface (but not an annotation type)?
duke@1: * False until overridden.
duke@1: *
duke@1: * @return true if it represents a interface
duke@1: */
duke@1: public boolean isInterface() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item a exception class? False until overridden.
duke@1: *
duke@1: * @return true if it represents a exception
duke@1: */
duke@1: public boolean isException() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item a error class? False until overridden.
duke@1: *
duke@1: * @return true if it represents a error
duke@1: */
duke@1: public boolean isError() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item an enum type? False until overridden.
duke@1: *
duke@1: * @return true if it represents an enum type
duke@1: */
duke@1: public boolean isEnum() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item an annotation type? False until overridden.
duke@1: *
duke@1: * @return true if it represents an annotation type
duke@1: */
duke@1: public boolean isAnnotationType() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item an ordinary class (i.e. not an interface,
duke@1: * annotation type, enumeration, exception, or error)?
duke@1: * False until overridden.
duke@1: *
duke@1: * @return true if it represents an ordinary class
duke@1: */
duke@1: public boolean isOrdinaryClass() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Is this Doc item a class
duke@1: * (and not an interface or annotation type)?
duke@1: * This includes ordinary classes, enums, errors and exceptions.
duke@1: * False until overridden.
duke@1: *
duke@1: * @return true if it represents a class
duke@1: */
duke@1: public boolean isClass() {
duke@1: return false;
duke@1: }
duke@1:
duke@1: /**
duke@1: * return true if this Doc is include in the active set.
duke@1: */
duke@1: public abstract boolean isIncluded();
duke@1:
duke@1: /**
duke@1: * Return the source position of the entity, or null if
duke@1: * no position is available.
duke@1: */
duke@1: public SourcePosition position() { return null; }
duke@1: }