|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using ILLink.Shared;
using ILLink.Shared.TrimAnalysis;
using Mono.Cecil;
using TypeName = System.Reflection.Metadata.TypeName;
namespace Mono.Linker
{
internal sealed partial class TypeNameResolver
{
public bool TryResolveTypeName (
string typeNameString,
in DiagnosticContext diagnosticContext,
[NotNullWhen (true)] out TypeReference? typeReference,
[NotNullWhen (true)] out List<TypeResolutionRecord>? typeResolutionRecords,
bool needsAssemblyName)
{
typeReference = null;
typeResolutionRecords = null;
if (string.IsNullOrEmpty (typeNameString))
return false;
if (!TypeName.TryParse (typeNameString, out TypeName? parsedTypeName, s_typeNameParseOptions))
return false;
if (needsAssemblyName && !IsFullyQualified (parsedTypeName)) {
diagnosticContext.AddDiagnostic (DiagnosticId.TypeNameIsNotAssemblyQualified, typeNameString);
return false;
}
// If parsedTypeName doesn't have an assembly name in it but it does have a namespace,
// search for the type in the calling object's assembly. If not found, look in the core
// assembly.
ICustomAttributeProvider? provider = diagnosticContext.Origin.Provider;
AssemblyDefinition? referencingAssembly = provider switch {
AssemblyDefinition asm => asm,
TypeDefinition type => type.Module?.Assembly,
IMemberDefinition member => member.DeclaringType.Module.Assembly,
null => null,
_ => throw new NotSupportedException ()
};
if (referencingAssembly is null)
return false;
typeResolutionRecords = new List<TypeResolutionRecord> ();
typeReference = ResolveTypeName (referencingAssembly, parsedTypeName, typeResolutionRecords);
return typeReference != null;
static bool IsFullyQualified (TypeName typeName)
{
if (typeName.AssemblyName is null)
return false;
if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
return IsFullyQualified (typeName.GetElementType ());
if (typeName.IsConstructedGenericType) {
foreach (var typeArgument in typeName.GetGenericArguments ()) {
if (!IsFullyQualified (typeArgument))
return false;
}
}
return true;
}
}
}
}
|