notes/pl/groovy/groovy-traits.txt
Ihar Hancharenka 5dff80e88e first
2023-03-27 16:52:17 +03:00

76 строки
1.9 KiB
Plaintext

package devoxx.demo
trait MessageSender {
void send(String method, Writer writer) {
writer.print "MESSAGE: $message"
}
}
import spock.lang.Specification
class MessageSenderSpec extends Specification {
void 'test @MessageSource annotation adds MessageSender trait to class'() {
expect:
MessageSender.isAssignableFrom SomeClass
}
void 'test invoking the send method'() {
given:
def writer = new StringWriter()
def obj = new SomeClass()
when:
obj.send 'Hi There', writer
then:
writer.toString() == 'MESSAGE: Hi There'
}
}
@MessageSource
class SomeClass {
}
package devoxx.demo
import org.codehaus.groovy.transform.GroovyASTTransformationClass
import java.lang.annotation.Target
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.ElementType
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
@GroovyASTTransformationClass("devoxx.demo.MessagerTransformation")
@interface MessageSource {
}
package devoxx.demo
import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.ClassHelper
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.CompilePhase
import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.transform.ASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformation
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
class MessagerTransformation implements ASTTransformation {
@Override
void visit(ASTNode[] nodes, SourceUnit source) {
ClassNode classNode = nodes[1] // 0 - annotation node, 1 - Foo-class-node
ClassNode senderNode = ClassHelper.make(MessageSender)
if (!classNode.declaresInterface(senderNode)) {
classNode.addInterface(senderNode)
}
}
}