<commit_before>package javaposse.jobdsl.dsl.doc

import groovy.json.JsonBuilder
import javaposse.jobdsl.dsl.DslFactory
import javaposse.jobdsl.dsl.NoDoc
import javaposse.jobdsl.dsl.RequiresPlugin
import org.codehaus.groovy.groovydoc.GroovyAnnotationRef
import org.codehaus.groovy.groovydoc.GroovyClassDoc
import org.codehaus.groovy.groovydoc.GroovyMethodDoc
import org.codehaus.groovy.groovydoc.GroovyParameter
import org.codehaus.groovy.tools.groovydoc.ArrayClassDocWrapper

import java.lang.annotation.Annotation
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

class ApiDocGenerator {

    final private GroovyDocHelper docHelper = new GroovyDocHelper('src/main/groovy/')
    final private String commandDocsPath = 'src/main/docs'
    final private Class rootClass = DslFactory
    final private Map allContextClasses = [:]
    final private List allContextClassesList = []

    static void main(String[] args) {
        String version = args[0]
        String outputPath = args[1]

        JsonBuilder builder = new ApiDocGenerator().generateApi(version)

        File file = new File(outputPath)
        file.parentFile.mkdirs()

        file.withWriter { it << builder.toPrettyString() }
    }

    JsonBuilder generateApi(String version) {
        allContextClassesList << rootClass.name
        allContextClasses[rootClass.name] = processClass(rootClass)
        Map map = [
            version: version,
            root: [
                name: 'Jenkins Job DSL API',
                contextClass: rootClass.name
            ],
            contexts: allContextClasses
        ]

        JsonBuilder builder = new JsonBuilder()
        builder map

        builder
    }

    private Map processClass(Class clazz) {
        Map map = [type: clazz.name]

        map.methods = getMethodsForClass(clazz)
        getDelegateClasses(clazz).each { Class delegateClass ->
            map.methods.addAll getMethodsForClass(delegateClass)
        }
        map.methods = map.methods.sort { it.name }
        map
    }

    private List<Class> getDelegateClasses(Class clazz) {
        GroovyClassDoc classDoc = docHelper.getGroovyClassDoc(clazz)
        List delegateNames = classDoc.properties().findAll {
            it.annotations().any { GroovyAnnotationRef a -> a.name == 'Delegate' }
        }*.name()

        Field[] declaredFields = clazz.declaredFields.findAll { delegateNames.contains it.name }
        declaredFields*.type
    }

    private List getMethodsForClass(Class clazz) {
        List<String> methodNames = clazz.methods.findAll {
            !it.name.startsWith('get') &&
                !it.name.startsWith('set') &&
                !it.name.startsWith('is') &&
                !(it.declaringClass in [Object, Script]) &&
                Modifier.isPublic(it.modifiers) &&
                !it.name.contains('$') &&
                !it.getAnnotation(NoDoc) &&
                !(it.name in ['invokeMethod', 'executeWithXmlActions'])
        }*.name.unique().sort()
        methodNames.collect { processMethodName it, clazz }
    }

    private Map processMethodName(String methodName, Class clazz) {
        Map methodMap = [
            name      : methodName,
            signatures: []
        ]
        GroovyMethodDoc[] methodDocs = docHelper.getAllMethods(clazz).findAll { it.name() == methodName }

        methodDocs.each { GroovyMethodDoc methodDoc ->
            Method method = GroovyDocHelper.getMethodFromGroovyMethodDoc(methodDoc, clazz)
            if (method) {
                Map signature = processMethod(method, methodDoc)
                methodMap.signatures << signature

                Class contextClass = getContextClass(method, methodDoc)
                if (contextClass) {
                    signature.contextClass = contextClass.name
                    if (!allContextClassesList.contains(contextClass.name)) {
                        allContextClassesList << contextClass.name
                        allContextClasses[contextClass.name] = processClass(contextClass)
                    }
                }
            }
        }

        List<RequiresPlugin> annotations = methodDocs.collect { GroovyMethodDoc methodDoc ->
            Method method = GroovyDocHelper.getMethodFromGroovyMethodDoc(methodDoc, clazz)
            method?.getAnnotation(RequiresPlugin)
        }.findAll()

        String dslPlugin = annotations.find { it.id() }?.id() // TODO add min ver
        if (dslPlugin) {
            methodMap.plugin = dslPlugin
        }

        String path = "${clazz.name.replaceAll('\\.', '/')}/$methodName"
        File file = new File("${commandDocsPath}/examples/${path}.groovy")
        // TODO check superclasses

        if (file.exists()) {
            methodMap.examples = file.text
        }

        methodMap
    }

    private Class getContextClass(Method method, GroovyMethodDoc methodDoc) {
        Class clazz = null
        GroovyParameter[] groovyParameters = methodDoc.parameters()
        if (groovyParameters.length) {
            Annotation[][] parameterAnnotations = method.parameterAnnotations
            clazz = getContextClass(groovyParameters[-1], parameterAnnotations[-1])
        }
        clazz
    }<commit_msg>if examples could not be found, try to load them for the super class<commit_after>package javaposse.jobdsl.dsl.doc

import groovy.json.JsonBuilder
import javaposse.jobdsl.dsl.DslFactory
import javaposse.jobdsl.dsl.NoDoc
import javaposse.jobdsl.dsl.RequiresPlugin
import org.codehaus.groovy.groovydoc.GroovyAnnotationRef
import org.codehaus.groovy.groovydoc.GroovyClassDoc
import org.codehaus.groovy.groovydoc.GroovyMethodDoc
import org.codehaus.groovy.groovydoc.GroovyParameter
import org.codehaus.groovy.tools.groovydoc.ArrayClassDocWrapper

import java.lang.annotation.Annotation
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

class ApiDocGenerator {

