The two files below are example outputs of the code generator for call interception in gradle/gradle
Last active
February 16, 2023 12:23
-
-
Save h0tk3y/0a905b638bb0459b33578ec511d7c242 to your computer and use it in GitHub Desktop.
Call interception generated sources example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.gradle.internal.classpath; | |
import java.io.File; | |
import java.io.FileFilter; | |
import java.io.FileInputStream; | |
import java.io.FilenameFilter; | |
import java.lang.Object; | |
import java.lang.Override; | |
import java.lang.String; | |
import java.lang.Throwable; | |
import java.nio.charset.Charset; | |
import java.util.Arrays; | |
import java.util.List; | |
import kotlin.io.FilesKt; | |
import org.gradle.internal.classpath.declarations.FileInputStreamInterceptorsDeclaration; | |
import org.gradle.internal.classpath.declarations.FileInterceptorsDeclaration; | |
import org.gradle.internal.classpath.declarations.KotlinFileExtensionsInterceptorsDeclaration; | |
import org.gradle.internal.classpath.intercept.CallInterceptor; | |
import org.gradle.internal.classpath.intercept.InterceptScope; | |
import org.gradle.internal.classpath.intercept.Invocation; | |
class InterceptorDeclaration_GroovyInterceptorsImpl { | |
public static List<CallInterceptor> getCallInterceptors() { | |
return Arrays.asList( | |
new ReadTextCallInterceptor(), | |
new ListFilesCallInterceptor(), | |
new ExistsCallInterceptor(), | |
new IsFileCallInterceptor(), | |
new IsDirectoryCallInterceptor(), | |
new FileInputStreamConstructorCallInterceptor() | |
); | |
} | |
private static class ReadTextCallInterceptor extends CallInterceptor { | |
public ReadTextCallInterceptor() { | |
super(InterceptScope.methodsNamed("readText")); | |
} | |
@Override | |
protected Object doIntercept(Invocation invocation, String consumer) throws Throwable { | |
Object receiver = invocation.getReceiver(); | |
if (receiver.equals(FilesKt.class)) { | |
Object arg0 = invocation.getArgument(0); | |
if (arg0 instanceof File) { | |
File arg0Typed = (File) arg0; | |
Object arg1 = invocation.getArgument(1); | |
if (arg1 instanceof Charset) { | |
Charset arg1Typed = (Charset) arg1; | |
if (invocation.getArgsCount() == 2) { | |
return KotlinFileExtensionsInterceptorsDeclaration.intercept_readText(arg0Typed, arg1Typed, 0, consumer); | |
} | |
} | |
} | |
} | |
return invocation.callOriginal(); | |
} | |
} | |
private static class ListFilesCallInterceptor extends CallInterceptor { | |
public ListFilesCallInterceptor() { | |
super(InterceptScope.methodsNamed("listFiles")); | |
} | |
@Override | |
protected Object doIntercept(Invocation invocation, String consumer) throws Throwable { | |
Object receiver = invocation.getReceiver(); | |
if (receiver instanceof File) { | |
File receiverTyped = (File) receiver; | |
if (invocation.getArgsCount() == 0) { | |
return FileInterceptorsDeclaration.intercept_listFiles(receiverTyped, consumer); | |
} | |
Object arg0 = invocation.getArgument(0); | |
if (arg0 instanceof FileFilter) { | |
FileFilter arg0Typed = (FileFilter) arg0; | |
if (invocation.getArgsCount() == 1) { | |
return FileInterceptorsDeclaration.intercept_listFiles(receiverTyped, arg0Typed, consumer); | |
} | |
} | |
if (arg0 instanceof FilenameFilter) { | |
FilenameFilter arg0Typed = (FilenameFilter) arg0; | |
if (invocation.getArgsCount() == 1) { | |
return FileInterceptorsDeclaration.intercept_listFiles(receiverTyped, arg0Typed, consumer); | |
} | |
} | |
} | |
return invocation.callOriginal(); | |
} | |
} | |
private static class ExistsCallInterceptor extends CallInterceptor { | |
public ExistsCallInterceptor() { | |
super(InterceptScope.methodsNamed("exists")); | |
} | |
@Override | |
protected Object doIntercept(Invocation invocation, String consumer) throws Throwable { | |
Object receiver = invocation.getReceiver(); | |
if (receiver instanceof File) { | |
File receiverTyped = (File) receiver; | |
if (invocation.getArgsCount() == 0) { | |
return FileInterceptorsDeclaration.intercept_exists(receiverTyped, consumer); | |
} | |
} | |
return invocation.callOriginal(); | |
} | |
} | |
private static class IsFileCallInterceptor extends CallInterceptor { | |
public IsFileCallInterceptor() { | |
super(InterceptScope.methodsNamed("isFile")); | |
} | |
@Override | |
protected Object doIntercept(Invocation invocation, String consumer) throws Throwable { | |
Object receiver = invocation.getReceiver(); | |
if (receiver instanceof File) { | |
File receiverTyped = (File) receiver; | |
if (invocation.getArgsCount() == 0) { | |
return FileInterceptorsDeclaration.intercept_isFile(receiverTyped, consumer); | |
} | |
} | |
return invocation.callOriginal(); | |
} | |
} | |
private static class IsDirectoryCallInterceptor extends CallInterceptor { | |
public IsDirectoryCallInterceptor() { | |
super(InterceptScope.methodsNamed("isDirectory")); | |
} | |
@Override | |
protected Object doIntercept(Invocation invocation, String consumer) throws Throwable { | |
Object receiver = invocation.getReceiver(); | |
if (receiver instanceof File) { | |
File receiverTyped = (File) receiver; | |
if (invocation.getArgsCount() == 0) { | |
return FileInterceptorsDeclaration.intercept_isDirectory(receiverTyped, consumer); | |
} | |
} | |
return invocation.callOriginal(); | |
} | |
} | |
private static class FileInputStreamConstructorCallInterceptor extends CallInterceptor { | |
public FileInputStreamConstructorCallInterceptor() { | |
super(InterceptScope.constructorsOf(FileInputStream.class)); | |
} | |
@Override | |
protected Object doIntercept(Invocation invocation, String consumer) throws Throwable { | |
Object receiver = invocation.getReceiver(); | |
if (receiver.equals(FileInputStream.class)) { | |
Object arg0 = invocation.getArgument(0); | |
if (arg0 instanceof File) { | |
File arg0Typed = (File) arg0; | |
if (invocation.getArgsCount() == 1) { | |
FileInputStream result = new FileInputStream(arg0Typed); | |
FileInputStreamInterceptorsDeclaration.interceptFileInputStreamConstructor(result, arg0Typed, consumer); | |
return result; | |
} | |
} | |
if (arg0 instanceof String) { | |
String arg0Typed = (String) arg0; | |
if (invocation.getArgsCount() == 1) { | |
FileInputStream result = new FileInputStream(arg0Typed); | |
FileInputStreamInterceptorsDeclaration.interceptFileInputStreamConstructor(result, arg0Typed, consumer); | |
return result; | |
} | |
} | |
} | |
return invocation.callOriginal(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.gradle.internal.classpath; | |
import java.io.File; | |
import java.io.FileFilter; | |
import java.io.FileInputStream; | |
import java.io.FilenameFilter; | |
import java.lang.Override; | |
import java.lang.String; | |
import java.nio.charset.Charset; | |
import kotlin.io.FilesKt; | |
import org.gradle.internal.classpath.declarations.FileInputStreamInterceptorsDeclaration; | |
import org.gradle.internal.classpath.declarations.FileInterceptorsDeclaration; | |
import org.gradle.internal.classpath.declarations.KotlinFileExtensionsInterceptorsDeclaration; | |
import org.gradle.internal.instrumentation.api.jvmbytecode.JvmBytecodeCallInterceptor; | |
import org.gradle.internal.instrumentation.utils.LocalVariablesSorterWithDroppedVariables; | |
import org.gradle.model.internal.asm.MethodVisitorScope; | |
import org.objectweb.asm.MethodVisitor; | |
import org.objectweb.asm.Opcodes; | |
import org.objectweb.asm.Type; | |
class InterceptorDeclaration_JvmBytecodeImpl extends MethodVisitorScope implements JvmBytecodeCallInterceptor { | |
private static final Type FILE_INPUT_STREAM_INTERCEPTORS_DECLARATION_TYPE = Type.getType(FileInputStreamInterceptorsDeclaration.class); | |
private static final Type KOTLIN_FILE_EXTENSIONS_INTERCEPTORS_DECLARATION_TYPE = Type.getType(KotlinFileExtensionsInterceptorsDeclaration.class); | |
private static final Type FILE_INTERCEPTORS_DECLARATION_TYPE = Type.getType(FileInterceptorsDeclaration.class); | |
private final LocalVariablesSorterWithDroppedVariables localVariablesSorter; | |
/** | |
* This is the method visitor that does not map the local variables with the {@link localVariablesSorter} and can thus use the newly introduced variables. | |
*/ | |
private final MethodVisitor unmappedMethodVisitor; | |
public InterceptorDeclaration_JvmBytecodeImpl(MethodVisitor unmappedMethodVisitor, | |
LocalVariablesSorterWithDroppedVariables localVariablesSorter) { | |
super(localVariablesSorter); | |
this.localVariablesSorter = localVariablesSorter; | |
this.unmappedMethodVisitor = unmappedMethodVisitor; | |
} | |
private static String binaryClassNameOf(String className) { | |
return Type.getObjectType(className).getClassName(); | |
} | |
private void loadOwnerBinaryClassName(String className) { | |
_LDC(binaryClassNameOf(className)); | |
} | |
@Override | |
public boolean visitMethodInsn(String className, int opcode, String owner, String name, | |
String descriptor, boolean isInterface) { | |
if (owner.equals("java/io/FileInputStream")) { | |
/** | |
* Intercepting constructor (getting notified after it): {@link FileInputStream#FileInputStream(File)} | |
* Intercepted by {@link FileInputStreamInterceptorsDeclaration#interceptFileInputStreamConstructor(FileInputStream, File, String)} | |
*/ | |
if (name.equals("<init>") && descriptor.equals("(Ljava/io/File;)V") && opcode == Opcodes.INVOKESPECIAL) { | |
Type type0 = Type.getType(File.class); | |
int var0 = localVariablesSorter.newLocal(type0); | |
unmappedMethodVisitor.visitVarInsn(type0.getOpcode(Opcodes.ISTORE), var0); | |
_DUP(); | |
unmappedMethodVisitor.visitVarInsn(type0.getOpcode(Opcodes.ILOAD), var0); | |
_INVOKESPECIAL(owner, name, descriptor); | |
unmappedMethodVisitor.visitVarInsn(type0.getOpcode(Opcodes.ILOAD), var0); | |
localVariablesSorter.dropLocal(var0); | |
loadOwnerBinaryClassName(className); | |
_INVOKESTATIC(FILE_INPUT_STREAM_INTERCEPTORS_DECLARATION_TYPE, "interceptFileInputStreamConstructor", "(Ljava/io/FileInputStream;Ljava/io/File;Ljava/lang/String;)V"); | |
return true; | |
} | |
/** | |
* Intercepting constructor (getting notified after it): {@link FileInputStream#FileInputStream(String)} | |
* Intercepted by {@link FileInputStreamInterceptorsDeclaration#interceptFileInputStreamConstructor(FileInputStream, String, String)} | |
*/ | |
if (name.equals("<init>") && descriptor.equals("(Ljava/lang/String;)V") && opcode == Opcodes.INVOKESPECIAL) { | |
Type type0 = Type.getType(String.class); | |
int var0 = localVariablesSorter.newLocal(type0); | |
unmappedMethodVisitor.visitVarInsn(type0.getOpcode(Opcodes.ISTORE), var0); | |
_DUP(); | |
unmappedMethodVisitor.visitVarInsn(type0.getOpcode(Opcodes.ILOAD), var0); | |
_INVOKESPECIAL(owner, name, descriptor); | |
unmappedMethodVisitor.visitVarInsn(type0.getOpcode(Opcodes.ILOAD), var0); | |
localVariablesSorter.dropLocal(var0); | |
loadOwnerBinaryClassName(className); | |
_INVOKESTATIC(FILE_INPUT_STREAM_INTERCEPTORS_DECLARATION_TYPE, "interceptFileInputStreamConstructor", "(Ljava/io/FileInputStream;Ljava/lang/String;Ljava/lang/String;)V"); | |
return true; | |
} | |
} | |
if (owner.equals("kotlin/io/FilesKt")) { | |
/** | |
* Intercepting static method: {@link FilesKt#readText(File, Charset)} | |
* Intercepted by {@link KotlinFileExtensionsInterceptorsDeclaration#intercept_readText(File, Charset, int, String)} | |
*/ | |
if (name.equals("readText") && descriptor.equals("(Ljava/io/File;Ljava/nio/charset/Charset;)Ljava/lang/String;") && opcode == Opcodes.INVOKESTATIC) { | |
// The interceptor expects a Kotlin default mask, add a zero argument: | |
_ICONST_0(); | |
_LDC(binaryClassNameOf(className)); | |
_INVOKESTATIC(KOTLIN_FILE_EXTENSIONS_INTERCEPTORS_DECLARATION_TYPE, "intercept_readText", "(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/String;)Ljava/lang/String;"); | |
return true; | |
} | |
// Additionally intercept the signature with the Kotlin default mask and marker: | |
if (name.equals("readText$default") && descriptor.equals("(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/lang/String;") && opcode == Opcodes.INVOKESTATIC) { | |
_POP(); | |
_LDC(binaryClassNameOf(className)); | |
_INVOKESTATIC(KOTLIN_FILE_EXTENSIONS_INTERCEPTORS_DECLARATION_TYPE, "intercept_readText", "(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/String;)Ljava/lang/String;"); | |
return true; | |
} | |
} | |
if (owner.equals("java/io/File")) { | |
/** | |
* Intercepting instance method: {@link File#listFiles()} | |
* Intercepted by {@link FileInterceptorsDeclaration#intercept_listFiles(File, String)} | |
*/ | |
if (name.equals("listFiles") && descriptor.equals("()Ljava/io/File;]") && opcode == Opcodes.INVOKEVIRTUAL) { | |
_LDC(binaryClassNameOf(className)); | |
_INVOKESTATIC(FILE_INTERCEPTORS_DECLARATION_TYPE, "intercept_listFiles", "(Ljava/io/File;Ljava/lang/String;)Ljava/io/File;]"); | |
return true; | |
} | |
/** | |
* Intercepting instance method: {@link File#listFiles(FileFilter)} | |
* Intercepted by {@link FileInterceptorsDeclaration#intercept_listFiles(File, FileFilter, String)} | |
*/ | |
if (name.equals("listFiles") && descriptor.equals("(Ljava/io/FileFilter;)Ljava/io/File;]") && opcode == Opcodes.INVOKEVIRTUAL) { | |
_LDC(binaryClassNameOf(className)); | |
_INVOKESTATIC(FILE_INTERCEPTORS_DECLARATION_TYPE, "intercept_listFiles", "(Ljava/io/File;Ljava/io/FileFilter;Ljava/lang/String;)Ljava/io/File;]"); | |
return true; | |
} | |
/** | |
* Intercepting instance method: {@link File#listFiles(FilenameFilter)} | |
* Intercepted by {@link FileInterceptorsDeclaration#intercept_listFiles(File, FilenameFilter, String)} | |
*/ | |
if (name.equals("listFiles") && descriptor.equals("(Ljava/io/FilenameFilter;)Ljava/io/File;]") && opcode == Opcodes.INVOKEVIRTUAL) { | |
_LDC(binaryClassNameOf(className)); | |
_INVOKESTATIC(FILE_INTERCEPTORS_DECLARATION_TYPE, "intercept_listFiles", "(Ljava/io/File;Ljava/io/FilenameFilter;Ljava/lang/String;)Ljava/io/File;]"); | |
return true; | |
} | |
/** | |
* Intercepting instance method: {@link File#exists()} | |
* Intercepted by {@link FileInterceptorsDeclaration#intercept_exists(File, String)} | |
*/ | |
if (name.equals("exists") && descriptor.equals("()Z") && opcode == Opcodes.INVOKEVIRTUAL) { | |
_LDC(binaryClassNameOf(className)); | |
_INVOKESTATIC(FILE_INTERCEPTORS_DECLARATION_TYPE, "intercept_exists", "(Ljava/io/File;Ljava/lang/String;)Z"); | |
return true; | |
} | |
/** | |
* Intercepting instance method: {@link File#isFile()} | |
* Intercepted by {@link FileInterceptorsDeclaration#intercept_isFile(File, String)} | |
*/ | |
if (name.equals("isFile") && descriptor.equals("()Z") && opcode == Opcodes.INVOKEVIRTUAL) { | |
_LDC(binaryClassNameOf(className)); | |
_INVOKESTATIC(FILE_INTERCEPTORS_DECLARATION_TYPE, "intercept_isFile", "(Ljava/io/File;Ljava/lang/String;)Z"); | |
return true; | |
} | |
/** | |
* Intercepting instance method: {@link File#isDirectory()} | |
* Intercepted by {@link FileInterceptorsDeclaration#intercept_isDirectory(File, String)} | |
*/ | |
if (name.equals("isDirectory") && descriptor.equals("()Z") && opcode == Opcodes.INVOKEVIRTUAL) { | |
_LDC(binaryClassNameOf(className)); | |
_INVOKESTATIC(FILE_INTERCEPTORS_DECLARATION_TYPE, "intercept_isDirectory", "(Ljava/io/File;Ljava/lang/String;)Z"); | |
return true; | |
} | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment