aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/ftbsc/lll/proxies/MethodProxy.java
blob: 5f80c08a1a68ed4d116de91028e5cf3bb3f3dcfc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package ftbsc.lll.proxies;

import org.objectweb.asm.Type;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import static ftbsc.lll.tools.DescriptorBuilder.nameToDescriptor;

/**
 * A container for information about class methods to be used
 * in ASM patching.
 * @since 0.3.0
 */
public class MethodProxy extends AbstractProxy {

   /**
    * The parameters of the method.
    */
   public final Type[] parameters;

   /**
    * The return type of the method.
    */
   public final Type returnType;

   /**
    * A public constructor, builds a proxy from a {@link Method}
    * obtained from reflection.
    * @param m the {@link Method} object corresponding to this.
    */
   public MethodProxy(Method m) {
      super(m.getName(), Type.getType(m), m.getModifiers(), Type.getInternalName(m.getDeclaringClass()));
      Type mt = Type.getType(m);
      this.parameters = mt.getArgumentTypes();
      this.returnType = mt.getReturnType();
   }

   /**
    * A protected constructor, called only from the builder.
    * @param name the name of the method
    * @param modifiers the modifiers of the method
    * @param parent the FQN of the parent class of the method
    * @param parameters the parameters of the method
    * @param returnType the return type of the method
    */
   protected MethodProxy(String name, int modifiers, String parent, Type[] parameters, Type returnType) {
      super(name, Type.getMethodType(returnType, parameters), modifiers, parent);
      this.parameters = parameters;
      this.returnType = returnType;
   }

   /**
    * Returns a new instance of {@link MethodProxy.Builder}.
    * @param name the name of the method
    * @return the builder object for method proxies
    */
   public static Builder builder(String name) {
      return new Builder(name);
   }

   /**
    * A builder object for {@link MethodProxy}.
    */
   public static class Builder extends AbstractProxy.Builder<MethodProxy> {
      /**
       * The parameters of the method.
       */
      private final List<Type> parameters;

      /**
       * The return type of the method. Defaults to void.
       */
      private Type returnType;

      /**
       * The constructor of the builder, used only internally.
       * @param name the name of the method
       */
      Builder(String name) {
         super(name);
         this.parameters = new ArrayList<>();
         this.returnType = Type.getType(void.class);
      }

      /**
       * Adds a parameter of a given type.
       * @param fqn the fully qualified name of the parameter type
       * @param arrayLevel the array level of the parameter type
       * @return the builder's state after the change
       */
      public Builder addParameter(String fqn, int arrayLevel) {
         this.parameters.add(Type.getType(nameToDescriptor(fqn, arrayLevel)));
         return this;
      }

      /**
       * Adds a parameter of a given type.
       * @param paramType the {@link Class} object corresponding to
       *                  the parameter type.
       * @return the builder's state after the change
       */
      public Builder addParameter(Class<?> paramType) {
         this.parameters.add(Type.getType(paramType));
         return this;
      }

      /**
       * Sets the return type to the given type.
       * @param fqn the fully qualified name of the return type
       * @param arrayLevel the array level of the return type
       * @return the builder's state after the change
       */
      public Builder setReturnType(String fqn, int arrayLevel) {
         this.returnType = Type.getType(nameToDescriptor(fqn, arrayLevel));
         return this;
      }

      /**
       * Sets the return type to the given type.
       * @param returnType the {@link Class} object corresponding to
       *                   the return type
       * @return the builder's state after the change
       */
      public Builder setReturnType(Class<?> returnType) {
         this.returnType = Type.getType(returnType);
         return this;
      }

      /**
       * Builds a {@link MethodProxy} of the given kind.
       * @return the built {@link MethodProxy}
       */
      @Override
      public MethodProxy build() {
         return new MethodProxy(name, modifiers, parent, parameters.toArray(new Type[0]), returnType);
      }
   }
}