package me.coley.recaf.search;

import org.objectweb.asm.*;

/**
 * Visitor that adds matched results in annotations to a result collector.
 *
 * @author Matt
 */
public class SearchAnnotationVisitor extends AnnotationVisitor {
	private final SearchCollector collector;
	private final Context.AnnotationContext context;

	/**
	 * Constructs an annotation search visitor.
	 *
	 * @param collector
	 * 		Result collector.
	 * @param context
	 * 		Current search context.
	 * @param descriptor
	 * 		Annotation type.
	 */
	public SearchAnnotationVisitor(SearchCollector collector, Context<?> context, String
			descriptor) {
		super(Opcodes.ASM7);
		this.collector = collector;
		this.context = context.withAnno(descriptor);
		collector.queries(ClassReferenceQuery.class)
				.forEach(q -> {
					String type = Type.getType(descriptor).getInternalName();
					q.match(collector.getAccess(type, Opcodes.ACC_ANNOTATION), type);
					collector.addMatched(this.context, q);
				});
	}

	@Override
	public void visit(String name, Object value) {
		// Skip null
		if (value == null) {
			return;
		}
		if (value instanceof String) {
			collector.queries(StringQuery.class)
					.forEach(q -> {
						q.match((String) value);
						collector.addMatched(null, q);
					});
		} else if (value instanceof Number) {
			// TODO: Value
		} else if (value instanceof Character){
			// TODO: Value
		} else if (value.getClass().isArray()) {
			if (value instanceof int[]) {
				// TODO: Value
			}
		}
	}

	@Override
	public void visitEnum(String name, String descriptor, String value) {
		collector.queries(ClassReferenceQuery.class)
				.forEach(q -> {
					String type = Type.getType(descriptor).getInternalName();
					q.match(collector.getAccess(type, Opcodes.ACC_ANNOTATION), type);
					collector.addMatched(context, q);
				});
		collector.queries(StringQuery.class)
				.forEach(q -> {
					q.match(value);
					collector.addMatched(null, q);
				});
	}

	@Override
	public AnnotationVisitor visitAnnotation(String name, String descriptor) {
		return new SearchAnnotationVisitor(collector, context, descriptor);
	}

	@Override
	public AnnotationVisitor visitArray(final String name) {
		return this;
	}
}
@@ -54,16 +54,49 @@
 asm.*;%0A%0A
+import java.lang.reflect.Array;%0A%0A
 /**%0A * V
@@ -1335,182 +1335,685 @@
 %0A%09%09%09
-// TODO: Value%0A%09%09%7D else if (value instanceof Character)%7B%0A%09%09%09// TODO: Value%0A%09%09%7D else if (value.getClass().isArray()) %7B%0A%09%09%09if (value instanceof int%5B%5D)
+collector.queries(ValueQuery.class)%0A%09%09%09%09%09.forEach(q -%3E %7B%0A%09%09%09%09%09%09q.match(value);%0A%09%09%09%09%09%09collector.addMatched(context, q);%0A%09%09%09%09%09%7D);%0A%09%09%7D else if (value instanceof Character)%7B%0A%09%09%09int cval = (int) value;%0A%09%09%09collector.queries(ValueQuery.class)%0A%09%09%09%09%09.forEach(q -%3E %7B%0A%09%09%09%09%09%09q.match(cval);%0A%09%09%09%09%09%09collector.addMatched(context, q);%0A%09%09%09%09%09%7D);%0A%09%09%7D else if (value.getClass().isArray()) %7B%0A%09%09%09int length = Array.getLength(value);%0A%09%09%09Object%5B%5D array = new Object%5Blength%5D;%0A%09%09%09for(int i = 0; i %3C length; i++)%0A%09%09%09%09array%5Bi%5D = Array.get(value, i);%0A%09%09%09collector.queries(ValueQuery.class)%0A%09%09%09%09%09.forEach(q -%3E
  %7B%0A%09%09%09%09
+%09
-// TODO: Value%0A%09%09%09%7D
+%09for (Object i : array)%0A%09%09%09%09%09%09%09q.match(i);%0A%09%09%09%09%09%09collector.addMatched(context, q);%0A%09%09%09%09%09%7D);
 %0A%09%09%7D

Add value search to annotaiton search