All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.micronaut.ast.groovy.utils.PublicMethodVisitor.groovy Maven / Gradle / Ivy

There is a newer version: 4.7.9
Show newest version
/*
 * Copyright 2017-2020 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.micronaut.ast.groovy.utils

import groovy.transform.CompileStatic
import io.micronaut.core.annotation.Internal
import io.micronaut.core.naming.NameUtils
import org.codehaus.groovy.ast.ClassCodeVisitorSupport
import org.codehaus.groovy.ast.ClassHelper
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.MethodNode
import org.codehaus.groovy.ast.Parameter
import org.codehaus.groovy.ast.PropertyNode
import org.codehaus.groovy.control.SourceUnit

/**
 * Visits public methods in a class node.
 *
 * @author Graeme Rocher
 * @since 1.0
 */
@CompileStatic
@Internal
abstract class PublicMethodVisitor extends ClassCodeVisitorSupport {

    final SourceUnit sourceUnit
    private final Set processed = new HashSet<>()
    private ClassNode current

    PublicMethodVisitor(SourceUnit sourceUnit) {
        this.sourceUnit = sourceUnit
    }

    @Override
    protected SourceUnit getSourceUnit() {
        return sourceUnit
    }

    void accept(ClassNode classNode) {
        while (classNode != null && classNode.name != Object.class.getName()) {
            this.current = classNode
            classNode.visitContents(this)
            for (i in classNode.getAllInterfaces()) {
                if (i.name != GroovyObject.class.name) {
                    this.current = i
                    i.visitContents(this)
                }
            }

            classNode = classNode.getSuperClass()
        }
    }

    @Override
    void visitMethod(MethodNode node) {
        if (isAcceptable(node)) {
            def key = node.getText()
            if (!processed.contains(key)) {
                processed.add(key)
                accept(current ?: node.declaringClass, node)
            }
        }
    }

    @Override
    void visitProperty(PropertyNode node) {
        //Convert the property to a setter method
        Parameter param = new Parameter(node.type, node.name)
        MethodNode setter = new MethodNode(NameUtils.setterNameFor(node.name),
                node.modifiers,
                ClassHelper.makeCached(Void.TYPE),
                [param] as Parameter[],
                null,
                null)
        setter.addAnnotations(node.field.getAnnotations())
        setter.setDeclaringClass(node.getDeclaringClass())

        //Convert the property to a getter method
        MethodNode getter = new MethodNode(NameUtils.getterNameFor(node.name),
                node.modifiers,
                node.type,
                [] as Parameter[],
                null,
                null)
        getter.addAnnotations(node.field.getAnnotations())
        getter.setDeclaringClass(node.getDeclaringClass())

        ClassNode classNode = current ?: node.declaringClass
        //Can't use node.getText() because for properties because it returns 
        String key = classNode.getName() + '#' + node.getName()
        if (!processed.contains(key)) {
            processed.add(key)
            if (isAcceptable(setter)) {
                accept(classNode, setter)
            }
            if (isAcceptable(getter)) {
                accept(classNode, getter)
            }
        }

    }

    protected boolean isAcceptable(MethodNode node) {
        node.isPublic() && !node.isStatic() && !node.isSynthetic() && !node.isFinal()
    }

    abstract void accept(ClassNode classNode, MethodNode methodNode)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy