/** * Creates a method rebase resolver which is only capable of rebasing constructors if the * instrumented methods suggest this. * * @param instrumentedMethods The instrumented methods to consider for rebasement. * @param instrumentedType The instrumented type. * @param classFileVersion The class file version to define a potential auxiliary type in. * @param auxiliaryTypeNamingStrategy A naming strategy to apply when naming an auxiliary type. * @param methodNameTransformer The method name transformer to use. * @return Returns a method rebase resolver that is capable of rebasing any of the instrumented * methods. */ public static MethodRebaseResolver make( MethodList<?> instrumentedMethods, TypeDescription instrumentedType, ClassFileVersion classFileVersion, AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy, MethodNameTransformer methodNameTransformer) { return instrumentedMethods.filter(isConstructor()).isEmpty() ? MethodsOnly.of(instrumentedMethods, methodNameTransformer) : of( instrumentedMethods, TrivialType.INSTANCE.make( auxiliaryTypeNamingStrategy.name(TrivialType.INSTANCE, instrumentedType), classFileVersion, AuxiliaryType.MethodAccessorFactory.Illegal.INSTANCE), methodNameTransformer); }
/* * Initializes the methods of the annotation that is read by this binder. */ static { MethodList<MethodDescription.InDefinedShape> methodList = new TypeDescription.ForLoadedType(FieldValue.class).getDeclaredMethods(); DEFINING_TYPE = methodList.filter(named("definingType")).getOnly(); FIELD_NAME = methodList.filter(named("value")).getOnly(); }
@Override public MethodRegistry.Prepared prepare( InstrumentedType instrumentedType, MethodGraph.Compiler methodGraphCompiler, LatentMethodMatcher methodFilter) { LinkedHashMap<MethodDescription, Prepared.Entry> implementations = new LinkedHashMap<MethodDescription, Prepared.Entry>(); Set<Handler> handlers = new HashSet<Handler>(entries.size()); MethodList<?> helperMethods = instrumentedType.getDeclaredMethods(); for (Entry entry : entries) { if (handlers.add(entry.getHandler())) { instrumentedType = entry.getHandler().prepare(instrumentedType); ElementMatcher<? super MethodDescription> handledMethods = noneOf(helperMethods); helperMethods = instrumentedType.getDeclaredMethods(); for (MethodDescription helperMethod : helperMethods.filter(handledMethods)) { implementations.put(helperMethod, entry.asSupplementaryEntry(helperMethod)); } } } MethodGraph.Linked methodGraph = methodGraphCompiler.compile(instrumentedType); // Casting required for Java 6 compiler. ElementMatcher<? super MethodDescription> relevanceMatcher = (ElementMatcher<? super MethodDescription>) not(anyOf(implementations.keySet())).and(methodFilter.resolve(instrumentedType)); for (MethodGraph.Node node : methodGraph.listNodes()) { MethodDescription methodDescription = node.getRepresentative(); boolean visibilityBridge = instrumentedType.isPublic() && !instrumentedType.isInterface(); if (relevanceMatcher.matches(methodDescription)) { for (Entry entry : entries) { if (entry.resolve(instrumentedType).matches(methodDescription)) { implementations.put( methodDescription, entry.asPreparedEntry( instrumentedType, methodDescription, node.getMethodTypes())); visibilityBridge = false; break; } } } if (visibilityBridge && methodDescription.isPublic() && !(methodDescription.isAbstract() || methodDescription.isFinal()) && !node.getSort().isMadeVisible() && methodDescription.getDeclaringType().asErasure().isPackagePrivate()) { // Visibility bridges are required for public types that inherit a public method from a // package-private type. // Checking the last condition contradicts any method that is defined by the instrumented // type itself. implementations.put( methodDescription, Prepared.Entry.forVisibilityBridge(methodDescription, node.getMethodTypes())); } } MethodDescription typeInitializer = new MethodDescription.Latent.TypeInitializer(instrumentedType); for (Entry entry : entries) { if (entry.resolve(instrumentedType).matches(typeInitializer)) { implementations.put( typeInitializer, entry.asPreparedEntry( instrumentedType, typeInitializer, Collections.<MethodDescription.TypeToken>emptySet())); break; } } return new Prepared( implementations, instrumentedType.getLoadedTypeInitializer(), instrumentedType.getTypeInitializer(), instrumentedType.asErasure(), methodGraph); }