Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.strobel.assembler.metadata.MetadataParser Maven / Gradle / Ivy
/*
* MetadataParser.java
*
* Copyright (c) 2013 Mike Strobel
*
* This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain;
* and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0.
* A copy of the license can be found in the License.html file at the root of this distribution.
* By using this source code in any fashion, you are agreeing to be bound by the terms of the
* Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*/
package com.strobel.assembler.metadata;
import com.strobel.assembler.metadata.signatures.*;
import com.strobel.compilerservices.RuntimeHelpers;
import com.strobel.core.ArrayUtilities;
import com.strobel.core.SafeCloseable;
import com.strobel.core.StringUtilities;
import com.strobel.core.VerifyArgument;
import com.strobel.util.EmptyArrayCache;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Mike Strobel
*/
public final class MetadataParser {
private final IMetadataResolver _resolver;
private final SignatureParser _signatureParser;
private final Stack _genericContexts;
private final CoreMetadataFactory _factory;
private final AtomicInteger _suppressResolveDepth;
public MetadataParser() {
this(MetadataSystem.instance());
}
public MetadataParser(final IMetadataResolver resolver) {
_resolver = VerifyArgument.notNull(resolver, "resolver");
_signatureParser = SignatureParser.make();
_genericContexts = new Stack<>();
_factory = CoreMetadataFactory.make(resolver, new StackBasedGenericContext());
_suppressResolveDepth = new AtomicInteger();
}
public MetadataParser(final TypeDefinition owner) {
VerifyArgument.notNull(owner, "owner");
_resolver = owner.getResolver() != null ? owner.getResolver() : MetadataSystem.instance();
_signatureParser = SignatureParser.make();
_genericContexts = new Stack<>();
_factory = CoreMetadataFactory.make(owner, new StackBasedGenericContext());
_suppressResolveDepth = new AtomicInteger();
}
public final SafeCloseable suppressTypeResolution() {
_suppressResolveDepth.incrementAndGet();
return new SafeCloseable() {
@Override
public void close() {
_suppressResolveDepth.decrementAndGet();
}
};
}
private final class StackBasedGenericContext implements IGenericContext {
@Override
public GenericParameter findTypeVariable(final String name) {
for (int i = _genericContexts.size() - 1; i >= 0; i--) {
final IGenericContext context = _genericContexts.get(i);
final GenericParameter typeVariable = context.findTypeVariable(name);
if (typeVariable != null) {
return typeVariable;
}
}
if (_resolver instanceof IGenericContext) {
return ((IGenericContext) _resolver).findTypeVariable(name);
}
return null;
}
}
public final IMetadataResolver getResolver() {
return _resolver;
}
public void pushGenericContext(final IGenericContext context) {
_genericContexts.push(VerifyArgument.notNull(context, "context"));
}
public void popGenericContext() {
_genericContexts.pop();
}
public TypeReference parseTypeDescriptor(final String descriptor) {
VerifyArgument.notNull(descriptor, "descriptor");
if (descriptor.startsWith("[")) {
return parseTypeSignature(descriptor);
}
return parseTypeSignature("L" + descriptor + ";");
}
public TypeReference parseTypeSignature(final String signature) {
VerifyArgument.notNull(signature, "signature");
final TypeSignature typeSignature = _signatureParser.parseTypeSignature(signature);
final Reifier reifier = Reifier.make(_factory);
typeSignature.accept(reifier);
return reifier.getResult();
}
public FieldReference parseField(final TypeReference declaringType, final String name, final String signature) {
VerifyArgument.notNull(declaringType, "declaringType");
VerifyArgument.notNull(name, "name");
VerifyArgument.notNull(signature, "signature");
pushGenericContext(declaringType);
try {
return new UnresolvedField(
declaringType,
name,
parseTypeSignature(signature)
);
}
finally {
popGenericContext();
}
}
public MethodReference parseMethod(final TypeReference declaringType, final String name, final String descriptor) {
VerifyArgument.notNull(declaringType, "declaringType");
VerifyArgument.notNull(name, "name");
VerifyArgument.notNull(descriptor, "descriptor");
pushGenericContext(declaringType);
try {
final IMethodSignature signature = parseMethodSignature(descriptor);
return lookupMethod(declaringType, name, signature);
}
finally {
popGenericContext();
}
}
public TypeReference lookupType(final String packageName, final String typeName) {
// final TypeReference reference = new UnresolvedType(packageName, typeName);
final String dottedName;
if (StringUtilities.isNullOrEmpty(packageName)) {
dottedName = typeName;
}
else {
dottedName = packageName + "." + typeName;
}
final TypeReference reference = _factory.makeNamedType(dottedName);
if (_suppressResolveDepth.get() > 0) {
return reference;
}
// final TypeReference resolved = _resolver.resolve(reference);
//
// return resolved != null ? resolved : reference;
return reference;
}
/*
public TypeReference lookupType(final TypeReference declaringType, final String typeName) {
final TypeReference reference = new UnresolvedType(declaringType, typeName);
if (_suppressResolveDepth.get() > 0) {
return reference;
}
// final TypeReference resolved = _resolver.resolve(reference);
//
// return resolved != null ? resolved : reference;
return reference;
}
*/
protected TypeReference lookupTypeVariable(final String name) {
for (int i = 0, n = _genericContexts.size(); i < n; i++) {
final IGenericContext context = _genericContexts.get(i);
final TypeReference typeVariable = context.findTypeVariable(name);
if (typeVariable != null) {
return typeVariable;
}
}
if (_resolver instanceof IGenericContext) {
return ((IGenericContext) _resolver).findTypeVariable(name);
}
return null;
}
@SuppressWarnings("ConstantConditions")
public IMethodSignature parseMethodSignature(final String signature) {
VerifyArgument.notNull(signature, "signature");
final MethodTypeSignature methodTypeSignature = _signatureParser.parseMethodSignature(signature);
final Reifier reifier = Reifier.make(_factory);
final TypeReference returnType;
final List parameterTypes;
final List genericParameters;
final List thrownTypes;
final ReturnType returnTypeSignature = methodTypeSignature.getReturnType();
final TypeSignature[] parameterTypeSignatures = methodTypeSignature.getParameterTypes();
final FormalTypeParameter[] genericParameterSignatures = methodTypeSignature.getFormalTypeParameters();
final FieldTypeSignature[] thrownTypeSignatures = methodTypeSignature.getExceptionTypes();
boolean needPopGenericContext = false;
try {
if (ArrayUtilities.isNullOrEmpty(genericParameterSignatures)) {
genericParameters = Collections.emptyList();
}
else {
final GenericParameter[] gp = new GenericParameter[genericParameterSignatures.length];
pushGenericContext(
new IGenericContext() {
@Override
public GenericParameter findTypeVariable(final String name) {
for (final GenericParameter g : gp) {
if (g == null) {
break;
}
if (StringUtilities.equals(g.getName(), name)) {
return g;
}
}
return null;
}
}
);
needPopGenericContext = true;
//
// Reify generic parameters in two passes so that if a parameter has bounds depending
// on a successor parameter, the successor can be resolved.
//
for (int i = 0; i < gp.length; i++) {
gp[i] = _factory.makeTypeVariable(
genericParameterSignatures[i].getName(),
EmptyArrayCache.fromElementType(FieldTypeSignature.class)
);
}
genericParameters = ArrayUtilities.asUnmodifiableList(gp);
for (int i = 0; i < gp.length; i++) {
final FieldTypeSignature[] bounds = genericParameterSignatures[i].getBounds();
if (!ArrayUtilities.isNullOrEmpty(bounds)) {
gp[i].setExtendsBound(_factory.makeTypeBound(bounds));
}
}
}
returnTypeSignature.accept(reifier);
returnType = reifier.getResult();
if (ArrayUtilities.isNullOrEmpty(parameterTypeSignatures)) {
parameterTypes = Collections.emptyList();
}
else {
final TypeReference[] pt = new TypeReference[parameterTypeSignatures.length];
for (int i = 0; i < pt.length; i++) {
parameterTypeSignatures[i].accept(reifier);
pt[i] = reifier.getResult();
}
parameterTypes = ArrayUtilities.asUnmodifiableList(pt);
}
if (ArrayUtilities.isNullOrEmpty(thrownTypeSignatures)) {
thrownTypes = Collections.emptyList();
}
else {
final TypeReference[] tt = new TypeReference[thrownTypeSignatures.length];
for (int i = 0; i < tt.length; i++) {
thrownTypeSignatures[i].accept(reifier);
tt[i] = reifier.getResult();
}
thrownTypes = ArrayUtilities.asUnmodifiableList(tt);
}
return _factory.makeMethodSignature(returnType, parameterTypes, genericParameters, thrownTypes);
}
finally {
if (needPopGenericContext) {
popGenericContext();
}
}
}
public IClassSignature parseClassSignature(final String signature) {
VerifyArgument.notNull(signature, "signature");
final ClassSignature classSignature = _signatureParser.parseClassSignature(signature);
final Reifier reifier = Reifier.make(_factory);
final TypeReference baseType;
final List interfaceTypes;
final List genericParameters;
final ClassTypeSignature baseTypeSignature = classSignature.getSuperType();
final ClassTypeSignature[] interfaceTypeSignatures = classSignature.getInterfaces();
final FormalTypeParameter[] genericParameterSignatures = classSignature.getFormalTypeParameters();
boolean needPopGenericContext = false;
try {
if (ArrayUtilities.isNullOrEmpty(genericParameterSignatures)) {
genericParameters = Collections.emptyList();
}
else {
final GenericParameter[] gp = new GenericParameter[genericParameterSignatures.length];
pushGenericContext(
new IGenericContext() {
@Override
public GenericParameter findTypeVariable(final String name) {
for (final GenericParameter g : gp) {
if (g == null) {
break;
}
if (StringUtilities.equals(g.getName(), name)) {
return g;
}
}
return null;
}
}
);
needPopGenericContext = true;
//
// Reify generic parameters in two passes so that if a parameter has bounds depending
// on a successor parameter, the successor can be resolved.
//
for (int i = 0; i < gp.length; i++) {
gp[i] = _factory.makeTypeVariable(
genericParameterSignatures[i].getName(),
EmptyArrayCache.fromElementType(FieldTypeSignature.class)
);
}
genericParameters = ArrayUtilities.asUnmodifiableList(gp);
for (int i = 0; i < gp.length; i++) {
final FieldTypeSignature[] bounds = genericParameterSignatures[i].getBounds();
if (!ArrayUtilities.isNullOrEmpty(bounds)) {
gp[i].setExtendsBound(_factory.makeTypeBound(bounds));
}
}
}
baseTypeSignature.accept(reifier);
baseType = reifier.getResult();
if (ArrayUtilities.isNullOrEmpty(interfaceTypeSignatures)) {
interfaceTypes = Collections.emptyList();
}
else {
final TypeReference[] it = new TypeReference[interfaceTypeSignatures.length];
for (int i = 0; i < it.length; i++) {
interfaceTypeSignatures[i].accept(reifier);
it[i] = reifier.getResult();
}
interfaceTypes = ArrayUtilities.asUnmodifiableList(it);
}
return _factory.makeClassSignature(baseType, interfaceTypes, genericParameters);
}
finally {
if (needPopGenericContext) {
popGenericContext();
}
}
}
protected MethodReference lookupMethod(final TypeReference declaringType, final String name, final IMethodSignature signature) {
final MethodReference reference = new UnresolvedMethod(
declaringType,
name,
signature
);
if (_suppressResolveDepth.get() > 0) {
return reference;
}
// final MethodReference resolved = _resolver.resolve(reference);
//
// return resolved != null ? resolved : reference;
return reference;
}
//
@SuppressWarnings("MismatchedReadAndWriteOfArray")
private final static TypeReference[] PRIMITIVE_TYPES = new TypeReference[16];
static {
RuntimeHelpers.ensureClassInitialized(MetadataSystem.class);
final TypeReference[] allPrimitives = {
BuiltinTypes.Boolean,
BuiltinTypes.Byte,
BuiltinTypes.Character,
BuiltinTypes.Short,
BuiltinTypes.Integer,
BuiltinTypes.Long,
BuiltinTypes.Float,
BuiltinTypes.Double,
BuiltinTypes.Void
};
for (final TypeReference t : allPrimitives) {
PRIMITIVE_TYPES[hashPrimitiveName(t.getName())] = t;
}
}
private static int hashPrimitiveName(final String name) {
if (name.length() < 3) {
return 0;
}
return (name.charAt(0) + name.charAt(2)) % 16;
}
//
//
private final class UnresolvedMethod extends MethodReference {
private final TypeReference _declaringType;
private final String _name;
private final IMethodSignature _signature;
private final List _genericParameters;
UnresolvedMethod(final TypeReference declaringType, final String name, final IMethodSignature signature) {
_declaringType = VerifyArgument.notNull(declaringType, "declaringType");
_name = VerifyArgument.notNull(name, "name");
_signature = VerifyArgument.notNull(signature, "signature");
if (_signature.hasGenericParameters()) {
final GenericParameterCollection genericParameters = new GenericParameterCollection(this);
for (final GenericParameter genericParameter : _signature.getGenericParameters()) {
genericParameters.add(genericParameter);
}
genericParameters.freeze(false);
_genericParameters = genericParameters;
}
else {
_genericParameters = Collections.emptyList();
}
}
@Override
public String getName() {
return _name;
}
@Override
public TypeReference getReturnType() {
return _signature.getReturnType();
}
@Override
public List getParameters() {
return _signature.getParameters();
}
@Override
public TypeReference getDeclaringType() {
return _declaringType;
}
@Override
public List getGenericParameters() {
return _genericParameters;
}
@Override
public List getThrownTypes() {
return _signature.getThrownTypes();
}
}
//
//
private final class UnresolvedField extends FieldReference {
private final TypeReference _declaringType;
private final String _name;
private final TypeReference _fieldType;
UnresolvedField(final TypeReference declaringType, final String name, final TypeReference fieldType) {
_declaringType = VerifyArgument.notNull(declaringType, "declaringType");
_name = VerifyArgument.notNull(name, "name");
_fieldType = VerifyArgument.notNull(fieldType, "fieldType");
}
@Override
public String getName() {
return _name;
}
@Override
public TypeReference getDeclaringType() {
return _declaringType;
}
@Override
public TypeReference getFieldType() {
return _fieldType;
}
@Override
protected StringBuilder appendName(final StringBuilder sb, final boolean fullName, final boolean dottedName) {
if (fullName) {
final TypeReference declaringType = getDeclaringType();
if (declaringType != null) {
return declaringType.appendName(sb, true, false).append('.').append(_name);
}
}
return sb.append(_name);
}
}
/*
private final class UnresolvedGenericType extends TypeReference implements IGenericInstance {
private final TypeReference _genericDefinition;
private final List _typeParameters;
UnresolvedGenericType(final TypeReference genericDefinition, final List typeParameters) {
_genericDefinition = genericDefinition;
_typeParameters = typeParameters;
}
@Override
public TypeReference getElementType() {
return null;
}
@Override
public String getName() {
return _genericDefinition.getName();
}
@Override
public String getPackageName() {
return _genericDefinition.getPackageName();
}
@Override
public TypeReference getDeclaringType() {
return _genericDefinition.getDeclaringType();
}
@Override
public String getSimpleName() {
return _genericDefinition.getSimpleName();
}
@Override
public String getFullName() {
return _genericDefinition.getFullName();
}
@Override
public String getInternalName() {
return _genericDefinition.getInternalName();
}
@Override
public boolean isGenericDefinition() {
return false;
}
@Override
public List getGenericParameters() {
return _genericDefinition.getGenericParameters();
}
@Override
public boolean hasTypeArguments() {
return true;
}
@Override
public List getTypeArguments() {
return _typeParameters;
}
@Override
public IGenericParameterProvider getGenericDefinition() {
return _genericDefinition;
}
@Override
public TypeReference getUnderlyingType() {
return _genericDefinition;
}
@Override
public TypeDefinition resolve() {
return _resolver.resolve(this);
}
@Override
public FieldDefinition resolve(final FieldReference field) {
return _resolver.resolve(field);
}
@Override
public MethodDefinition resolve(final MethodReference method) {
return _resolver.resolve(method);
}
@Override
public TypeDefinition resolve(final TypeReference type) {
return _resolver.resolve(type);
}
}
*/
/*
private final class UnresolvedType extends TypeReference {
private final String _name;
private final String _packageName;
private final TypeReference _declaringType;
private final GenericParameterCollection _genericParameters;
private String _fullName;
private String _internalName;
UnresolvedType(final TypeReference declaringType, final String name) {
_name = VerifyArgument.notNull(name, "name");
_packageName = StringUtilities.EMPTY;
_declaringType = VerifyArgument.notNull(declaringType, "declaringType");
_genericParameters = new GenericParameterCollection(this);
}
UnresolvedType(final String packageName, final String name) {
_packageName = VerifyArgument.notNull(packageName, "packageName");
_name = VerifyArgument.notNull(name, "name");
_declaringType = null;
_genericParameters = new GenericParameterCollection(this);
}
UnresolvedType(final TypeReference declaringType, final String name, final List genericParameters) {
_name = VerifyArgument.notNull(name, "name");
_packageName = StringUtilities.EMPTY;
_declaringType = VerifyArgument.notNull(declaringType, "declaringType");
_genericParameters = new GenericParameterCollection(this);
for (final GenericParameter genericParameter : genericParameters) {
_genericParameters.add(genericParameter);
}
}
UnresolvedType(final String packageName, final String name, final List genericParameters) {
_packageName = VerifyArgument.notNull(packageName, "packageName");
_name = VerifyArgument.notNull(name, "name");
_declaringType = null;
_genericParameters = new GenericParameterCollection(this);
for (final GenericParameter genericParameter : genericParameters) {
_genericParameters.add(genericParameter);
}
}
@Override
public String getName() {
return _name;
}
@Override
public String getPackageName() {
return _packageName;
}
public String getFullName() {
if (_fullName == null) {
final StringBuilder name = new StringBuilder();
appendName(name, true, true);
_fullName = name.toString();
}
return _fullName;
}
public String getInternalName() {
if (_internalName == null) {
final StringBuilder name = new StringBuilder();
appendName(name, true, false);
_internalName = name.toString();
}
return _internalName;
}
@Override
public boolean isAnonymous() {
return _declaringType != null && _shortName == null;
}
@Override
public TypeReference getDeclaringType() {
return _declaringType;
}
@Override
public String getSimpleName() {
return _name;
}
@Override
public boolean isGenericDefinition() {
return hasGenericParameters();
}
@Override
public List getGenericParameters() {
return _genericParameters;
}
@Override
public TypeReference makeGenericType(final List typeArguments) {
VerifyArgument.notEmpty(typeArguments, "typeArguments");
VerifyArgument.noNullElements(typeArguments, "typeArguments");
// final TypeDefinition resolved = this.resolve();
return new UnresolvedGenericType(
// resolved != null ? resolved : this,
this,
ArrayUtilities.asUnmodifiableList(typeArguments.toArray(new TypeReference[typeArguments.size()]))
);
}
@Override
public TypeReference makeGenericType(final TypeReference... typeArguments) {
VerifyArgument.notEmpty(typeArguments, "typeArguments");
VerifyArgument.noNullElements(typeArguments, "typeArguments");
// final TypeDefinition resolved = this.resolve();
return new UnresolvedGenericType(
// resolved != null ? resolved : this,
this,
ArrayUtilities.asUnmodifiableList(typeArguments.clone())
);
}
@Override
public TypeDefinition resolve() {
return _resolver.resolve(this);
}
@Override
public FieldDefinition resolve(final FieldReference field) {
return _resolver.resolve(field);
}
@Override
public MethodDefinition resolve(final MethodReference method) {
return _resolver.resolve(method);
}
@Override
public TypeDefinition resolve(final TypeReference type) {
return _resolver.resolve(type);
}
}
*/
//
}