/*
* Copyright (c) 2006 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.util;
import javax.annotation.*;
import mockit.external.asm.*;
import mockit.internal.*;
import mockit.internal.state.*;
import static mockit.external.asm.ClassReader.*;
import static mockit.external.asm.Opcodes.*;
public final class ParameterNameExtractor extends ClassVisitor
{
@Nonnull private String classDesc;
@Nonnegative private int memberAccess;
@Nonnull private String memberName;
@Nonnull private String memberDesc;
public ParameterNameExtractor()
{
classDesc = memberName = memberDesc = "";
}
@Nonnull
public String extractNames(@Nonnull Class<?> classOfInterest)
{
String className = classOfInterest.getName();
classDesc = className.replace('.', '/');
if (!ParameterNames.hasNamesForClass(classDesc)) {
// Reads class from file, since JRE 1.6 (but not 1.7) discards parameter names on retransformation.
ClassReader cr = ClassFile.readFromFile(classDesc);
cr.accept(this, SKIP_FRAMES);
}
return classDesc;
}
@Nullable @Override
public MethodVisitor visitMethod(
int access, @Nonnull String name, @Nonnull String desc, @Nullable String signature, @Nullable String[] exceptions)
{
if ((access & ACC_SYNTHETIC) == 0) {
memberAccess = access;
memberName = name;
memberDesc = desc;
return new MethodOrConstructorVisitor();
}
return null;
}
private final class MethodOrConstructorVisitor extends MethodVisitor
{
@Override
public void visitLocalVariable(
@Nonnull String name, @Nonnull String desc, String signature, Label start, Label end, @Nonnegative int index)
{
ParameterNames.registerName(classDesc, memberAccess, memberName, memberDesc, desc, name, index);
}
}
}