Mendokumentasikan Groovy dengan Groovydoc

Groovydoc diperkenalkan pada tahun 2007 untuk menyediakan Groovy apa yang disediakan Javadoc untuk Java. Groovydoc digunakan untuk menghasilkan dokumentasi API untuk kelas Groovy dan Java yang menyusun bahasa Groovy. Dalam siaran ini, saya ingin memanggil Groovydoc melalui baris perintah dan melalui tugas semut yang disediakan Groovy.

Kod Sumber Groovy dan Java dengan Komen Groovydoc / Javadoc

Saya akan menggunakan versi dan skrip Groovy yang disesuaikan untuk pertama kalinya yang diperkenalkan dalam catatan blog saya Easy Groovy Logger Injection dan Log Guarding untuk menunjukkan Groovydoc. Skrip Groovy utama dan kelas Groovy dari jawatan itu telah diubah suai untuk memasukkan lebih banyak komen gaya Javadoc untuk menunjukkan Groovydoc dalam tindakan yang lebih baik. Skrip yang disemak dan kelas yang berkaitan ditunjukkan dalam senarai kod seterusnya.

demoGroovyLogTransformation.groovy

#!/usr/bin/env groovy /** * demoGroovyLogTransformation.groovy * * Grab SLF4J, Log4j, and Apache Commons Logging dependencies using @Grab and * demonstrate Groovy 1.8's injected logging handles. * * //marxsoftware.blogspot.com/2011/05/easy-groovy-logger-injection-an... */ // No need to "grab" java.util.logging: it's part of the JDK! /* * Specifying 'slf4j-simple' rather than 'slf4j-api' to avoid the error * "Failed to load class "org.slf4j.impl.StaticLoggerBinder" that is caused by * specifying no or more than one of the actual logging binding libraries to * be used (see //www.slf4j.org/codes.html#StaticLoggerBinder). One should * be selected from 'slf4j-nop', 'slf4j-simple', 'slf4j-log4j12.jar', * 'slf4j-jdk14', or 'logback-classic'. An example of specifying the SLF4J * dependency via @Grab is available at * //mvnrepository.com/artifact/org.slf4j/slf4j-api/1.6.1. */ @Grab(group='org.slf4j', module="slf4j-simple", version="1.6.1") /* * An example of specifying the Log4j dependency via @Grab is at * //mvnrepository.com/artifact/log4j/log4j/1.2.16. */ @Grab(group='log4j', module="log4j", version="1.2.16") /* * An example of specifying the Apache Commons Logging dependency via @Grab is at * //mvnrepository.com/artifact/commons-logging/commons-logging-api/1..... */ @Grab(group='commons-logging', module="commons-logging-api", version="1.1") /* * Run the tests... */ int headerSize = 79 printHeader("java.util.logger", headerSize) def javaUtilLogger = new JavaUtilLoggerClass() printHeader("Log4j", headerSize) def log4jLogger = new Log4jLoggerClass() printHeader("SLF4j", headerSize) def slf4jLogger = new Slf4jLoggerClass() printHeader("Apache Commons", headerSize) def commonsLogger = new ApacheCommonsLoggerClass() /** * Print header with provided text. * * @param textForHeader Text to be included in the header. * @param sizeOfHeader Number of characters in each row of header. */ def printHeader(final String textForHeader, final int sizeOfHeader) { println "=".multiply(sizeOfHeader) println "= ${textForHeader}${' '.multiply(sizeOfHeader-textForHeader.size()-4)}=".multiply(sizeOfHeader) } 

JavaUtilLoggerClass.groovy

import groovy.util.logging.Log /** * Sample Groovy class using {@code @Log} to inject java.util.logging logger * into the class. */ @Log class JavaUtilLoggerClass { /** * Constructor. */ public JavaUtilLoggerClass() { println "\njava.util.logging (${log.name}: ${log.class}):" log.info "${this.printAndReturnValue(1)}" log.finer "${this.printAndReturnValue(2)}" } /** * Print provided value and then return it as part of String indicating part * of JDK's java.util.logging. * * @param newValue Value to be printed and included in return String. * @return String indicating newValue and JDK for java.util.logging. */ public String printAndReturnValue(int newValue) { println "JDK: Print method invoked for ${newValue}" return "JDK: ${newValue}" } } 

Log4jLoggerClass.groovy

