| package org.codehaus.groovy.tools |
| |
| import groovy.xml.StreamingMarkupBuilder |
| |
| import java.io.File |
| |
| import com.thoughtworks.qdox.JavaDocBuilder |
| import com.thoughtworks.qdox.model.JavaSource |
| import com.thoughtworks.qdox.model.JavaClass |
| import com.thoughtworks.qdox.model.JavaMethod |
| import com.thoughtworks.qdox.model.JavaParameter |
| import com.thoughtworks.qdox.model.Type |
| import java.util.*; |
| |
| |
| /** |
| * Generate documentation about the methods provided by the Groovy Development Kit |
| * enhancing the standard JDK classes. |
| * |
| * @author Guillaume Laforge, John Wilson |
| */ |
| class DocGenerator |
| { |
| File file |
| File outputFile |
| JavaDocBuilder builder |
| |
| DocGenerator(File fileToParse, File outputFile) |
| { |
| this.file = fileToParse |
| this.outputFile = outputFile |
| } |
| |
| /** |
| * Parse the DefaultGroovyMethods class to build a graph representing the structure of the class, |
| * with its methods, javadoc comments and tags. |
| */ |
| private void parse() |
| { |
| def reader = file.newReader() |
| builder = new JavaDocBuilder() |
| |
| builder.addSource(reader) |
| } |
| |
| /** |
| * Builds an HTML page from the structure of DefaultGroovyMethods. |
| */ |
| |
| def generate() { |
| parse() |
| |
| def sources = builder.getSources() |
| |
| def firstSource = sources[0] |
| def classes = firstSource.getClasses() |
| def groovyMeth = classes[0] |
| |
| // categorize all groovy methods per core JDK class to which it applies |
| def jdkEnhancedClasses = [:] |
| def methods = groovyMeth.getMethods() |
| |
| def start = System.currentTimeMillis(); |
| for (method in methods) { |
| if (method.isPublic() && method.isStatic()) { |
| def parameters = method.getParameters() |
| def jdkClass = parameters[0].getType().toString() |
| |
| if (jdkEnhancedClasses.containsKey(jdkClass)) { |
| List l = jdkEnhancedClasses[jdkClass]; |
| l.add(method) |
| } |
| else |
| jdkEnhancedClasses[jdkClass] = [method] |
| } |
| } |
| //start = System.currentTimeMillis(); |
| println " added classes in ${System.currentTimeMillis() - start} ms" |
| |
| def headElement = { head { |
| mkp.comment 'generated by Groovy using Streaming Markup' |
| title 'GDK : Groovy methods' |
| style(['type':'text/css'], ' @import url("./style/maven-base.css"); ') |
| style(['type':'text/css'], ' @import url("http://codehaus.org/codehaus-style.css"); ') |
| } |
| } |
| |
| def sortedClasses = new TreeSet(jdkEnhancedClasses.keySet()) |
| |
| def ind = 0 |
| def cellsInRow = 4 |
| // Split sortedClasses into list of 4-element lists |
| def rowList = sortedClasses.inject([]) { list, item -> |
| if (ind++ % cellsInRow == 0) |
| list << [item] |
| else |
| list[-1] << item |
| return list |
| } |
| |
| def classLinks = { mkp.yield { |
| def classCounter = 0 |
| table(width:'100%') { |
| tr { |
| th(colspan:"${cellsInRow}", "Groovy JDK classes") |
| } |
| for (row in rowList) { |
| if (row.size() < cellsInRow) { |
| (cellsInRow - row.size()).times { row << "" } |
| } |
| tr { |
| for (className in row) { |
| td(width:'25%') { |
| a(href:"#cls${classCounter}", "${className}") |
| } |
| classCounter++; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| def summary = { mkp.yield { |
| def counter = 0 |
| def classCounter = 0 |
| |
| // lets iterate in sorted class name order |
| for (String className in sortedClasses) { |
| |
| p { a(name:"cls${classCounter}") } |
| b className |
| classCounter++ |
| |
| def listOfMethods = jdkEnhancedClasses[className] |
| listOfMethods.sort{ it.name } |
| |
| table(width:'100%') { |
| for (JavaMethod meth in listOfMethods) { |
| counter++ |
| |
| tr { |
| td(width:'30%') { |
| mkp.yield getReturnType(meth) |
| } |
| td(width:'70%') { |
| a(href:"#meth${counter}") { |
| mkp.yield meth.getName() |
| } |
| mkp.yield "(${getParametersDecl(meth)})" |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| def details = { mkp.yield { |
| def counter = 0 |
| |
| for (className in sortedClasses) { |
| |
| h2 className |
| |
| def listOfMethods = jdkEnhancedClasses[className] |
| listOfMethods.sort{ it.name } |
| |
| for (JavaMethod meth in listOfMethods) { |
| counter++ |
| |
| a(name:"meth${counter}") |
| |
| p { |
| b "${getReturnType(meth)} ${meth.getName()}(${getParametersDecl(meth)})" |
| } |
| |
| ul { |
| // |
| // Java comments can contain markup - pass it through as is |
| // |
| mkp.yieldUnescaped "${getComment(meth)} " |
| |
| ul { |
| def params = meth.getTags() |
| def count = 0 |
| |
| for (param in params) { |
| if (count++ != 0 && param.getName() != "throws" && param.getName() != "return") { |
| li "${param.getName()} ${param.getValue()}" |
| } |
| } |
| |
| def returnType = getReturnType(meth) |
| |
| if (returnType != "") { |
| if (returnType != "void") { |
| li { |
| b "returns" |
| mkp.yield ": ${returnType}" |
| |
| def returnTag = meth.getTagByName("return") |
| |
| if (returnTag != null) { |
| mkp.yield " - " |
| i returnTag.getValue() |
| } |
| } |
| } |
| |
| def exceptions = meth.getExceptions() |
| |
| for (ex in exceptions) { |
| if (ex != null) { |
| li { |
| b "throws" |
| mkp.yield ": ${ex}" |
| |
| def exMsg = meth.getTagByName("throws") |
| |
| if (exMsg != null) { |
| mkp.yield " - " |
| i exMsg.getValue() |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| def bodyElement = { body { |
| h1 'Groovy JDK methods' |
| p 'New methods added to the JDK to make it more groovy.' |
| mkp.yield classLinks |
| mkp.yield summary |
| mkp.yield details |
| } |
| } |
| |
| outputFile.getParentFile().mkdirs() |
| outputFile.newPrintWriter() << new StreamingMarkupBuilder().bind{ html { |
| mkp.yield headElement |
| mkp.yield bodyElement |
| } |
| } |
| } |
| |
| /** |
| * Retrieves a String representing the return type |
| */ |
| private getReturnType(method) |
| { |
| def returnType = method.getReturns() |
| |
| if (returnType != null) { |
| return returnType.toString() |
| } else { |
| return "" |
| } |
| } |
| |
| /** |
| * Retrieve a String representing the declaration of the parameters of the method passed as parameter. |
| * |
| * @param method a method |
| * @return the declaration of the method (long version) |
| */ |
| private getParametersDecl(method) |
| { |
| getParameters(method).collect{ "${it.getType()} ${it.getName()}" }.join(", ") |
| } |
| |
| /** |
| * Retrieve the parameters of the method. |
| * |
| * @param method a method |
| * @return a list of parameters without the first one |
| */ |
| private getParameters(method) |
| { |
| if (method.getParameters().size() > 1) |
| return method.getParameters().toList()[1..-1] |
| else |
| return [] |
| } |
| |
| /** |
| * Retrieve the JavaDoc comment associated with the method passed as parameter. |
| * |
| * @param method a method |
| * @return the JavaDoc comment associated with this method |
| */ |
| private getComment(method) |
| { |
| def ans = method.getComment() |
| if (ans == null) return "" |
| return ans |
| } |
| |
| /** |
| * Main entry point. |
| */ |
| static void main(args) |
| { |
| def defaultGroovyMethodSource = |
| //new File("D:/cvs-groovy/groovy/groovy-core/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java") |
| new File("src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java") |
| def outFileName = |
| //new File("D:/cvs-groovy/groovy/groovy-core/target/html/groovy-jdk.html") |
| new File("target/html/groovy-jdk.html") |
| |
| def start = System.currentTimeMillis(); |
| |
| def docGen = new DocGenerator(defaultGroovyMethodSource, outFileName) |
| docGen.generate() |
| |
| def end = System.currentTimeMillis(); |
| |
| println "Done. in ${end - start} millis" |
| |
| } |
| } |