All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.coley.cafedude.tree.visitor.writer.MethodWriter Maven / Gradle / Ivy

Go to download

Tree module for CafeDude, containing a simplified intermediate model for classes

There is a newer version: 2.1.1
Show newest version
package software.coley.cafedude.tree.visitor.writer;

import software.coley.cafedude.classfile.AttributeConstants;
import software.coley.cafedude.classfile.Method;
import software.coley.cafedude.classfile.annotation.Annotation;
import software.coley.cafedude.classfile.attribute.*;
import software.coley.cafedude.classfile.constant.CpClass;
import software.coley.cafedude.classfile.constant.CpUtf8;
import software.coley.cafedude.tree.visitor.AnnotationDefaultVisitor;
import software.coley.cafedude.tree.visitor.AnnotationVisitor;
import software.coley.cafedude.tree.visitor.CodeVisitor;
import software.coley.cafedude.tree.visitor.MethodVisitor;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * Method visitor for writing back to a {@link Method}.
 *
 * @author Justus Garbe
 */
public class MethodWriter extends DeclarationWriter implements MethodVisitor {
	private final List attributes = new ArrayList<>();
	private final List exceptions = new ArrayList<>();
	private final List parameters = new ArrayList<>();
	private final Map> visibleParameterAnnotations = new HashMap<>();
	private final Map> invisibleParameterAnnotations = new HashMap<>();
	private final Consumer callback;
	private final Method method;

	MethodWriter(Symbols symbols, int access, CpUtf8 name, CpUtf8 descriptor, Consumer callback) {
		super(symbols);
		this.method = new Method(attributes, access, name, descriptor);
		this.callback = callback;
	}

	@Override
	public void visitThrows(@Nonnull String type) {
		exceptions.add(symbols.newClass(type));
	}

	@Override
	public void visitParameter(@Nonnull String name, int access) {
		parameters.add(new MethodParametersAttribute.Parameter(
				access,
				symbols.newUtf8(name)));
	}

	@Override
	public AnnotationVisitor visitParameterAnnotation(int parameter, @Nonnull String type, boolean visible) {
		return new AnnotationWriter(symbols, values -> {
			Annotation annotation = new Annotation(symbols.newUtf8(type), values);
			Map> map = visible ? visibleParameterAnnotations : invisibleParameterAnnotations;
			map.computeIfAbsent(parameter, k -> new ArrayList<>()).add(annotation);
		});
	}

	@Nonnull
	@Override
	public CodeVisitor visitCode() {
		return new CodeWriter(symbols, attributes::add);
	}

	@Nonnull
	@Override
	public AnnotationDefaultVisitor visitAnnotationDefault() {
		return new AnnotationDefaultWriter(symbols, value -> {
			attributes.add(new AnnotationDefaultAttribute(
					symbols.newUtf8(AttributeConstants.ANNOTATION_DEFAULT),
					value));
		});
	}

	@Override
	public void visitMethodEnd() {
		super.visitDeclarationEnd();
		if (!exceptions.isEmpty()) {
			attributes.add(new ExceptionsAttribute(
					symbols.newUtf8(AttributeConstants.EXCEPTIONS),
					exceptions));
		}
		if (!parameters.isEmpty()) {
			attributes.add(new MethodParametersAttribute(
					symbols.newUtf8(AttributeConstants.METHOD_PARAMETERS),
					parameters));
		}
		if (!visibleParameterAnnotations.isEmpty()) {
			attributes.add(new ParameterAnnotationsAttribute(
					symbols.newUtf8(AttributeConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS),
					visibleParameterAnnotations,
					true));
		}
		if (!invisibleParameterAnnotations.isEmpty()) {
			attributes.add(new ParameterAnnotationsAttribute(
					symbols.newUtf8(AttributeConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS),
					invisibleParameterAnnotations,
					false));
		}
		callback.accept(method);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy