Standard Libraries

/** --- Javadoc ---

   Classes to represent Javadoc documentation.
*/

import semmle.code.Location
import Element

/** A Javadoc parent is an element whose child can be some Javadoc documentation. */
class JavadocParent extends @javadocParent {
  /** get a piece of documentation attached to this parent */
 JavadocElement getAChild() { result.getParent() = this }

  /** get the index'th piece of documentation for this parent */
 JavadocElement getChild(int index) {
   result = this.getAChild() and result.getIndex() = index
 }

  /** get a piece of documentation whose tag name is name */
 JavadocTag getATag(string name) {
   result = this.getAChild() and result.getTagName() = name
 }

 /** printable representation */
 /*abstract*/ string toString() { result = "Javadoc" }
}

/** A Javadoc comment */
class Javadoc extends JavadocParent, @javadoc {
 
  /** length of this comment in lines */
  int getNumberOfLines() {
    result = this.getLocation().getNumberOfCommentLines()
  }

  /** return value of @version tag */
  string getVersion() {
    result = this.getATag("@version").getChild(0).toString()
  }

  /** return value of @author tag */
  string getAuthor() {
    result = this.getATag("@author").getChild(0).toString()
  }

  /** printable representation of comment */
  string toString() {
    if count(this.getAChild()) = 1 then 
      result = "/** " + this.getChild(0).toString() + " */"
    else 
      result = "/** " + this.getChild(0).toString() + " ...*/"
  }
  
  /** source location for this element */
  Location getLocation() { hasLocation(this,result) }

  /** URL for this element */
  string getURL() { result = this.getLocation().getURL() or
                    (not exists(this.getLocation().getURL()) and
                         result="") }

  /** icon to display */
  string getIconPath() { result = "icons/javadoc.png" }
}

/** A documentable element that can have an attached Javadoc comment */
class Documentable extends Element, @member {
  /** the Javadoc comment attached to this element */
  Javadoc getJavadoc() { hasJavadoc(this,result,_) }

  /** this element's author */
  string getAuthor() {
   result = this.getJavadoc().getAuthor()
  }
}

/** Common super class for Javadoc elements (either tags or text) */
class JavadocElement extends @javadocElement {
  /** the element's parent */
  JavadocParent getParent() {
    javadocTag(this,_,result,_,_) or javadocText(this,_,result,_,_)
  }

  /** the element's index as a child of its parent */
  int getIndex() {
    javadocTag(this,_,_,result,_) or javadocText(this,_,_,result,_)
  }

  /** printable representation */
  /*abstract*/ string toString() { result = "Javadoc element" }
  
  /** source location for this element */
  Location getLocation() { hasLocation(this,result) }

  /** URL for this element */
  string getURL() { result = this.getLocation().getURL() or
                    (not exists(this.getLocation().getURL()) and
                         result="") }

  /** icon to display */
  string getIconPath() { result = "icons/javadoc.png" }
}

/** A Javadoc tag */
class JavadocTag extends JavadocElement, JavadocParent, @javadocTag {
  /** the tag name */
  string getTagName() { javadocTag(this,result,_,_,_) }

  /** printable representation */
  string toString() { result = this.getTagName() }
}

/** A @param tag */
class ParamTag extends JavadocTag {
  ParamTag() { this.getTagName() = "@param" }

  /** get the parameter name */
  string getParamName() { result = this.getChild(0).toString() }

  /** get the parameter documentation */
  string getText() { result = this.getChild(1).toString() }
}

/** An @author tag */
class AuthorTag extends JavadocTag {
  AuthorTag() { this.getTagName() = "@author" }

  /** get the author name */
  string getAuthorName() { result = this.getChild(0).toString() }
}

/** A piece of Javadoc text */
class JavadocText extends JavadocElement, @javadocText {
  /** get the text */
  string getText() { javadocText(this,result,_,_,_) }

  /** printable representation */
  string toString() { result = this.getText() }
}