@Override
	public void transform(@Nonnull JvmTransformerContext context, @Nonnull Workspace workspace,
	                      @Nonnull WorkspaceResource resource, @Nonnull JvmClassBundle bundle,
	                      @Nonnull JvmClassInfo initialClassState) throws TransformationException {
		StaticValues valuesContainer = new StaticValues();
		EffectivelyFinalFields finalContainer = new EffectivelyFinalFields();

		// TODO: Make some config options for this
		//  - Option to make unsafe assumptions
		//    - treat all effectively final candidates as actually final
		//  - Option to scan other classes for references to our fields to have more thorough 'effective-final' checking
		//    - will be slower, but it will be opt-in and off by default

		// Populate initial values based on field's default value attribute
		for (FieldMember field : initialClassState.getFields()) {
			if (!field.hasStaticModifier())
				continue;

			// Add to effectively-final container if it is 'static final'
			// If the field is private add it to the "maybe" effectively-final list, and we'll confirm it later
			if (field.hasFinalModifier())
				finalContainer.add(field.getName(), field.getDescriptor());
			else if (field.hasPrivateModifier())
				// We can only assume private fields are effectively-final if nothing outside the <clinit> writes to them.
				// Any other level of access can be written to by child classes or classes in the same package.
				finalContainer.addMaybe(field.getName(), field.getDescriptor());
			// TODO: As mentioned above, we can add another 'else' case here for non-private fields
			//  but then we need to make sure no other classes write to those fields. So its more computational work...

			// Skip if there is no default value
			Object defaultValue = field.getDefaultValue();
			if (defaultValue == null)
				continue;

			// Skip if the value cannot be mapped to our representation
			ReValue mappedValue = Unchecked.getOr(() -> ReValue.ofConstant(defaultValue), null);
			if (mappedValue == null)
				continue;

			// Store the value
			valuesContainer.put(field.getName(), field.getDescriptor(), mappedValue);
		}

		// Visit <clinit> of classes and collect static field values of primitives
		String className = initialClassState.getName();
		if (initialClassState.getDeclaredMethod("<clinit>", "()V") != null) {
			ClassNode node = context.getNode(bundle, initialClassState);

			// Find the static initializer and determine which fields are "effectively-final"
			MethodNode clinit = null;
			for (MethodNode method : node.methods) {
				if ((method.access & Opcodes.ACC_STATIC) != 0 && method.name.equals("<clinit>") && method.desc.equals("()V")) {
					clinit = method;
				} else if (method.instructions != null) {
					// Any put-static to a field in our class means it is not effectively-final because the method is not the static initializer
					for (AbstractInsnNode instruction : method.instructions) {
						if (instruction.getOpcode() == Opcodes.PUTSTATIC && instruction instanceof FieldInsnNode fieldInsn) {
							// Skip if not targeting our class
							if (!fieldInsn.owner.equals(className))
								continue;
							String fieldName = fieldInsn.name;
							String fieldDesc = fieldInsn.desc;
							finalContainer.removeMaybe(fieldName, fieldDesc);
						}
					}
				}
			}
			finalContainer.commitMaybeIntoEffectivelyFinals();

			// Only analyze if we see static setters
			if (clinit != null && hasStaticSetters(clinit)) {
				try {
					ReAnalyzer analyzer = context.newAnalyzer(inheritanceGraph, node, clinit);
					ReInterpreter interpreter = analyzer.getInterpreter();
					Frame<ReValue>[] frames = analyzer.analyze(node.name, clinit);
					AbstractInsnNode[] instructions = clinit.instructions.toArray();
					for (int i = 0; i < instructions.length; i++) {
						AbstractInsnNode instruction = instructions[i];
						if (instruction.getOpcode() == Opcodes.PUTSTATIC && instruction instanceof FieldInsnNode fieldInsn) {
							// Skip if not targeting our class
							if (!fieldInsn.owner.equals(className))
								continue;

							// Skip if the field is not final, or effectively final
							String fieldName = fieldInsn.name;
							String fieldDesc = fieldInsn.desc;
							if (!finalContainer.contains(fieldName, fieldDesc))
								continue;

							// Merge the static value state
							Frame<ReValue> frame = frames[i];
							ReValue existingValue = valuesContainer.get(fieldName, fieldDesc);
							ReValue stackValue = frame.getStack(frame.getStackSize() - 1);
							ReValue merged = existingValue == null ? stackValue : interpreter.merge(existingValue, stackValue);
							valuesContainer.put(fieldName, fieldDesc, merged);
						}
					}

					// Any static final fields that have not been assigned are assumed to contain their default values.
					valuesContainer.commitRemainingAsDefaults(finalContainer);
				} catch (Throwable t) {
					throw new TransformationException("Error encountered when computing static constants", t);
				}
			}
		} else {
			// If there is no static initializer, then assume the values are defaults (o for primitives, null for objects)
			try {
				valuesContainer.commitRemainingAsDefaults(finalContainer);
			} catch (IllegalValueException ex) {
				throw new TransformationException("Error encountered when computing default constant values", ex);
			}
		}

		// Record the values for the target class if we recorded at least one value
		if (!valuesContainer.staticFieldValues.isEmpty())
			classValues.put(className, valuesContainer);
	}
@param className
		Name of class defining the field.
@param fieldName
		Field name.
@param fieldDesc
		Field descriptor.

@return Static value wrapper if known, otherwise {@code null}.
recaf-core/src/main/java/software/coley/recaf/services/deobfuscation/transform/generic/StaticValueCollectionTransformer.java