Skip to content

Commit f723a58

Browse files
authored
Add support for global functions and variables (#1610)
1 parent 6595118 commit f723a58

26 files changed

+561
-229
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// An interface to describe a Swift entity's compound membership
6+
abstract interface class CompoundMemeber {
7+
abstract final bool isStatic;
8+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import '../shared/referred_type.dart';
6+
import 'declaration.dart';
7+
import 'executable.dart';
8+
import 'parameterizable.dart';
9+
import 'type_parameterizable.dart';
10+
11+
/// Describes a function-like entity.
12+
abstract interface class FunctionDeclaration
13+
implements Declaration, Parameterizable, Executable, TypeParameterizable {
14+
abstract final ReferredType? returnType;
15+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import '../shared/referred_type.dart';
6+
import 'declaration.dart';
7+
8+
/// Describes a variable-like entity.
9+
abstract interface class VariableDeclaration implements Declaration {
10+
abstract final bool isConstant;
11+
abstract final ReferredType type;
12+
}

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

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,14 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import '../../../_core/interfaces/declaration.dart';
6-
import '../../../_core/interfaces/executable.dart';
5+
import '../../../_core/interfaces/function_declaration.dart';
76
import '../../../_core/interfaces/objc_annotatable.dart';
8-
import '../../../_core/interfaces/parameterizable.dart';
9-
import '../../../_core/interfaces/type_parameterizable.dart';
107
import '../../../_core/shared/parameter.dart';
118
import '../../../_core/shared/referred_type.dart';
129

1310
/// Describes a method declaration for a Swift compound entity
1411
/// (e.g, class, structs)
15-
class MethodDeclaration
16-
implements
17-
Declaration,
18-
TypeParameterizable,
19-
Executable,
20-
Parameterizable,
21-
ObjCAnnotatable {
12+
class MethodDeclaration implements FunctionDeclaration, ObjCAnnotatable {
2213
@override
2314
String id;
2415

@@ -37,6 +28,7 @@ class MethodDeclaration
3728
@override
3829
List<String> statements;
3930

31+
@override
4032
ReferredType? returnType;
4133

4234
bool isStatic;

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import '../../../_core/interfaces/declaration.dart';
65
import '../../../_core/interfaces/executable.dart';
76
import '../../../_core/interfaces/objc_annotatable.dart';
7+
import '../../../_core/interfaces/variable_declaration.dart';
88
import '../../../_core/shared/referred_type.dart';
99

1010
/// Describes a property declaration for a Swift compound entity
1111
/// (e.g, class, structs)
12-
class PropertyDeclaration implements Declaration, ObjCAnnotatable {
12+
class PropertyDeclaration implements VariableDeclaration, ObjCAnnotatable {
1313
@override
1414
String id;
1515

@@ -19,25 +19,30 @@ class PropertyDeclaration implements Declaration, ObjCAnnotatable {
1919
@override
2020
bool hasObjCAnnotation;
2121

22+
@override
23+
ReferredType type;
24+
25+
@override
26+
bool isConstant;
27+
2228
bool hasSetter;
2329

2430
PropertyStatements? getter;
2531
PropertyStatements? setter;
2632

27-
ReferredType type;
28-
2933
bool isStatic;
3034

3135
PropertyDeclaration({
3236
required this.id,
3337
required this.name,
3438
required this.type,
3539
this.hasSetter = false,
40+
this.isConstant = false,
3641
this.hasObjCAnnotation = false,
3742
this.getter,
3843
this.setter,
3944
this.isStatic = false,
40-
});
45+
}) : assert(!isConstant || !hasSetter);
4146
}
4247

4348
class PropertyStatements implements Executable {

pkgs/swift2objc/lib/src/ast/declarations/globals/globals.dart

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,25 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import '../../_core/interfaces/declaration.dart';
6-
import '../../_core/interfaces/parameterizable.dart';
7-
import '../../_core/interfaces/type_parameterizable.dart';
5+
import '../../_core/interfaces/function_declaration.dart';
6+
import '../../_core/interfaces/variable_declaration.dart';
87
import '../../_core/shared/parameter.dart';
98
import '../../_core/shared/referred_type.dart';
109

1110
/// A container for globally defined values (i.e variables & constants)
1211
/// and functions.
1312
class Globals {
1413
List<GlobalFunctionDeclaration> functions;
15-
List<GlobalValueDeclaration> values;
14+
List<GlobalVariableDeclaration> variables;
1615

1716
Globals({
1817
required this.functions,
19-
required this.values,
18+
required this.variables,
2019
});
2120
}
2221

2322
/// Describes a globally defined function.
24-
class GlobalFunctionDeclaration
25-
implements Declaration, Parameterizable, TypeParameterizable {
23+
class GlobalFunctionDeclaration implements FunctionDeclaration {
2624
@override
2725
String id;
2826

@@ -35,30 +33,37 @@ class GlobalFunctionDeclaration
3533
@override
3634
List<GenericType> typeParams;
3735

38-
ReferredType returnType;
36+
@override
37+
ReferredType? returnType;
38+
39+
@override
40+
List<String> statements;
3941

4042
GlobalFunctionDeclaration({
4143
required this.id,
4244
required this.name,
4345
required this.params,
44-
required this.typeParams,
4546
required this.returnType,
47+
this.typeParams = const [],
48+
this.statements = const [],
4649
});
4750
}
4851

4952
/// Describes a globally defined values (i.e variable/constant).
50-
class GlobalValueDeclaration implements Declaration {
53+
class GlobalVariableDeclaration implements VariableDeclaration {
5154
@override
5255
String id;
5356

5457
@override
5558
String name;
5659

57-
DeclaredType type;
60+
@override
61+
ReferredType type;
5862

63+
@override
5964
bool isConstant;
6065

61-
GlobalValueDeclaration({
66+
GlobalVariableDeclaration({
6267
required this.id,
6368
required this.name,
6469
required this.type,

pkgs/swift2objc/lib/src/generator/generators/class_generator.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,15 @@ List<String> _generateClassProperties(ClassDeclaration declaration) {
104104
return declaration.properties.map(
105105
(property) {
106106
final header = StringBuffer();
107+
107108
if (property.hasObjCAnnotation) {
108109
header.write('@objc ');
109110
}
110111

112+
if (property.isStatic) {
113+
header.write('static ');
114+
}
115+
111116
header.write('public var ${property.name}: ${property.type.name} {');
112117

113118
final getterLines = [

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extension TopLevelOnly<T extends Declaration> on List<T> {
3333
(declaration) =>
3434
declaration is CompoundDeclaration ||
3535
declaration is EnumDeclaration ||
36-
declaration is GlobalValueDeclaration ||
36+
declaration is GlobalVariableDeclaration ||
3737
declaration is GlobalFunctionDeclaration,
3838
).toList();
3939
}
@@ -55,7 +55,7 @@ String parseSymbolName(Json symbolJson) {
5555
.get();
5656
}
5757

58-
bool symbolHasObjcAnnotation(Json symbolJson) {
58+
bool parseSymbolHasObjcAnnotation(Json symbolJson) {
5959
return symbolJson['declarationFragments'].any(
6060
(json) =>
6161
json['kind'].exists &&

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ InitializerDeclaration parseInitializerDeclaration(
1111
return InitializerDeclaration(
1212
id: parseSymbolId(initializerSymbolJson),
1313
params: parseInitializerParams(initializerSymbolJson, symbolgraph),
14-
hasObjCAnnotation: symbolHasObjcAnnotation(initializerSymbolJson),
14+
hasObjCAnnotation: parseSymbolHasObjcAnnotation(initializerSymbolJson),
1515
);
1616
}
1717

pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_property_declaration.dart renamed to pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_variable_declaration.dart

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import '../../../ast/_core/interfaces/declaration.dart';
22
import '../../../ast/_core/shared/referred_type.dart';
33
import '../../../ast/declarations/compounds/members/property_declaration.dart';
4+
import '../../../ast/declarations/globals/globals.dart';
45
import '../../_core/json.dart';
56
import '../../_core/parsed_symbolgraph.dart';
67
import '../../_core/utils.dart';
@@ -11,17 +12,32 @@ PropertyDeclaration parsePropertyDeclaration(
1112
ParsedSymbolgraph symbolgraph, {
1213
bool isStatic = false,
1314
}) {
15+
final isConstant = _parseVariableIsConstant(propertySymbolJson);
1416
return PropertyDeclaration(
1517
id: parseSymbolId(propertySymbolJson),
1618
name: parseSymbolName(propertySymbolJson),
17-
type: _parsePropertyType(propertySymbolJson, symbolgraph),
18-
hasObjCAnnotation: symbolHasObjcAnnotation(propertySymbolJson),
19-
hasSetter: _propertyHasSetter(propertySymbolJson),
19+
type: _parseVariableType(propertySymbolJson, symbolgraph),
20+
hasObjCAnnotation: parseSymbolHasObjcAnnotation(propertySymbolJson),
21+
isConstant: isConstant,
22+
hasSetter: isConstant ? false : _parsePropertyHasSetter(propertySymbolJson),
2023
isStatic: isStatic,
2124
);
2225
}
2326

24-
ReferredType _parsePropertyType(
27+
GlobalVariableDeclaration parseGlobalVariableDeclaration(
28+
Json variableSymbolJson,
29+
ParsedSymbolgraph symbolgraph, {
30+
bool isStatic = false,
31+
}) {
32+
return GlobalVariableDeclaration(
33+
id: parseSymbolId(variableSymbolJson),
34+
name: parseSymbolName(variableSymbolJson),
35+
type: _parseVariableType(variableSymbolJson, symbolgraph),
36+
isConstant: _parseVariableIsConstant(variableSymbolJson),
37+
);
38+
}
39+
40+
ReferredType _parseVariableType(
2541
Json propertySymbolJson,
2642
ParsedSymbolgraph symbolgraph,
2743
) {
@@ -47,8 +63,8 @@ ReferredType _parsePropertyType(
4763
return typeDeclaration.asDeclaredType;
4864
}
4965

50-
bool _propertyHasSetter(Json propertySymbolJson) {
51-
final fragmentsJson = propertySymbolJson['declarationFragments'];
66+
bool _parseVariableIsConstant(Json variableSymbolJson) {
67+
final fragmentsJson = variableSymbolJson['declarationFragments'];
5268

5369
final declarationKeywordJson = fragmentsJson.firstWhere(
5470
(json) {
@@ -67,25 +83,38 @@ bool _propertyHasSetter(Json propertySymbolJson) {
6783

6884
final declarationKeyword = declarationKeywordJson['spelling'].get<String>();
6985

70-
if (declarationKeyword == 'var') {
71-
final hasExplicitSetter = fragmentsJson.any(
72-
(json) => json['spelling'].get<String>() == 'set',
73-
);
86+
return declarationKeyword == 'let';
87+
}
7488

75-
final hasExplicitGetter = fragmentsJson.any(
76-
(json) => json['spelling'].get<String>() == 'get',
77-
);
89+
bool _parsePropertyHasSetter(Json propertySymbolJson) {
90+
final fragmentsJson = propertySymbolJson['declarationFragments'];
7891

79-
if (hasExplicitGetter) {
80-
if (hasExplicitSetter) {
81-
return true;
82-
} else {
83-
return false;
84-
}
85-
}
92+
final hasExplicitSetter = fragmentsJson.any(
93+
(json) => json['spelling'].get<String>() == 'set',
94+
);
8695

87-
return true;
88-
}
96+
final hasExplicitGetter = fragmentsJson.any(
97+
(json) => json['spelling'].get<String>() == 'get',
98+
);
8999

90-
return false;
100+
if (hasExplicitGetter) {
101+
if (hasExplicitSetter) {
102+
// has explicit getter and has explicit setter
103+
return true;
104+
} else {
105+
// has explicit getter and no explicit setter
106+
return false;
107+
}
108+
} else {
109+
if (hasExplicitSetter) {
110+
// has no explicit getter and but has explicit setter
111+
throw Exception(
112+
'Invalid property at ${propertySymbolJson.path}. '
113+
'Properties can not have a setter without a getter',
114+
);
115+
} else {
116+
// has no explicit getter and no explicit setter
117+
return true;
118+
}
119+
}
91120
}

0 commit comments

Comments
 (0)