Java tutorial
/* * Copyright 2014-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.jvm.java.abi; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import java.util.SortedSet; import javax.annotation.Nullable; class MethodMirror extends MethodVisitor implements Comparable<MethodMirror> { private final String name; private final String desc; private final String signature; private final int access; private final String[] exceptions; private final SortedSet<AnnotationMirror> annotations; private final AnnotationMirror[] parameterAnnotations; @Nullable private AnnotationDefaultValueMirror annotationDefault; private final String key; public MethodMirror(int access, String name, String desc, String signature, String[] exceptions) { super(Opcodes.ASM5); this.access = access; this.name = name; this.desc = Preconditions.checkNotNull(desc); this.signature = signature; this.exceptions = exceptions; this.annotations = Sets.newTreeSet(); int paramCount = countParameters(desc); this.parameterAnnotations = new AnnotationMirror[paramCount]; this.key = name + desc + paramCount; } private int countParameters(String desc) { int count = 0; char[] chars = desc.toCharArray(); // Find the opening parenthesis. int i = 0; while (i < chars.length && chars[i] != '(') { i++; } i++; // We stopped on the '(' // Now iterate, counting the parameter types until we find the closing parenthesis. for (; i < chars.length && chars[i] != ')'; i++) { switch (chars[i]) { // Base types as defined in // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3) case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': count++; break; // Array type case '[': // The array type is defined as "[ ComponentType". This means that we don't want to // increment the parameter count yet, as it'll happen in the next iteration through this // loop. break; // Class type case 'L': count++; // Skip forward to the next ";" while (chars[i] != ';') { i++; } break; default: throw new RuntimeException("Unknown parameter type: " + chars[i]); } } return count; } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { AnnotationMirror mirror = new AnnotationMirror(desc, visible); annotations.add(mirror); return mirror; } @Override public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { AnnotationMirror mirror = new AnnotationMirror(desc, visible); parameterAnnotations[parameter] = mirror; return mirror; } @Override public AnnotationVisitor visitAnnotationDefault() { annotationDefault = new AnnotationDefaultValueMirror(); return annotationDefault; } @Override public int compareTo(MethodMirror o) { if (this == o) { return 0; } return key.compareTo(o.key); } public void appendTo(ClassWriter writer) { MethodVisitor method = writer.visitMethod(access, name, desc, signature, exceptions); for (AnnotationMirror annotation : annotations) { annotation.appendTo(method); } for (int i = 0; i < parameterAnnotations.length; i++) { AnnotationMirror annotation = parameterAnnotations[i]; if (annotation == null) { continue; } annotation.appendTo(method, i); } if (annotationDefault != null) { annotationDefault.appendTo(method); } method.visitEnd(); } }