import groovy.util.logging.Log4j import org.apache.log4j.Level /** * Sample Groovy class using {@code @Log4j} to inject Log4j logger * into the class. */ @Log4j class Log4jLoggerClass { /** * Constructor. */ Log4jLoggerClass() { // It is necessary to set logging level here because default is FATAL and // we are not using a Log4j external configuration file in this example log.setLevel(Level.INFO) println "\nLog4j Logging (${log.name}: ${log.class}):" log.info "${this.printAndReturnValue(1)}" log.debug "${this.printAndReturnValue(2)}" } /** * Print provided value and then return it as part of String indicating part * of Log4j. * * @param newValue Value to be printed and included in return String. * @return String indicating newValue and Log4j. */ public String printAndReturnValue(int newValue) { println "Log4j: Print method invoked for ${newValue}" return "Log4j: ${newValue}" } } 

Slf4jLoggerClass.groovy

import groovy.util.logging.Slf4j /** * Sample Groovy class using {@code @Slf4j} to inject Simple Logging Facade for * Java (SLF4J) logger into the class. */ @Slf4j class Slf4jLoggerClass { /** * Constructor. */ public Slf4jLoggerClass() { println "\nSLF4J Logging (${log.name}: ${log.class}):" log.info "${this.printAndReturnValue(1)}" log.debug "${this.printAndReturnValue(2)}" } /** * Print provided value and then return it as part of String indicating part * of SLF4J logging. * * @param newValue Value to be printed and included in return String. * @return String indicating newValue and SLF4J. */ public String printAndReturnValue(int newValue) { println "SLF4J: Print method invoked for ${newValue}" return "SLF4J: ${newValue}" } } 

ApacheCommonsLoggerClass.groovy

import groovy.util.logging.Commons /** * Sample Groovy class using {@code @Commons} to inject Apache Commons logger * into the class. */ @Commons class ApacheCommonsLoggerClass { /** * Constructor. */ public ApacheCommonsLoggerClass() { println "\nApache Commons Logging (${log.name}: ${log.class}):" log.info "${this.printAndReturnValue(1)}" log.debug "${this.printAndReturnValue(2)}" } /** * Print provided value and then return it as part of String indicating part * of Apache Commons Logging. * * @param newValue Value to be printed and included in return String. * @return String indicating newValue and Apache Commons Logging. */ public String printAndReturnValue(int newValue) { println "Commons: Print method invoked for ${newValue}" return "Commons: ${newValue}" } } 

Sebagai tambahan kepada skrip dan kelas Groovy di atas, saya juga menggunakan kelas Java baru di sini untuk menggambarkan bahawa Groovydoc berfungsi pada kelas Java dan juga kelas Groovy. Kelas Java tidak banyak berbuat selain memberikan komen Javadoc untuk diproses oleh Groovydoc.

DoNothingClass.java

/** * Class that does not do anything, but is here to be a Java class run through * groovydoc. */ public class DoNothingClass { /** * Simple method that returns literal "Hello _addressee_!" string where * _addressee_ is the name provided to this method. * * @param addressee Name for returned salutation to be addressed to. * @return "Hello!" */ public String sayHello(final String addressee) { return "Hello, " + addressee; } /** * Main executable function. */ public static void main(final String[] arguments) { final DoNothingClass me = new DoNothingClass(); me.sayHello("Dustin"); } /** * Provide String representation of this object. * * @return String representation of me. */ @Override public String toString() { return "Hello!"; } } 

Menjalankan Groovydoc di Command Line

Dengan skrip Groovy, kelas Groovy, dan kelas Java yang ditunjukkan di atas sudah siap, inilah masanya untuk mengalihkan perhatian untuk menjalankan Groovydoc terhadap kelas dan skrip ini. Seperti halnya Javadoc, Groovydoc dapat dijalankan dari baris perintah. Perintah untuk menjalankan Groovydoc terhadap kelas dan skrip di atas (dengan asumsi semuanya berada dalam direktori yang sama di mana perintah itu dijalankan) kelihatan seperti ini:

groovydoc -classpath C:\groovy-1.8.0\lib\ -d output -windowtitle "Groovy 1.8 Logging Example" -header "Groovy 1.8 Logging (Inspired by Actual Events)" -footer "Inspired by Actual Events: Logging in Groovy 1.8" -doctitle "Logging in Groovy 1.8 Demonstrated" *.groovy *.java 

Perintah di atas semuanya dijalankan pada satu baris. Namun, untuk pembacaan yang lebih baik, saya telah menambah jeda baris untuk memecah perintah.

groovydoc -classpath C:\groovy-1.8.0\lib\ -d output -windowtitle "Groovy 1.8 Logging Example" -header "Groovy 1.8 Logging (Inspired by Actual Events)" -footer "Inspired by Actual Events: Logging in Groovy 1.8" -doctitle "Logging in Groovy 1.8 Demonstrated" *.groovy *.java 

Parameter perintah groovydoc kelihatan biasa bagi sesiapa sahaja yang telah menggunakan javadoc dari baris arahan. Bahagian terakhir perintah menetapkan bahawa groovydoc harus dijalankan terhadap kod Groovy dan Java.

Menjalankan Groovydoc dari Ant

Groovydoc juga dapat diakses dengan mudah melalui tugas semut khusus seperti yang dijelaskan dalam Panduan Pengguna Groovy. Cukup mudah untuk menerapkan tugas semut groovydoc dengan terlebih dahulu menyediakan taskdef yang sesuai dan kemudian dengan menggunakan tag yang ditentukan. Ini ditunjukkan dalam coretan XML berikut dari build.xmlfail yang berkaitan .

Sebahagian daripada fail Semut build.xml Menunjukkan Tugas groovydoc


    
    

Bahagian Semut yang build.xmlditunjukkan di atas kira-kira setara dengan yang digunakan pada baris perintah. Mempunyai Groovydoc tersedia melalui Semut adalah mustahak kerana memudahkan untuk mengintegrasikan pembuatan dokumentasi Groovy dari sistem binaan berasaskan Ant.

Dokumentasi Dihasilkan Groovydoc

Kerana setiap pendekatan untuk menghasilkan dokumentasi Groovy melalui Groovydoc (baris perintah atau berasaskan Ant) berfungsi sama seperti yang lain, saya sekarang akan memberi tumpuan kepada output HTML yang mungkin berasal dari kedua-dua pendekatan tersebut. Siri tangkapan skrin seterusnya menunjukkan dokumentasi yang dihasilkan bermula dengan halaman utama, diikuti oleh halaman DefaultPackage (saya dengan malas meninggalkan skrip, kelas Groovy, dan kelas Java di direktori semasa dan tanpa pernyataan pakej), diikuti masing-masing dengan output untuk skrip Groovy, untuk kelas Groovy contoh, dan untuk kelas Java yang dibuat. Tiga gambar terakhir membantu membezakan antara output untuk Skrip Groovy berbanding kelas Groovy berbanding kelas Java.

Contoh Halaman Utama Groovydoc

Output Groovydoc untuk Contoh Pakej (DefaultPackage)

Keluaran Groovydoc untuk Contoh Skrip Groovy

Keluaran Groovydoc untuk Contoh Kelas Groovy

Output Groovydoc untuk Contoh Kelas Java

Beberapa pemerhatian dapat dibuat dari output Groovydoc yang ditunjukkan di atas. Pertama, dokumentasi yang dihasilkan untuk skrip Groovy hanya mendokumentasikan kaedah yang ditentukan dalam skrip (termasuk mainkaedah tersirat ). Apa yang tidak begitu jelas dari gambar statik di atas adalah bahawa, sebenarnya, tidak ada output Groovydoc yang dibuat untuk skrip sama sekali kecuali sekurang-kurangnya satu kaedah ditentukan secara eksplisit dalam skrip. Sekiranya satu kaedah ditentukan dalam skrip, maka output Groovydoc dihasilkan untuk kaedah yang ditentukan dan untuk kaedah utama yang tersirat. Pilihan -nomainforscriptsboleh diberikan kepada Groovydoc untuk tidak menghasilkan Groovydoc untuk mainkaedah tersirat . Hasil penambahan pilihan ini ditunjukkan seterusnya (perhatikan bahawa maindokumentasi tidak lagi ditampilkan).

Yang -nommainforscriptspilihan adalah baik kerana kita sering tidak mahu mainfungsi yang akan tersirat didokumenkan oleh skrip kami. Sesungguhnya, mainfungsi tersebut biasanya "disembunyikan" dari kita sebagai penulis skrip dan penyelenggara.

Pemerhatian kedua dari melihat output yang dihasilkan Groovydoc adalah bahawa output yang dihasilkan membezakan antara kod sumber Groovy dan Java. Skrip dan kelas Groovy diberi label dengan "[Groovy]" dan kelas Java dilabelkan dengan "[Java]." Ini juga terbukti dalam dokumentasi Groovy API yang dihasilkan oleh Groovydoc di mana ciri ini memudahkan untuk mengenal pasti bahawa groovy.sql.Sql dan AntBuilder adalah kelas Java sementara JmxBuilder dan SwingBuilder adalah kelas Groovy.