    final private GroovyDocHelper docHelper = new GroovyDocHelper('src/main/groovy/')
    final private String commandDocsPath = 'src/main/docs'
    final private Class rootClass = DslFactory
    final private Map allContextClasses = [:]
    final private List allContextClassesList = []

    static void main(String[] args) {
        String version = args[0]
        String outputPath = args[1]

        JsonBuilder builder = new ApiDocGenerator().generateApi(version)

        File file = new File(outputPath)
        file.parentFile.mkdirs()

        file.withWriter { it << builder.toPrettyString() }
    }

    JsonBuilder generateApi(String version) {
        allContextClassesList << rootClass.name
        allContextClasses[rootClass.name] = processClass(rootClass)
        Map map = [
            version: version,
            root: [
                name: 'Jenkins Job DSL API',
                contextClass: rootClass.name
            ],
            contexts: allContextClasses
        ]

        JsonBuilder builder = new JsonBuilder()
        builder map

        builder
    }

    private Map processClass(Class clazz) {
        Map map = [type: clazz.name]

        map.methods = getMethodsForClass(clazz)
        getDelegateClasses(clazz).each { Class delegateClass ->
            map.methods.addAll getMethodsForClass(delegateClass)
        }
        map.methods = map.methods.sort { it.name }
        map
    }

    private List<Class> getDelegateClasses(Class clazz) {
        GroovyClassDoc classDoc = docHelper.getGroovyClassDoc(clazz)
        List delegateNames = classDoc.properties().findAll {
            it.annotations().any { GroovyAnnotationRef a -> a.name == 'Delegate' }
        }*.name()

        Field[] declaredFields = clazz.declaredFields.findAll { delegateNames.contains it.name }
        declaredFields*.type
    }

    private List getMethodsForClass(Class clazz) {
        List<String> methodNames = clazz.methods.findAll {
            !it.name.startsWith('get') &&
                !it.name.startsWith('set') &&
                !it.name.startsWith('is') &&
                !(it.declaringClass in [Object, Script]) &&
                Modifier.isPublic(it.modifiers) &&
                !it.name.contains('$') &&
                !it.getAnnotation(NoDoc) &&
                !(it.name in ['invokeMethod', 'executeWithXmlActions'])
        }*.name.unique().sort()
        methodNames.collect { processMethodName it, clazz }
    }

    private Map processMethodName(String methodName, Class clazz) {
        Map methodMap = [
            name      : methodName,
            signatures: []
        ]
        GroovyMethodDoc[] methodDocs = docHelper.getAllMethods(clazz).findAll { it.name() == methodName }

        methodDocs.each { GroovyMethodDoc methodDoc ->
            Method method = GroovyDocHelper.getMethodFromGroovyMethodDoc(methodDoc, clazz)
            if (method) {
                Map signature = processMethod(method, methodDoc)
                methodMap.signatures << signature

                Class contextClass = getContextClass(method, methodDoc)
                if (contextClass) {
                    signature.contextClass = contextClass.name
                    if (!allContextClassesList.contains(contextClass.name)) {
                        allContextClassesList << contextClass.name
                        allContextClasses[contextClass.name] = processClass(contextClass)
                    }
                }
            }
        }

        List<RequiresPlugin> annotations = methodDocs.collect { GroovyMethodDoc methodDoc ->
            Method method = GroovyDocHelper.getMethodFromGroovyMethodDoc(methodDoc, clazz)
            method?.getAnnotation(RequiresPlugin)
        }.findAll()

        String dslPlugin = annotations.find { it.id() }?.id() // TODO add min ver
        if (dslPlugin) {
            methodMap.plugin = dslPlugin
        }

        String examples = getExamples(clazz, methodName)
        if (examples) {
            methodMap.examples = examples
        }

        methodMap
    }

    private String getExamples(Class clazz, String methodName) {
        String path = "${clazz.name.replaceAll('\\.', '/')}/$methodName"
        File file = new File("${commandDocsPath}/examples/${path}.groovy")
        if (file.exists()) {
            file.text
        } else if (clazz.superclass) {
            getExamples(clazz.superclass, methodName)
        } else {
            null
        }
    }

    private Class getContextClass(Method method, GroovyMethodDoc methodDoc) {
        Class clazz = null
        GroovyParameter[] groovyParameters = methodDoc.parameters()
        if (groovyParameters.length) {
            Annotation[][] parameterAnnotations = method.parameterAnnotations
            clazz = getContextClass(groovyParameters[-1], parameterAnnotations[-1])
        }
        clazz
    }
{'fraction_non_alphanumeric': 0.09435850773430392, 'fraction_numerical': 0.0007279344858962694, 'mean_word_length': 2.34989332520573, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2407281', 'n_tokens_mistral': 3089, 'n_tokens_neox': 2905, 'n_words': 592}