Permalink
Switch branches/tags
version-2.9.0 version-2.8.2 version-2.8.0 version-2.7.0-beta3 version-2.6.0-beta3 version-2.4.0 version-2.3.5 version-2.3.4 version-2.3.2 version-2.3.2-beta1 version-2.3.0-beta3 version-2.3.0-beta2 version-2.3.0-beta1 version-2.2.0 version-2.1.0 version-2.0.0 version-2.0.0-rc4 version-2.0.0-rc3 version-2.0.0-rc2 version-2.0.0-rc version-2.0.0-beta5 version-2.0.0-beta4 version-2.0.0-beta3 version-2.0.0-beta1 version-1.3.2 version-1.3.1 version-1.3.0 version-1.3.0-beta1-20160429-01 version-1.2.2 version-1.2.1 version-1.2.0 version-1.2.0-beta1-20160108-01 version-1.2.0-beta version-1.2.0-beta-20151211-01 version-1.1.1 version-1.1.0 version-1.1.0-rc1-20151109-01 version-1.0.0 version-1.0.0-beta1-20141031-01 toolset_5 toolset_3 toolset_2 toolset_1_1 toolset_1 Visual.Studio.2015.Update.1.RC Visual.Studio.2015.Update.1.CTP Visual-Studio-2017 Visual-Studio-2017-Version-15.8 Visual-Studio-2017-Version-15.7.2 Visual-Studio-2017-Version-15.7 Visual-Studio-2017-Version-15.6 Visual-Studio-2017-Version-15.5 Visual-Studio-2017-Version-15.4 Visual-Studio-2017-Version-15.3.5 Visual-Studio-2017-Version-15.3.4 Visual-Studio-2017-Version-15.3.2 Visual-Studio-2017-Version-15.3 Visual-Studio-2017-Version-15.2 Visual-Studio-2017-Version-15.1 Visual-Studio-2017-RC4 Visual-Studio-2017-RC3 Visual-Studio-2017-RC2 Visual-Studio-2017-RC Visual-Studio-2017-Preview-Version-15.3 Visual-Studio-2017-Preview-6-Version-15.7 Visual-Studio-2017-Preview-3-Version-15.4 Visual-Studio-2017-Preview-3-Version-15.3 Visual-Studio-2017-Preview-2-Version-15.4 Visual-Studio-2017-Preview-2-Version-15.3 Visual-Studio-2017-Preview-1-Version-15.4 Visual-Studio-2015 Visual-Studio-2015-Update-3 Visual-Studio-2015-Update-3-Micro-Update-1 Visual-Studio-2015-Update-2 Visual-Studio-2015-Update-2-RC Visual-Studio-2015-Update-2-Micro-Update-3 Visual-Studio-2015-Update-2-Micro-Update-1 Visual-Studio-2015-Update-1 Visual-Studio-2015-Update-1-RC Visual-Studio-2015-Update-1-CTP Visual-Studio-2015-RC Visual-Studio-2015-Preview Visual-Studio-2015-CTP-6 Visual-Studio-2015-CTP-5 Visual-Studio-15-Preview Visual-Studio-15-Preview-5 Visual-Studio-15-Preview-4 Visual-Studio-15-Preview-3 VS.Toolset.Roslyn.1.1.0-beta1-20150727-01 VS.Tools.X86.Managed.V45.1.0.150513.2 Oss.Scan.2015.03.13 Oss.Scan.2013.03.13 NetFx.Toolset.150729
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
307 lines (288 sloc) 12.3 KB
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Reflection.Metadata;
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
internal struct MetadataDecoder
{
private readonly MetadataReader _reader;
private readonly ImmutableArray<string> _allTypeParameters;
private readonly int _containingArity;
private readonly ImmutableArray<string> _methodTypeParameters;
internal MetadataDecoder(
MetadataReader reader,
ImmutableArray<string> allTypeParameters,
int containingArity,
ImmutableArray<string> methodTypeParameters)
{
_reader = reader;
_allTypeParameters = allTypeParameters;
_containingArity = containingArity;
_methodTypeParameters = methodTypeParameters;
}
// cf. MetadataDecoder<>.GetSignatureForMethod.
internal ImmutableArray<ParameterSignature> DecodeParameters(MethodDefinition methodDef)
{
var signatureReader = _reader.GetBlobReader(methodDef.Signature);
var signatureHeader = signatureReader.ReadSignatureHeader();
var typeParameterCount = signatureHeader.IsGeneric ? signatureReader.ReadCompressedInteger() : 0;
var parameterCount = signatureReader.ReadCompressedInteger();
var builder = ImmutableArray.CreateBuilder<ParameterSignature>(parameterCount);
var returnType = DecodeParameter(ref signatureReader);
for (int i = 0; i < parameterCount; i++)
{
builder.Add(DecodeParameter(ref signatureReader));
}
return builder.ToImmutable();
}
// cf. MetadataDecoder<>.DecodeParameterOrThrow.
private ParameterSignature DecodeParameter(ref BlobReader signatureReader)
{
bool isByRef = false;
while (true)
{
var typeCode = signatureReader.ReadSignatureTypeCode();
switch (typeCode)
{
case SignatureTypeCode.RequiredModifier:
case SignatureTypeCode.OptionalModifier:
// Skip modifiers.
break;
case SignatureTypeCode.ByReference:
isByRef = true;
break;
default:
var type = DecodeType(ref signatureReader, typeCode);
return new ParameterSignature(type, isByRef);
}
}
}
// cf. MetadataDecoder<>.DecodeTypeOrThrow.
private TypeSignature DecodeType(ref BlobReader signatureReader, SignatureTypeCode typeCode)
{
switch (typeCode)
{
case SignatureTypeCode.TypeHandle:
{
int typeArgumentOffset = 0;
return DecodeType(signatureReader.ReadTypeHandle(), ImmutableArray<TypeSignature>.Empty, ref typeArgumentOffset);
}
case SignatureTypeCode.Array:
{
var elementType = DecodeModifiersAndType(ref signatureReader);
int rank;
int sizes;
signatureReader.TryReadCompressedInteger(out rank);
signatureReader.TryReadCompressedInteger(out sizes);
if (sizes != 0)
{
throw UnhandledMetadata();
}
return new ArrayTypeSignature(elementType, rank);
}
case SignatureTypeCode.SZArray:
{
var elementType = DecodeModifiersAndType(ref signatureReader);
return new ArrayTypeSignature(elementType, 1);
}
case SignatureTypeCode.GenericTypeInstance:
return DecodeGenericTypeInstance(ref signatureReader);
case SignatureTypeCode.Pointer:
{
var pointedAtType = DecodeModifiersAndType(ref signatureReader);
return new PointerTypeSignature(pointedAtType);
}
case SignatureTypeCode.GenericTypeParameter:
return DecodeGenericTypeParameter(ref signatureReader, _allTypeParameters, _containingArity);
case SignatureTypeCode.GenericMethodParameter:
return DecodeGenericTypeParameter(ref signatureReader, _methodTypeParameters, 0);
default:
{
var signature = typeCode.ToSpecialType().GetTypeSignature();
if (signature == null)
{
throw UnhandledMetadata();
}
return signature;
}
}
}
// Ignore modifiers and decode type.
private TypeSignature DecodeModifiersAndType(ref BlobReader signatureReader)
{
while (true)
{
var typeCode = signatureReader.ReadSignatureTypeCode();
switch (typeCode)
{
case SignatureTypeCode.RequiredModifier:
case SignatureTypeCode.OptionalModifier:
// Skip modifiers.
break;
default:
return DecodeType(ref signatureReader, typeCode);
}
}
}
private TypeSignature DecodeGenericTypeParameter(
ref BlobReader signatureReader,
ImmutableArray<string> typeParameters,
int containingArity)
{
int index = signatureReader.ReadCompressedInteger();
if (index < containingArity)
{
// Unspecified type parameter.
throw UnhandledMetadata();
}
var name = typeParameters[index - containingArity];
return new QualifiedTypeSignature(null, name);
}
// cf. MetadataDecoder<>.DecodeGenericTypeInstanceOrThrow.
private TypeSignature DecodeGenericTypeInstance(ref BlobReader signatureReader)
{
var typeCode = signatureReader.ReadSignatureTypeCode();
var typeHandle = signatureReader.ReadTypeHandle();
var typeArguments = DecodeGenericTypeArguments(ref signatureReader);
int typeArgumentOffset = 0;
var type = DecodeType(typeHandle, typeArguments, ref typeArgumentOffset);
if (typeArgumentOffset != typeArguments.Length)
{
// Generic type reference names must include arity
// to avoid loading referenced assemblies.
throw UnhandledMetadata();
}
return type;
}
private ImmutableArray<TypeSignature> DecodeGenericTypeArguments(ref BlobReader signatureReader)
{
int typeArgCount;
signatureReader.TryReadCompressedInteger(out typeArgCount);
var builder = ImmutableArray.CreateBuilder<TypeSignature>(typeArgCount);
for (int i = 0; i < typeArgCount; i++)
{
var typeArg = DecodeModifiersAndType(ref signatureReader);
builder.Add(typeArg);
}
return builder.ToImmutable();
}
// cf. MetadataDecoder<>.GetSymbolForTypeHandleOrThrow.
private TypeSignature DecodeType(
EntityHandle handle,
ImmutableArray<TypeSignature> typeArguments,
ref int typeArgumentOffset)
{
switch (handle.Kind)
{
case HandleKind.TypeDefinition:
return DecodeTypeDefinition((TypeDefinitionHandle)handle, typeArguments, ref typeArgumentOffset);
case HandleKind.TypeReference:
return DecodeTypeReference((TypeReferenceHandle)handle, typeArguments, ref typeArgumentOffset);
default:
throw new BadImageFormatException();
}
}
// cf. MetadataDecoder<>.GetTypeOfTypeDef.
private TypeSignature DecodeTypeDefinition(
TypeDefinitionHandle handle,
ImmutableArray<TypeSignature> typeArguments,
ref int typeArgumentOffset)
{
var typeDef = _reader.GetTypeDefinition(handle);
TypeSignature qualifier;
var declaringTypeHandle = typeDef.GetDeclaringType();
if (declaringTypeHandle.IsNil)
{
// Include namespace.
qualifier = GetNamespace(typeDef.Namespace);
}
else
{
// Include declaring type.
qualifier = DecodeTypeDefinition(declaringTypeHandle, typeArguments, ref typeArgumentOffset);
}
return CreateTypeSignature(qualifier, _reader.GetString(typeDef.Name), typeArguments, ref typeArgumentOffset);
}
// cf. MetadataDecoder<>.GetTypeOfTypeRef.
private TypeSignature DecodeTypeReference(
TypeReferenceHandle handle,
ImmutableArray<TypeSignature> typeArguments,
ref int typeArgumentOffset)
{
var typeRef = _reader.GetTypeReference(handle);
TypeSignature qualifier;
var scope = typeRef.ResolutionScope;
switch (scope.Kind)
{
case HandleKind.AssemblyReference:
case HandleKind.ModuleReference:
// Include namespace.
qualifier = GetNamespace(typeRef.Namespace);
break;
case HandleKind.TypeReference:
// Include declaring type.
qualifier = DecodeTypeReference((TypeReferenceHandle)scope, typeArguments, ref typeArgumentOffset);
break;
default:
throw new BadImageFormatException();
}
return CreateTypeSignature(qualifier, _reader.GetString(typeRef.Name), typeArguments, ref typeArgumentOffset);
}
private string GetTypeName(StringHandle nameHandle, out int arity)
{
return RemoveAritySeparatorIfAny(_reader.GetString(nameHandle), out arity);
}
private QualifiedTypeSignature GetNamespace(StringHandle namespaceHandle)
{
var namespaceName = _reader.GetString(namespaceHandle);
if (string.IsNullOrEmpty(namespaceName))
{
return null;
}
QualifiedTypeSignature signature = null;
var parts = namespaceName.Split('.');
foreach (var part in parts)
{
signature = new QualifiedTypeSignature(signature, part);
}
return signature;
}
private static TypeSignature CreateTypeSignature(
TypeSignature qualifier,
string typeName,
ImmutableArray<TypeSignature> typeArguments,
ref int typeArgumentOffset)
{
int arity;
typeName = RemoveAritySeparatorIfAny(typeName, out arity);
var qualifiedName = new QualifiedTypeSignature(qualifier, typeName);
if (arity == 0)
{
return qualifiedName;
}
typeArguments = ImmutableArray.Create(typeArguments, typeArgumentOffset, arity);
typeArgumentOffset += arity;
return new GenericTypeSignature(qualifiedName, typeArguments);
}
private static string RemoveAritySeparatorIfAny(string typeName, out int arity)
{
arity = 0;
int index = typeName.LastIndexOf('`');
if (index < 0)
{
return typeName;
}
int n;
if (int.TryParse(typeName.Substring(index + 1), out n))
{
arity = n;
}
return typeName.Substring(0, index);
}
private static Exception UnhandledMetadata()
{
return new NotSupportedException();
}
}
}