Skip to content

Commit

Permalink
Changed Assembly.findTypeDefinition to resolveTypeDefinition, account…
Browse files Browse the repository at this point in the history
…ing for type forwarding.
  • Loading branch information
tristanlabelle committed Feb 17, 2024
1 parent 6a1d542 commit 8d217c8
Show file tree
Hide file tree
Showing 17 changed files with 95 additions and 91 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import DotNetMetadata

let context = AssemblyLoadContext()
let assembly = try context.load(path: #"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll"#)
let typeDefinition = assembly.findTypeDefinition(fullName: "System.IDisposable")!
let typeDefinition = assembly.resolveTypeDefinition(fullName: "System.IDisposable")!
print("interface \(typeDefinition.name) {")
for method in typeDefinition.methods {
print(" void \(method.name)()")
Expand Down
4 changes: 2 additions & 2 deletions Sources/DotNetMetadata/Assembly+resolve.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ extension Assembly {
case let .module(index):
// Assume single-module assembly
guard index?.zeroBased == 0 else { break }
return findTypeDefinition(namespace: namespace, name: name)!
return try resolveTypeDefinition(namespace: namespace, name: name)!
case let .assemblyRef(index):
guard let index = index else { break }
return try resolve(index).findTypeDefinition(namespace: namespace, name: name)!
return try resolve(index).resolveTypeDefinition(namespace: namespace, name: name)!
default:
fatalError("Not implemented: resolution scope \(row.resolutionScope)")
}
Expand Down
28 changes: 16 additions & 12 deletions Sources/DotNetMetadata/Assembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,6 @@ public class Assembly: CustomDebugStringConvertible {
return dict
}()

public func findTypeDefinition(fullName: String) -> TypeDefinition? {
typeDefinitionsByFullName[fullName]
}

public func findTypeDefinition(namespace: String?, name: String) -> TypeDefinition? {
findTypeDefinition(fullName: makeFullTypeName(namespace: namespace, name: name))
}

public func findTypeDefinition(namespace: String?, enclosingName: String, nestedNames: [String]) -> TypeDefinition? {
findTypeDefinition(fullName: makeFullTypeName(namespace: namespace, enclosingName: enclosingName, nestedNames: nestedNames))
}

public private(set) lazy var exportedTypesByFullName: [String: ExportedType] = {
let exportedTypes = exportedTypes
var dict = [String: ExportedType](minimumCapacity: exportedTypes.count)
Expand All @@ -106,6 +94,22 @@ public class Assembly: CustomDebugStringConvertible {
return dict
}()

public func resolveTypeDefinition(fullName: String, allowForwarding: Bool = true) throws -> TypeDefinition? {
if let typeDefinition = typeDefinitionsByFullName[fullName] { return typeDefinition }
if let exportedType = exportedTypesByFullName[fullName] { return try exportedType.definition }
return nil
}

public func resolveTypeDefinition(namespace: String?, name: String, allowForwarding: Bool = true) throws -> TypeDefinition? {
let fullName = makeFullTypeName(namespace: namespace, name: name)
return try resolveTypeDefinition(fullName: fullName, allowForwarding: allowForwarding)
}

public func resolveTypeDefinition(namespace: String?, enclosingName: String, nestedNames: [String], allowForwarding: Bool = true) throws -> TypeDefinition? {
let fullName = makeFullTypeName(namespace: namespace, enclosingName: enclosingName, nestedNames: nestedNames)
return try resolveTypeDefinition(fullName: fullName, allowForwarding: allowForwarding)
}

internal lazy var mscorlib: Mscorlib = {
if let mscorlib = self as? Mscorlib {
return mscorlib
Expand Down
2 changes: 1 addition & 1 deletion Sources/DotNetMetadata/Attribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public final class Attribute {
// > it is permitted to omit the assembly-name, version, culture and public-key-token.
assembly = self.assembly
}
return .type(definition: assembly.findTypeDefinition(fullName: fullName)!)
return .type(definition: try assembly.resolveTypeDefinition(fullName: fullName)!)

case .array(let elems): return .array(try elems.map(resolve))
case .boxed(_): fatalError("Not implemented: boxed custom attribute arguments")
Expand Down
4 changes: 2 additions & 2 deletions Sources/DotNetMetadata/ExportedType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public final class ExportedType {
}

public private(set) lazy var fullName: String = {
// Assume that exported type cannot be nested types
// TODO: Support nested exported types
makeFullTypeName(namespace: namespace, name: name)
}()

Expand All @@ -36,7 +36,7 @@ public final class ExportedType {
let definitionAssembly = try self.assembly.resolve(index)
// TODO: Optimize using the typeDefId field
// TODO: Support recursive exported types
guard let typeDefinition = definitionAssembly.findTypeDefinition(namespace: namespace, name: name) else {
guard let typeDefinition = try definitionAssembly.resolveTypeDefinition(namespace: namespace, name: name) else {
throw DotNetMetadataFormat.InvalidFormatError.tableConstraint
}
return typeDefinition
Expand Down
2 changes: 1 addition & 1 deletion Sources/DotNetMetadata/Mscorlib.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public final class Mscorlib: Assembly {
public final class SpecialTypes {
init(assembly: Assembly) throws {
func find<T: TypeDefinition>(_ name: String) throws -> T {
guard let typeDefinition = assembly.findTypeDefinition(fullName: "System." + name),
guard let typeDefinition = try assembly.resolveTypeDefinition(fullName: "System." + name),
let typeDefinition = typeDefinition as? T else {
throw MissingSpecialType()
}
Expand Down
12 changes: 6 additions & 6 deletions Tests/DotNetMetadata/AttributeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal final class AttributeTests: CompiledAssemblyTestCase {
}

public func testNumericArgument() throws {
let targetType = try XCTUnwrap(assembly.findTypeDefinition(fullName: "IntArgument"))
let targetType = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "IntArgument"))
let attribute = try XCTUnwrap(targetType.findAttribute(namespace: nil, name: "MyAttributeAttribute"))
let arguments = try attribute.arguments
XCTAssertEqual(arguments.count, 1)
Expand All @@ -41,7 +41,7 @@ internal final class AttributeTests: CompiledAssemblyTestCase {
}

public func testStringArgument() throws {
let targetType = try XCTUnwrap(assembly.findTypeDefinition(fullName: "StringArgument"))
let targetType = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "StringArgument"))
let attribute = try XCTUnwrap(targetType.findAttribute(namespace: nil, name: "MyAttributeAttribute"))
let arguments = try attribute.arguments
XCTAssertEqual(arguments.count, 1)
Expand All @@ -54,7 +54,7 @@ internal final class AttributeTests: CompiledAssemblyTestCase {
}

public func testTypeArgument() throws {
let targetType = try XCTUnwrap(assembly.findTypeDefinition(fullName: "TypeArgument"))
let targetType = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "TypeArgument"))
let attribute = try XCTUnwrap(targetType.findAttribute(namespace: nil, name: "MyAttributeAttribute"))
let arguments = try attribute.arguments
XCTAssertEqual(arguments.count, 1)
Expand All @@ -68,7 +68,7 @@ internal final class AttributeTests: CompiledAssemblyTestCase {

public func testEnumArgument() throws {
try XCTSkipIf(true, "Requires CoreLib support for .NET Core")
let targetType = try XCTUnwrap(assembly.findTypeDefinition(fullName: "EnumArgument"))
let targetType = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "EnumArgument"))
let attribute = try XCTUnwrap(targetType.findAttribute(namespace: nil, name: "MyAttributeAttribute"))
let arguments = try attribute.arguments
XCTAssertEqual(arguments.count, 1)
Expand All @@ -81,7 +81,7 @@ internal final class AttributeTests: CompiledAssemblyTestCase {
}

public func testNamedFieldArgument() throws {
let targetType = try XCTUnwrap(assembly.findTypeDefinition(fullName: "NamedFieldArgument"))
let targetType = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "NamedFieldArgument"))
let attribute = try XCTUnwrap(targetType.findAttribute(namespace: nil, name: "MyAttributeAttribute"))
XCTAssertEqual(try attribute.arguments.count, 0)
let namedArguments = try attribute.namedArguments
Expand All @@ -102,7 +102,7 @@ internal final class AttributeTests: CompiledAssemblyTestCase {
}

public func testNamedPropertyArgument() throws {
let targetType = try XCTUnwrap(assembly.findTypeDefinition(fullName: "NamedPropertyArgument"))
let targetType = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "NamedPropertyArgument"))
let attribute = try XCTUnwrap(targetType.findAttribute(namespace: nil, name: "MyAttributeAttribute"))
XCTAssertEqual(try attribute.arguments.count, 0)
let namedArguments = try attribute.namedArguments
Expand Down
14 changes: 7 additions & 7 deletions Tests/DotNetMetadata/EnumTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,32 @@ internal final class EnumTests: CompiledAssemblyTestCase {


public func testEnumerantNames() throws {
let enumDefinition = try XCTUnwrap(assembly.findTypeDefinition(fullName: "MyEnum") as? EnumDefinition)
let enumDefinition = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "MyEnum") as? EnumDefinition)
XCTAssertEqual(enumDefinition.fields.filter { $0.isStatic }.map { $0.name }.sorted(), ["A", "B"])
}

public func testUnderlyingType() throws {
try XCTSkipIf(true, "Requires CoreLib support for .NET Core")
XCTAssertEqual(
try XCTUnwrap(assembly.findTypeDefinition(fullName: "MyEnum") as? EnumDefinition).underlyingType.fullName,
try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "MyEnum") as? EnumDefinition).underlyingType.fullName,
"System.Int32")
XCTAssertEqual(
try XCTUnwrap(assembly.findTypeDefinition(fullName: "MyShortEnum") as? EnumDefinition).underlyingType.fullName,
try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "MyShortEnum") as? EnumDefinition).underlyingType.fullName,
"System.Int16")
}

public func testEnumerantValues() throws {
let enumDefinition = try XCTUnwrap(assembly.findTypeDefinition(fullName: "MyEnum") as? EnumDefinition)
let enumDefinition = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "MyEnum") as? EnumDefinition)
XCTAssertEqual(try XCTUnwrap(XCTUnwrap(enumDefinition.findField(name: "A")).literalValue), .int32(1))
XCTAssertEqual(try XCTUnwrap(XCTUnwrap(enumDefinition.findField(name: "B")).literalValue), .int32(2))

