Skip to content

Commit 9ef9699

Browse files
[swift2objc] Property Parsing and Generation Refactoring (#2056)
1 parent 479adb7 commit 9ef9699

File tree

6 files changed

+381
-42
lines changed

6 files changed

+381
-42
lines changed

pkgs/swift2objc/lib/src/ast/declarations/compounds/members/property_declaration.dart

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,29 @@ class PropertyDeclaration extends AstNode
3333
@override
3434
bool async;
3535

36+
bool mutating;
37+
3638
bool hasSetter;
3739

3840
PropertyStatements? getter;
3941
PropertyStatements? setter;
4042

4143
bool isStatic;
4244

43-
PropertyDeclaration({
44-
required this.id,
45-
required this.name,
46-
required this.type,
47-
this.hasSetter = false,
48-
this.isConstant = false,
49-
this.hasObjCAnnotation = false,
50-
this.getter,
51-
this.setter,
52-
this.isStatic = false,
53-
this.throws = false,
54-
this.async = false,
55-
}) : assert(!(isConstant && hasSetter)),
45+
PropertyDeclaration(
46+
{required this.id,
47+
required this.name,
48+
required this.type,
49+
this.hasSetter = false,
50+
this.isConstant = false,
51+
this.hasObjCAnnotation = false,
52+
this.getter,
53+
this.setter,
54+
this.isStatic = false,
55+
this.throws = false,
56+
this.async = false,
57+
this.mutating = false})
58+
: assert(!(isConstant && hasSetter)),
5659
assert(!(hasSetter && throws));
5760

5861
@override

pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_variable_declaration.dart

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@ PropertyDeclaration parsePropertyDeclaration(
1515
ParsedSymbolgraph symbolgraph, {
1616
bool isStatic = false,
1717
}) {
18-
final isConstant = _parseVariableIsConstant(propertySymbolJson);
18+
final info = parsePropertyInfo(propertySymbolJson['declarationFragments']);
1919
return PropertyDeclaration(
2020
id: parseSymbolId(propertySymbolJson),
2121
name: parseSymbolName(propertySymbolJson),
2222
type: _parseVariableType(propertySymbolJson, symbolgraph),
2323
hasObjCAnnotation: parseSymbolHasObjcAnnotation(propertySymbolJson),
24-
isConstant: isConstant,
25-
hasSetter: isConstant ? false : _parsePropertyHasSetter(propertySymbolJson),
24+
isConstant: info.constant,
25+
hasSetter: info.constant ? false : info.setter,
2626
isStatic: isStatic,
27-
throws: _parseVariableThrows(propertySymbolJson),
28-
async: _parseVariableAsync(propertySymbolJson),
27+
throws: info.throws,
28+
async: info.async,
2929
);
3030
}
3131

@@ -34,15 +34,14 @@ GlobalVariableDeclaration parseGlobalVariableDeclaration(
3434
ParsedSymbolgraph symbolgraph, {
3535
bool isStatic = false,
3636
}) {
37-
final isConstant = _parseVariableIsConstant(variableSymbolJson);
38-
final hasSetter = _parsePropertyHasSetter(variableSymbolJson);
37+
final info = parsePropertyInfo(variableSymbolJson['declarationFragments']);
3938
return GlobalVariableDeclaration(
4039
id: parseSymbolId(variableSymbolJson),
4140
name: parseSymbolName(variableSymbolJson),
4241
type: _parseVariableType(variableSymbolJson, symbolgraph),
43-
isConstant: isConstant || !hasSetter,
44-
throws: _parseVariableThrows(variableSymbolJson),
45-
async: _parseVariableAsync(variableSymbolJson),
42+
isConstant: info.constant || !info.setter,
43+
throws: info.throws,
44+
async: info.async,
4645
);
4746
}
4847

@@ -53,9 +52,7 @@ ReferredType _parseVariableType(
5352
parseTypeAfterSeparator(
5453
TokenList(propertySymbolJson['names']['subHeading']), symbolgraph);
5554

56-
bool _parseVariableIsConstant(Json variableSymbolJson) {
57-
final fragmentsJson = variableSymbolJson['declarationFragments'];
58-
55+
bool _parseVariableIsConstant(Json fragmentsJson) {
5956
final declarationKeyword = fragmentsJson.firstWhere(
6057
(json) =>
6158
matchFragment(json, 'keyword', 'var') ||
@@ -65,24 +62,39 @@ bool _parseVariableIsConstant(Json variableSymbolJson) {
6562
'Expected to find "var" or "let" as a keyword, found none',
6663
),
6764
);
68-
6965
return matchFragment(declarationKeyword, 'keyword', 'let');
7066
}
7167

72-
bool _parseVariableThrows(Json json) {
73-
final throws = json['declarationFragments']
74-
.any((frag) => matchFragment(frag, 'keyword', 'throws'));
75-
return throws;
68+
bool _findKeywordInFragments(Json json, String keyword) {
69+
return json.any((frag) => matchFragment(frag, 'keyword', keyword));
7670
}
7771

78-
bool _parseVariableAsync(Json json) {
79-
final async = json['declarationFragments']
80-
.any((frag) => matchFragment(frag, 'keyword', 'async'));
81-
return async;
72+
typedef ParsedPropertyInfo = ({
73+
bool async,
74+
bool throws,
75+
bool constant,
76+
bool getter,
77+
bool setter,
78+
bool mutating,
79+
});
80+
81+
ParsedPropertyInfo parsePropertyInfo(Json json) {
82+
final (getter, setter) = _parsePropertyGetAndSet(json);
83+
return (
84+
constant: _parseVariableIsConstant(json),
85+
async: _findKeywordInFragments(json, 'async'),
86+
throws: _findKeywordInFragments(json, 'throws'),
87+
getter: getter,
88+
setter: setter,
89+
mutating: _findKeywordInFragments(json, 'mutating')
90+
);
8291
}
8392

84-
bool _parsePropertyHasSetter(Json propertySymbolJson) {
85-
final fragmentsJson = propertySymbolJson['declarationFragments'];
93+
(bool, bool) _parsePropertyGetAndSet(Json fragmentsJson, {String? path}) {
94+
if (fragmentsJson.any((frag) => matchFragment(frag, 'text', ' { get }'))) {
95+
// has explicit getter and no explicit setter
96+
return (true, false);
97+
}
8698

8799
final hasExplicitSetter =
88100
fragmentsJson.any((frag) => matchFragment(frag, 'keyword', 'set'));
@@ -92,21 +104,21 @@ bool _parsePropertyHasSetter(Json propertySymbolJson) {
92104
if (hasExplicitGetter) {
93105
if (hasExplicitSetter) {
94106
// has explicit getter and has explicit setter
95-
return true;
107+
return (true, true);
96108
} else {
97109
// has explicit getter and no explicit setter
98-
return false;
110+
return (true, false);
99111
}
100112
} else {
101113
if (hasExplicitSetter) {
102114
// has no explicit getter and but has explicit setter
103115
throw Exception(
104-
'Invalid property at ${propertySymbolJson.path}. '
116+
'Invalid property${path != null ? ' at $path' : ''}. '
105117
'Properties can not have a setter without a getter',
106118
);
107119
} else {
108-
// has no explicit getter and no explicit setter
109-
return true;
120+
// has implicit getter and implicit setter
121+
return (true, true);
110122
}
111123
}
112124
}

pkgs/swift2objc/lib/src/transformer/transformers/transform_variable.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Declaration? transformProperty(
3333
originalProperty,
3434
globalNamer,
3535
transformationMap,
36+
property: true,
3637
wrapperPropertyName: originalProperty.name,
3738
variableReferenceExpression: '$propertySource.${originalProperty.name}',
3839
);
@@ -60,6 +61,7 @@ Declaration _transformVariable(
6061
VariableDeclaration originalVariable,
6162
UniqueNamer globalNamer,
6263
TransformationMap transformationMap, {
64+
bool property = false,
6365
required String wrapperPropertyName,
6466
required String variableReferenceExpression,
6567
}) {

pkgs/swift2objc/test/integration/structs_and_properties_input.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ public struct MyStruct {
2929

3030
public let representableConstantProperty: Int
3131

32+
public var mutatingProperty: Int {
33+
mutating get { 1 }
34+
}
35+
3236

3337
init(
3438
customVariableProperty: MyOtherStruct,

pkgs/swift2objc/test/integration/structs_and_properties_output.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ import Foundation
1414
@objc public class MyStructWrapper: NSObject {
1515
var wrappedInstance: MyStruct
1616

17+
@objc public var mutatingProperty: Int {
18+
get {
19+
wrappedInstance.mutatingProperty
20+
}
21+
}
22+
1723
@objc public var customGetterProperty: MyOtherStructWrapper {
1824
get {
1925
MyOtherStructWrapper(wrappedInstance.customGetterProperty)

0 commit comments

Comments
 (0)