Skip to content

Commit 205afff

Browse files
authored
[swift2objc] Fix nesting bugs (#3173)
1 parent 77d80f4 commit 205afff

File tree

5 files changed

+55
-12
lines changed

5 files changed

+55
-12
lines changed

pkgs/swift2objc/lib/src/ast/_core/interfaces/declaration.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import '../../ast_node.dart';
77
import '../../declarations/built_in/built_in_declaration.dart';
88
import '../shared/referred_type.dart';
99
import 'availability.dart';
10+
import 'nestable_declaration.dart';
1011

1112
/// A common interface for all Swift entities declarations.
1213
abstract interface class Declaration implements AstNode, Availability {
@@ -20,7 +21,14 @@ extension AsDeclaredType<T extends Declaration> on T {
2021
DeclaredType<T> get asDeclaredType => DeclaredType(id: id, declaration: this);
2122
}
2223

23-
extension DeclarationIsBuiltIn on Declaration {
24+
extension DeclarationExtensions on Declaration {
2425
bool get isBuiltIn =>
2526
this is BuiltInDeclaration || source == builtInInputConfig;
27+
28+
String get fullName {
29+
final parent = this is InnerNestableDeclaration
30+
? (this as InnerNestableDeclaration).nestingParent
31+
: null;
32+
return parent != null ? '${parent.fullName}.$name' : name;
33+
}
2634
}

pkgs/swift2objc/lib/src/transformer/_core/utils.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ import 'unique_namer.dart';
8484
);
8585

8686
return (
87-
'${transformedTypeDeclaration.name}($value)',
87+
'${transformedTypeDeclaration.fullName}($value)',
8888
transformedTypeDeclaration.asDeclaredType,
8989
);
9090
} else if (type is OptionalType) {

pkgs/swift2objc/lib/src/transformer/transform.dart

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class TransformationState {
3131

3232
// Bindings that will be generated as stubs.
3333
final stubs = <Declaration>{};
34+
35+
late final UniqueNamer globalNamer;
3436
}
3537

3638
/// Transforms the given declarations into the desired ObjC wrapped declarations
@@ -61,7 +63,7 @@ List<Declaration> transform(
6163
state.stubs.addAll(listDecls.stubDecls);
6264
state.bindings.addAll(listDecls.stubDecls);
6365

64-
final globalNamer = UniqueNamer(
66+
state.globalNamer = UniqueNamer(
6567
state.bindings.map((declaration) => declaration.name),
6668
);
6769

@@ -72,9 +74,9 @@ List<Declaration> transform(
7274

7375
final transformedDeclarations = [
7476
...topLevelDecls.map(
75-
(d) => maybeTransformDeclaration(d, globalNamer, state),
77+
(d) => maybeTransformDeclaration(d, state.globalNamer, state),
7678
),
77-
transformGlobals(globals, globalNamer, state),
79+
transformGlobals(globals, state.globalNamer, state),
7880
].nonNulls.toList();
7981

8082
return [
@@ -112,10 +114,20 @@ Declaration? maybeTransformDeclaration(
112114
}
113115

114116
if (declaration is InnerNestableDeclaration &&
115-
declaration.nestingParent != null) {
117+
declaration.nestingParent != null &&
118+
!nested) {
116119
// It's important that nested declarations are only transformed in the
117-
// context of their parent, so that their parentNamer is correct.
118-
assert(nested);
120+
// context of their parent, so that their parentNamer is correct. So find
121+
// the top level declaration this is nested in, and transform that first.
122+
maybeTransformDeclaration(
123+
_topLevelNestingParent(declaration),
124+
state.globalNamer,
125+
state,
126+
);
127+
128+
// Now that the parents are transformed, this declaration should haven been
129+
// transformed, and will be in the cache.
130+
return state.map[declaration]!;
119131
}
120132

121133
return switch (declaration) {
@@ -136,3 +148,8 @@ List<Declaration> _getPrimitiveWrapperClasses(TransformationState state) =>
136148
.map((entry) => entry.value)
137149
.nonNulls
138150
.toList();
151+
152+
Declaration _topLevelNestingParent(Declaration declaration) =>
153+
declaration is InnerNestableDeclaration && declaration.nestingParent != null
154+
? _topLevelNestingParent(declaration.nestingParent!)
155+
: declaration;

pkgs/swift2objc/test/integration/nested_types_input.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ public class OuterClass {
1212
public static func makeOuter() -> OuterClass { return OuterClass(); }
1313
public static func makeInner() -> InnerStruct { return InnerStruct(); }
1414
}
15+
16+
public func makeOther() -> OuterStruct.InnerClass {
17+
return OuterStruct.InnerClass();
18+
}
1519
}
1620

1721
public struct OuterStruct {
@@ -28,4 +32,8 @@ public struct OuterStruct {
2832
public static func makeOuter() -> OuterStruct { return OuterStruct(); }
2933
public static func makeInner() -> InnerStruct { return InnerStruct(); }
3034
}
35+
36+
public func makeOther() -> OuterClass.InnerClass {
37+
return OuterClass.InnerClass();
38+
}
3139
}

pkgs/swift2objc/test/integration/nested_types_output.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@ import Foundation
1616

1717
@objc static public func makeInnerClass() -> OuterClassWrapper.InnerClassWrapper {
1818
let result = OuterClass.makeInnerClass()
19-
return InnerClassWrapper(result)
19+
return OuterClassWrapper.InnerClassWrapper(result)
2020
}
2121

2222
@objc static public func makeInnerStruct() -> OuterClassWrapper.InnerStructWrapper {
2323
let result = OuterClass.makeInnerStruct()
24-
return InnerStructWrapper(result)
24+
return OuterClassWrapper.InnerStructWrapper(result)
25+
}
26+
27+
@objc public func makeOther() -> OuterStructWrapper.InnerClassWrapper {
28+
let result = wrappedInstance.makeOther()
29+
return OuterStructWrapper.InnerClassWrapper(result)
2530
}
2631

2732
@objc public class InnerClassWrapper: NSObject {
@@ -78,12 +83,17 @@ import Foundation
7883

7984
@objc static public func makeInnerStruct() -> OuterStructWrapper.InnerStructWrapper {
8085
let result = OuterStruct.makeInnerStruct()
81-
return InnerStructWrapper(result)
86+
return OuterStructWrapper.InnerStructWrapper(result)
8287
}
8388

8489
@objc static public func makeInnerClass() -> OuterStructWrapper.InnerClassWrapper {
8590
let result = OuterStruct.makeInnerClass()
86-
return InnerClassWrapper(result)
91+
return OuterStructWrapper.InnerClassWrapper(result)
92+
}
93+
94+
@objc public func makeOther() -> OuterClassWrapper.InnerClassWrapper {
95+
let result = wrappedInstance.makeOther()
96+
return OuterClassWrapper.InnerClassWrapper(result)
8797
}
8898

8999
@objc public class InnerStructWrapper: NSObject {

0 commit comments

Comments
 (0)