/** * Returns a {@code static}, {@code final} field constant. * * @param fieldDescription The field to represent a value of. * @return A dynamically resolved field value constant. */ public static Dynamic ofField(FieldDescription.InDefinedShape fieldDescription) { if (!fieldDescription.isStatic() || !fieldDescription.isFinal()) { throw new IllegalArgumentException("Field must be static and final: " + fieldDescription); } boolean selfDeclared = fieldDescription.getType().isPrimitive() ? fieldDescription.getType().asErasure().asBoxed().equals(fieldDescription.getType().asErasure()) : fieldDescription.getDeclaringType().equals(fieldDescription.getType().asErasure()); return new Dynamic(new ConstantDynamic(fieldDescription.getInternalName(), fieldDescription.getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "getStaticFinal", selfDeclared ? "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;" : "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;", false), selfDeclared ? new Object[0] : new Object[]{Type.getType(fieldDescription.getDeclaringType().getDescriptor())}), fieldDescription.getType().asErasure()); }
@Override public final StackManipulationToken stackManipulationToken() { return new SmtCombined( new SmtStatic( new TextConstant(", ") ), new SmtArray( new TypeDescription.ForLoadedType(CharSequence.class), List.of(type) .flatMap(TypeDescription::getDeclaredFields) .filter(f -> !f.isStatic()) .<StackManipulationToken>map(SmtAtomFieldToString::new) .prepend(new SmtAtomTypeToString(type)) .toJavaArray(i -> new StackManipulationToken[i]) ), new SmtInvokeMethod( new TypeDescription.ForLoadedType(String.class), new ConjunctionMatcher<>( ElementMatchers.named("join"), ElementMatchers.takesArguments(2), ElementMatchers.takesArgument(0, CharSequence.class), ElementMatchers.takesArgument(1, CharSequence[].class), ElementMatchers.returns(String.class) ) ) ); } }
@Override public final StackManipulationToken stackManipulationToken() { NaturalJavaAtom naturalMatcher = new NaturalJavaAtom(); return new SmtArray( List.of(type) .flatMap(TypeDescription::getDeclaredFields) .filter(f -> !f.isStatic()) .filter(f -> !naturalMatcher.matches(f.getType().asErasure())) .map(f -> new SmtLoadField(f)) .toJavaArray(SmtLoadField.class) ); } }
@Override public final StackManipulationToken stackManipulationToken() { NaturalJavaAtom naturalMatcher = new NaturalJavaAtom(); return new SmtArray( List.of(type) .flatMap(TypeDescription::getDeclaredFields) .filter(f -> !f.isStatic()) .filter(f -> naturalMatcher.matches(f.getType().asErasure())) .map(f -> new SmtLoadField(f)) .toJavaArray(SmtLoadField.class) ); } }
@Override public final StackManipulationToken stackManipulationToken() { return new SmtCombined( List.of(type) .flatMap(TypeDescription::getDeclaredFields) .filter(f -> !f.isStatic()) .map(f -> new SmtCheckAtomFieldEquality(type, f)) .toJavaArray(SmtCheckAtomFieldEquality.class) ); } }
/** * Resolves a var handle constant for a field. * * @param fieldDescription The field to represent a var handle for. * @return A dynamic constant that represents the created var handle constant. */ public static JavaConstant ofVarHandle(FieldDescription.InDefinedShape fieldDescription) { return new Dynamic(new ConstantDynamic(fieldDescription.getInternalName(), JavaType.VAR_HANDLE.getTypeStub().getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, fieldDescription.isStatic() ? "staticFieldVarHandle" : "fieldVarHandle", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;", false), Type.getType(fieldDescription.getDeclaringType().getDescriptor()), Type.getType(fieldDescription.getType().asErasure().getDescriptor())), JavaType.VAR_HANDLE.getTypeStub()); }
/** * Creates an accessor to read an enumeration value. * * @param enumerationDescription The description of the enumeration. * @return A stack manipulation for reading the enumeration. */ public static StackManipulation forEnumeration(EnumerationDescription enumerationDescription) { FieldList<FieldDescription.InDefinedShape> fieldList = enumerationDescription.getEnumerationType() .getDeclaredFields() .filter(named(enumerationDescription.getValue())); return fieldList.size() != 1 || !fieldList.getOnly().isStatic() || !fieldList.getOnly().isPublic() || !fieldList.getOnly().isEnum() ? StackManipulation.Illegal.INSTANCE : STATIC.new AccessDispatcher(fieldList.getOnly()).read(); }
/** * Extracts a handle type for a setter of the given field. * * @param fieldDescription The field for which to create a setter handle. * @return The corresponding handle type. */ protected static HandleType ofSetter(FieldDescription.InDefinedShape fieldDescription) { return fieldDescription.isStatic() ? PUT_STATIC_FIELD : PUT_FIELD; }
/** * Extracts a handle type for a getter of the given field. * * @param fieldDescription The field for which to create a getter handle. * @return The corresponding handle type. */ protected static HandleType ofGetter(FieldDescription.InDefinedShape fieldDescription) { return fieldDescription.isStatic() ? GET_STATIC_FIELD : GET_FIELD; }
/** * Creates a field access representation for a given field. * * @param fieldDescription The field to be accessed. * @return A field access definition for the given field. */ public static Defined forField(FieldDescription.InDefinedShape fieldDescription) { return fieldDescription.isStatic() ? STATIC.new AccessDispatcher(fieldDescription) : INSTANCE.new AccessDispatcher(fieldDescription); }