let shortEnumDefinition = try XCTUnwrap(assembly.findTypeDefinition(fullName: "MyShortEnum") as? EnumDefinition)
let shortEnumDefinition = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "MyShortEnum") as? EnumDefinition)
XCTAssertEqual(try XCTUnwrap(XCTUnwrap(shortEnumDefinition.findField(name: "A")).literalValue), .int16(42))
}

public func testIsFlags() throws {
try XCTSkipIf(true, "Requires CoreLib support for .NET Core")
XCTAssertFalse(try XCTUnwrap(assembly.findTypeDefinition(fullName: "MyEnum") as? EnumDefinition).isFlags)
XCTAssertTrue(try XCTUnwrap(assembly.findTypeDefinition(fullName: "MyFlagsEnum") as? EnumDefinition).isFlags)
XCTAssertFalse(try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "MyEnum") as? EnumDefinition).isFlags)
XCTAssertTrue(try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "MyFlagsEnum") as? EnumDefinition).isFlags)
}
}
4 changes: 2 additions & 2 deletions Tests/DotNetMetadata/FieldTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal final class FieldTests: CompiledAssemblyTestCase {

public override func setUpWithError() throws {
try super.setUpWithError()
typeDefinition = try XCTUnwrap(assembly.findTypeDefinition(fullName: "Fields"))
typeDefinition = try XCTUnwrap(assembly.resolveTypeDefinition(fullName: "Fields"))
publicInstanceField = try XCTUnwrap(typeDefinition.findField(name: "PublicInstance"))
privateStaticInitOnlyField = try XCTUnwrap(typeDefinition.findField(name: "PrivateStaticInitOnly"))
protectedLiteralField = try XCTUnwrap(typeDefinition.findField(name: "ProtectedLiteral"))
Expand All @@ -39,7 +39,7 @@ internal final class FieldTests: CompiledAssemblyTestCase {
public func testType() throws {
try XCTAssertEqual(
XCTUnwrap(publicInstanceField.type.asDefinition),
XCTUnwrap(assembly.findTypeDefinition(fullName: "FieldType")))
XCTUnwrap(assembly.resolveTypeDefinition(fullName: "FieldType")))
}

public func testVisibility() throws {
Expand Down
8 changes: 4 additions & 4 deletions Tests/DotNetMetadata/NetFX45MscorlibTests+events.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ import XCTest
extension NetFX45MscorlibTests {
func testTypeEventEnumeration() throws {
XCTAssertEqual(
Self.assembly.findTypeDefinition(fullName: "System.Diagnostics.Tracing.EventListener")?.events
try Self.assembly.resolveTypeDefinition(fullName: "System.Diagnostics.Tracing.EventListener")?.events
.filter({ $0.hasPublicAddRemoveAccessors }).map({ $0.name }).sorted(),
[ "EventSourceCreated", "EventWritten" ])
}

func testEventAccessors() throws {
let event = try XCTUnwrap(
Self.assembly.findTypeDefinition(fullName: "System.Diagnostics.Tracing.EventListener")?
Self.assembly.resolveTypeDefinition(fullName: "System.Diagnostics.Tracing.EventListener")?
.findEvent(name: "EventSourceCreated"))

XCTAssertEqual(try XCTUnwrap(event.addAccessor).name, "add_EventSourceCreated")
XCTAssertEqual(try XCTUnwrap(event.removeAccessor).name, "remove_EventSourceCreated")
}

func testEventType() throws {
let console = try XCTUnwrap(Self.assembly.findTypeDefinition(fullName: "System.Console"))
let console = try XCTUnwrap(Self.assembly.resolveTypeDefinition(fullName: "System.Console"))
let consoleCancelEventHandler = try XCTUnwrap(
Self.assembly.findTypeDefinition(fullName: "System.ConsoleCancelEventHandler") as? DelegateDefinition)
Self.assembly.resolveTypeDefinition(fullName: "System.ConsoleCancelEventHandler") as? DelegateDefinition)

XCTAssertEqual(
try XCTUnwrap(console.findEvent(name: "CancelKeyPress")).handlerType,
Expand Down
28 changes: 14 additions & 14 deletions Tests/DotNetMetadata/NetFX45MscorlibTests+methods.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ import XCTest
extension NetFX45MscorlibTests {
func testTypeMethodEnumeration() throws {
XCTAssertEqual(
Self.assembly.findTypeDefinition(fullName: "System.Collections.Generic.IEqualityComparer`1")?.methods.map({ $0.name }).sorted(),
try Self.assembly.resolveTypeDefinition(fullName: "System.Collections.Generic.IEqualityComparer`1")?.methods.map({ $0.name }).sorted(),
[ "Equals", "GetHashCode" ])
}

func testMethodClass() throws {
let object = Self.assembly.findTypeDefinition(fullName: "System.Object")
let object = try Self.assembly.resolveTypeDefinition(fullName: "System.Object")
XCTAssertNil(object?.findMethod(name: "ToString") as? Constructor)
XCTAssertNotNil(object?.findMethod(name: Constructor.name) as? Constructor)
}

func testMethodFlags() throws {
// Abstract interface method
let iasyncResult_get_IsCompleted = try XCTUnwrap(Self.assembly.findTypeDefinition(fullName: "System.IAsyncResult")?
let iasyncResult_get_IsCompleted = try XCTUnwrap(Self.assembly.resolveTypeDefinition(fullName: "System.IAsyncResult")?
.findMethod(name: "get_IsCompleted"))
XCTAssertEqual(iasyncResult_get_IsCompleted.isStatic, false)
XCTAssertEqual(iasyncResult_get_IsCompleted.isInstance, true)
Expand All @@ -26,7 +26,7 @@ extension NetFX45MscorlibTests {
XCTAssertEqual(iasyncResult_get_IsCompleted.nameKind, NameKind.special)

// Static method
let gc_WaitForPendingFinalizers = try XCTUnwrap(Self.assembly.findTypeDefinition(fullName: "System.GC")?
let gc_WaitForPendingFinalizers = try XCTUnwrap(Self.assembly.resolveTypeDefinition(fullName: "System.GC")?
.findMethod(name: "WaitForPendingFinalizers"))
XCTAssertEqual(gc_WaitForPendingFinalizers.isStatic, true)
XCTAssertEqual(gc_WaitForPendingFinalizers.isInstance, false)
Expand All @@ -35,7 +35,7 @@ extension NetFX45MscorlibTests {
XCTAssertEqual(gc_WaitForPendingFinalizers.nameKind, NameKind.regular)

// Overriden virtual method
let exception_ToString = try XCTUnwrap(Self.assembly.findTypeDefinition(fullName: "System.Exception")?
let exception_ToString = try XCTUnwrap(Self.assembly.resolveTypeDefinition(fullName: "System.Exception")?
.findMethod(name: "ToString", public: true, arity: 0))
XCTAssertEqual(exception_ToString.isStatic, false)
XCTAssertEqual(exception_ToString.isInstance, true)
Expand All @@ -46,55 +46,55 @@ extension NetFX45MscorlibTests {

func testMethodParamEnumeration() throws {
XCTAssertEqual(
try Self.assembly.findTypeDefinition(fullName: "System.Object")?
try Self.assembly.resolveTypeDefinition(fullName: "System.Object")?
.findMethod(name: "ReferenceEquals")?.params.map { $0.name },
[ "objA", "objB" ])

XCTAssertEqual(
try Self.assembly.findTypeDefinition(fullName: "System.Object")?
try Self.assembly.resolveTypeDefinition(fullName: "System.Object")?
.findMethod(name: "ToString")?.params.count, 0)
}

func testMethodHasReturnValue() throws {
XCTAssertEqual(
try Self.assembly.findTypeDefinition(fullName: "System.Object")?
try Self.assembly.resolveTypeDefinition(fullName: "System.Object")?
.findMethod(name: "ToString")?.hasReturnValue,
true)

XCTAssertEqual(
try Self.assembly.findTypeDefinition(fullName: "System.IDisposable")?
try Self.assembly.resolveTypeDefinition(fullName: "System.IDisposable")?
.findMethod(name: "Dispose")?.hasReturnValue,
false)
}

func testMethodReturnType() throws {
XCTAssertEqual(
try Self.assembly.findTypeDefinition(fullName: "System.Object")?
try Self.assembly.resolveTypeDefinition(fullName: "System.Object")?
.findMethod(name: "ToString")?.returnType.asDefinition?.fullName,
"System.String")

XCTAssertEqual(
try Self.assembly.findTypeDefinition(fullName: "System.IDisposable")?
try Self.assembly.resolveTypeDefinition(fullName: "System.IDisposable")?
.findMethod(name: "Dispose")?.returnType.asDefinition?.fullName,
"System.Void")
}

func testMethodParamType() throws {
XCTAssertEqual(
try Self.assembly.findTypeDefinition(fullName: "System.String")?
try Self.assembly.resolveTypeDefinition(fullName: "System.String")?
.findMethod(name: "IsNullOrEmpty")?.params[0].type.asDefinition?.fullName,
"System.String")
}

func testParamByRef() throws {
XCTAssertEqual(
try Self.assembly.findTypeDefinition(fullName: "System.Guid")?
try Self.assembly.resolveTypeDefinition(fullName: "System.Guid")?
.findMethod(name: "TryParse")?.params.map { $0.isByRef },
[ false, true ])
}

func testOverloadBinding() throws {
guard let convert = Self.assembly.findTypeDefinition(fullName: "System.Convert") else {
guard let convert = try Self.assembly.resolveTypeDefinition(fullName: "System.Convert") else {
return XCTFail("Failed to find System.Convert")
}

Expand Down
Loading

0 comments on commit 8d217c8

Please sign in to comment.