Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJackson Schuster <36744439+jtschuster@users.noreply.github.com>2022-03-18 22:20:24 +0300
committerGitHub <noreply@github.com>2022-03-18 22:20:24 +0300
commit1d774126b2aed67d61bb3bab54881555458e9452 (patch)
tree44df127135c0470e0f3d7e0fd5b405fa1bde0b2c
parented8b22a192b585f169446b1a4a14f3f81eda6154 (diff)
Create shared WellKnownTypes enum (#2692)
-rw-r--r--src/ILLink.RoslynAnalyzer/COMAnalyzer.cs10
-rw-r--r--src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs5
-rw-r--r--src/ILLink.RoslynAnalyzer/ITypeSymbolExtensions.cs24
-rw-r--r--src/ILLink.RoslynAnalyzer/TrimAnalysis/TypeProxy.cs8
-rw-r--r--src/ILLink.RoslynAnalyzer/TrimAnalysis/WellKnownTypeExtensions.cs23
-rw-r--r--src/ILLink.Shared/TypeSystemProxy/WellKnownType.cs37
-rw-r--r--src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs5
-rw-r--r--src/linker/Linker.Dataflow/TypeProxy.cs8
-rw-r--r--src/linker/Linker/TypeReferenceExtensions.cs7
9 files changed, 108 insertions, 19 deletions
diff --git a/src/ILLink.RoslynAnalyzer/COMAnalyzer.cs b/src/ILLink.RoslynAnalyzer/COMAnalyzer.cs
index d9e2d48cd..798bb8462 100644
--- a/src/ILLink.RoslynAnalyzer/COMAnalyzer.cs
+++ b/src/ILLink.RoslynAnalyzer/COMAnalyzer.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Immutable;
using System.Runtime.InteropServices;
using ILLink.Shared;
+using ILLink.Shared.TypeSystemProxy;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
@@ -88,11 +89,11 @@ namespace ILLink.RoslynAnalyzer
if (typeSymbol == null)
return false;
- if (typeSymbol.ContainingNamespace.Name == "System" && typeSymbol.Name == "Array") {
+ if (typeSymbol.IsTypeOf (WellKnownType.System_Array)) {
// System.Array marshals as IUnknown by default
return true;
- } else if (typeSymbol.ContainingNamespace.Name == "System" && typeSymbol.Name == "String" ||
- typeSymbol.ContainingNamespace.Name == "System.Text" && typeSymbol.Name == "StringBuilder") {
+ } else if (typeSymbol.IsTypeOf (WellKnownType.System_String) ||
+ typeSymbol.IsTypeOf ("System.Text", "StringBuilder")) {
// String and StringBuilder are special cased by interop
return false;
}
@@ -103,8 +104,7 @@ namespace ILLink.RoslynAnalyzer
} else if (typeSymbol.IsInterface ()) {
// Interface types marshal as COM by default
return true;
- } else if (typeSymbol.ContainingNamespace.Name == "System" &&
- typeSymbol.Name == "MulticastDelegate") {
+ } else if (typeSymbol.IsTypeOf ("System", "MulticastDelegate")) {
// Delegates are special cased by interop
return false;
} else if (typeSymbol.IsSubclassOf ("System.Runtime.InteropServices", "CriticalHandle") ||
diff --git a/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs b/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs
index ecf1cc1bf..c5cca0afd 100644
--- a/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs
+++ b/src/ILLink.RoslynAnalyzer/ISymbolExtensions.cs
@@ -113,7 +113,7 @@ namespace ILLink.RoslynAnalyzer
// Use definition type parameter names, not instance type parameters
methodSymbol = methodSymbol.OriginalDefinition;
// Format the declaring type with namespace and containing types.
- if (methodSymbol.ContainingSymbol.Kind == SymbolKind.NamedType) {
+ if (methodSymbol.ContainingSymbol?.Kind == SymbolKind.NamedType) {
// If the containing symbol is a method (for example for local functions),
// don't include the containing type's name. This matches the behavior of
// CSharpErrorMessageFormat.
@@ -147,8 +147,7 @@ namespace ILLink.RoslynAnalyzer
return false;
while (typeSymbol != null) {
- if (typeSymbol.ContainingNamespace.Name == ns &&
- typeSymbol.ContainingType.Name == type)
+ if (typeSymbol.IsTypeOf (ns, type))
return true;
typeSymbol = typeSymbol.ContainingType;
diff --git a/src/ILLink.RoslynAnalyzer/ITypeSymbolExtensions.cs b/src/ILLink.RoslynAnalyzer/ITypeSymbolExtensions.cs
index ab2487e1b..0560fa049 100644
--- a/src/ILLink.RoslynAnalyzer/ITypeSymbolExtensions.cs
+++ b/src/ILLink.RoslynAnalyzer/ITypeSymbolExtensions.cs
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics;
+using ILLink.Shared.TypeSystemProxy;
using Microsoft.CodeAnalysis;
namespace ILLink.RoslynAnalyzer
@@ -27,17 +29,17 @@ namespace ILLink.RoslynAnalyzer
private static HierarchyFlags GetFlags (ITypeSymbol type)
{
HierarchyFlags flags = 0;
- if (type.Name == "IReflect" && type.ContainingNamespace.GetDisplayName () == "System.Reflection") {
+ if (type.IsTypeOf (WellKnownType.System_Reflection_IReflect)) {
flags |= HierarchyFlags.IsSystemReflectionIReflect;
}
ITypeSymbol? baseType = type;
while (baseType != null) {
- if (baseType.Name == "Type" && baseType.ContainingNamespace.GetDisplayName () == "System")
+ if (baseType.IsTypeOf (WellKnownType.System_Type))
flags |= HierarchyFlags.IsSystemType;
foreach (var iface in baseType.Interfaces) {
- if (iface.Name == "IReflect" && iface.ContainingNamespace.GetDisplayName () == "System.Reflection") {
+ if (iface.IsTypeOf (WellKnownType.System_Reflection_IReflect)) {
flags |= HierarchyFlags.IsSystemReflectionIReflect;
}
}
@@ -50,5 +52,21 @@ namespace ILLink.RoslynAnalyzer
private static bool IsSystemType (HierarchyFlags flags) => (flags & HierarchyFlags.IsSystemType) != 0;
private static bool IsSystemReflectionIReflect (HierarchyFlags flags) => (flags & HierarchyFlags.IsSystemReflectionIReflect) != 0;
+
+ public static bool IsTypeOf (this ITypeSymbol symbol, string @namespace, string name)
+ {
+ return symbol.ContainingNamespace?.GetDisplayName () == @namespace && symbol.MetadataName == name;
+ }
+
+ public static bool IsTypeOf (this ITypeSymbol symbol, WellKnownType wellKnownType)
+ {
+ if (wellKnownType.TryGetSpecialType (out var specialType)) {
+ // Make sure checking the special type is the same as checking the metadata string names.
+ Debug.Assert (symbol.IsTypeOf (wellKnownType.GetNamespace (), wellKnownType.GetName ()) == (symbol.SpecialType == specialType));
+ return symbol.SpecialType == specialType;
+ }
+ var (Namespace, Name) = wellKnownType.GetNamespaceAndName ();
+ return symbol.IsTypeOf (Namespace, Name);
+ }
}
}
diff --git a/src/ILLink.RoslynAnalyzer/TrimAnalysis/TypeProxy.cs b/src/ILLink.RoslynAnalyzer/TrimAnalysis/TypeProxy.cs
index d66ed455b..8ccad1bad 100644
--- a/src/ILLink.RoslynAnalyzer/TrimAnalysis/TypeProxy.cs
+++ b/src/ILLink.RoslynAnalyzer/TrimAnalysis/TypeProxy.cs
@@ -14,12 +14,14 @@ namespace ILLink.Shared.TypeSystemProxy
public string Name { get => Type.MetadataName; }
- public string Namespace { get => Type.ContainingNamespace.Name; }
+ public string? Namespace { get => Type.ContainingNamespace?.Name; }
+
+ public bool IsTypeOf (string @namespace, string name) => Type.IsTypeOf (@namespace, name);
+
+ public bool IsTypeOf (WellKnownType wellKnownType) => Type.IsTypeOf (wellKnownType);
public string GetDisplayName () => Type.GetDisplayName ();
public override string ToString () => Type.ToString ();
-
- public bool IsTypeOf (string @namespace, string name) => Namespace == @namespace && Name == name;
}
}
diff --git a/src/ILLink.RoslynAnalyzer/TrimAnalysis/WellKnownTypeExtensions.cs b/src/ILLink.RoslynAnalyzer/TrimAnalysis/WellKnownTypeExtensions.cs
new file mode 100644
index 000000000..73f619082
--- /dev/null
+++ b/src/ILLink.RoslynAnalyzer/TrimAnalysis/WellKnownTypeExtensions.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.CodeAnalysis;
+
+namespace ILLink.Shared.TypeSystemProxy
+{
+ public static partial class WellKnownTypeExtensions
+ {
+ public static bool TryGetSpecialType (this WellKnownType wellKnownType, [NotNullWhen (true)] out SpecialType? specialType)
+ {
+ specialType = wellKnownType switch {
+ WellKnownType.System_String => SpecialType.System_String,
+ WellKnownType.System_Nullable_T => SpecialType.System_Nullable_T,
+ WellKnownType.System_Array => SpecialType.System_Array,
+ WellKnownType.System_Object => SpecialType.System_Object,
+ _ => null,
+ };
+ return specialType is not null;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ILLink.Shared/TypeSystemProxy/WellKnownType.cs b/src/ILLink.Shared/TypeSystemProxy/WellKnownType.cs
new file mode 100644
index 000000000..b4f061e6d
--- /dev/null
+++ b/src/ILLink.Shared/TypeSystemProxy/WellKnownType.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace ILLink.Shared.TypeSystemProxy
+{
+ public enum WellKnownType
+ {
+ System_String,
+ System_Nullable_T,
+ System_Type,
+ System_Reflection_IReflect,
+ System_Array,
+ System_Object,
+ System_Attribute
+ }
+
+ public static partial class WellKnownTypeExtensions
+ {
+ public static (string Namespace, string Name) GetNamespaceAndName (this WellKnownType type)
+ {
+ return type switch {
+ WellKnownType.System_String => ("System", "String"),
+ WellKnownType.System_Nullable_T => ("System", "Nullable`1"),
+ WellKnownType.System_Type => ("System", "Type"),
+ WellKnownType.System_Reflection_IReflect => ("System.Reflection", "IReflect"),
+ WellKnownType.System_Array => ("System", "Array"),
+ WellKnownType.System_Object => ("System", "Object"),
+ WellKnownType.System_Attribute => ("System", "Attribute"),
+ _ => throw new ArgumentException ($"{nameof (type)} is not a well-known type."),
+ };
+ }
+ public static string GetNamespace (this WellKnownType type) => GetNamespaceAndName (type).Namespace;
+ public static string GetName (this WellKnownType type) => GetNamespaceAndName (type).Name;
+ }
+} \ No newline at end of file
diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
index fdc39bc02..4ea6b848d 100644
--- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
+++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
@@ -10,6 +10,7 @@ using System.Linq;
using ILLink.Shared;
using ILLink.Shared.DataFlow;
using ILLink.Shared.TrimAnalysis;
+using ILLink.Shared.TypeSystemProxy;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Linker.Steps;
@@ -894,10 +895,10 @@ namespace Mono.Linker.Dataflow
var parameterTypeDef = _context.TryResolve (parameterType);
if (parameterTypeDef != null) {
- if (parameterTypeDef.IsTypeOf ("System", "Array")) {
+ if (parameterTypeDef.IsTypeOf (WellKnownType.System_Array)) {
// System.Array marshals as IUnknown by default
return true;
- } else if (parameterTypeDef.IsTypeOf ("System", "String") ||
+ } else if (parameterTypeDef.IsTypeOf (WellKnownType.System_String) ||
parameterTypeDef.IsTypeOf ("System.Text", "StringBuilder")) {
// String and StringBuilder are special cased by interop
return false;
diff --git a/src/linker/Linker.Dataflow/TypeProxy.cs b/src/linker/Linker.Dataflow/TypeProxy.cs
index 9fa5f5c09..d629b8524 100644
--- a/src/linker/Linker.Dataflow/TypeProxy.cs
+++ b/src/linker/Linker.Dataflow/TypeProxy.cs
@@ -16,12 +16,14 @@ namespace ILLink.Shared.TypeSystemProxy
public string Name { get => Type.Name; }
- public string Namespace { get => Type.Namespace; }
+ public string? Namespace { get => Type.Namespace; }
+
+ public bool IsTypeOf (string @namespace, string name) => Type.IsTypeOf (@namespace, name);
+
+ public bool IsTypeOf (WellKnownType wellKnownType) => Type.IsTypeOf (wellKnownType);
public string GetDisplayName () => Type.GetDisplayName ();
public override string ToString () => Type.ToString ();
-
- public bool IsTypeOf (string @namespace, string name) => Type.IsTypeOf (@namespace, name);
}
}
diff --git a/src/linker/Linker/TypeReferenceExtensions.cs b/src/linker/Linker/TypeReferenceExtensions.cs
index ea2239479..232f10a63 100644
--- a/src/linker/Linker/TypeReferenceExtensions.cs
+++ b/src/linker/Linker/TypeReferenceExtensions.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
+using ILLink.Shared.TypeSystemProxy;
using Mono.Cecil;
namespace Mono.Linker
@@ -358,6 +359,12 @@ namespace Mono.Linker
return tr.Name == type.Name && tr.Namespace == tr.Namespace;
}
+ public static bool IsTypeOf (this TypeReference tr, WellKnownType type)
+ {
+ var (@namespace, name) = type.GetNamespaceAndName ();
+ return tr.IsTypeOf (@namespace, name);
+ }
+
public static bool IsSubclassOf (this TypeReference type, string ns, string name, ITryResolveMetadata resolver)
{
TypeDefinition? baseType = resolver.TryResolve (type);