forked from flutter/packages
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathast.dart
317 lines (258 loc) · 9.25 KB
/
ast.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:collection/collection.dart' show ListEquality;
import 'package:meta/meta.dart';
import 'pigeon_lib.dart';
typedef _ListEquals = bool Function(List<Object?>, List<Object?>);
final _ListEquals _listEquals = const ListEquality<dynamic>().equals;
/// Enum that represents where an [Api] is located, on the host or Flutter.
enum ApiLocation {
/// The API is for calling functions defined on the host.
host,
/// The API is for calling functions defined in Flutter.
flutter,
}
/// Superclass for all AST nodes.
class Node {}
/// Represents a method on an [Api].
class Method extends Node {
/// Parametric constructor for [Method].
Method({
required this.name,
required this.returnType,
required this.arguments,
this.isAsynchronous = false,
this.offset,
this.objcSelector = '',
this.swiftFunction = '',
this.taskQueueType = TaskQueueType.serial,
this.documentationComments = const <String>[],
});
/// The name of the method.
String name;
/// The data-type of the return value.
TypeDeclaration returnType;
/// The arguments passed into the [Method].
List<NamedType> arguments;
/// Whether the receiver of this method is expected to return synchronously or not.
bool isAsynchronous;
/// The offset in the source file where the field appears.
int? offset;
/// An override for the generated objc selector (ex. "divideNumber:by:").
String objcSelector;
/// An override for the generated swift function signature (ex. "divideNumber(_:by:)").
String swiftFunction;
/// Specifies how handlers are dispatched with respect to threading.
TaskQueueType taskQueueType;
/// List of documentation comments, separated by line.
///
/// Lines should not include the comment marker itself, but should include any
/// leading whitespace, so that any indentation in the original comment is preserved.
/// For example: [" List of documentation comments, separated by line.", ...]
List<String> documentationComments;
@override
String toString() {
final String objcSelectorStr =
objcSelector.isEmpty ? '' : ' objcSelector:$objcSelector';
final String swiftFunctionStr =
swiftFunction.isEmpty ? '' : ' swiftFunction:$swiftFunction';
return '(Method name:$name returnType:$returnType arguments:$arguments isAsynchronous:$isAsynchronous$objcSelectorStr$swiftFunctionStr documentationComments:$documentationComments)';
}
}
/// Represents a collection of [Method]s that are hosted on a given [location].
class Api extends Node {
/// Parametric constructor for [Api].
Api({
required this.name,
required this.location,
required this.methods,
this.dartHostTestHandler,
this.documentationComments = const <String>[],
});
/// The name of the API.
String name;
/// Where the API's implementation is located, host or Flutter.
ApiLocation location;
/// List of methods inside the API.
List<Method> methods;
/// The name of the Dart test interface to generate to help with testing.
String? dartHostTestHandler;
/// List of documentation comments, separated by line.
///
/// Lines should not include the comment marker itself, but should include any
/// leading whitespace, so that any indentation in the original comment is preserved.
/// For example: [" List of documentation comments, separated by line.", ...]
List<String> documentationComments;
@override
String toString() {
return '(Api name:$name location:$location methods:$methods documentationComments:$documentationComments)';
}
}
/// A specific instance of a type.
@immutable
class TypeDeclaration {
/// Constructor for [TypeDeclaration].
const TypeDeclaration({
required this.baseName,
required this.isNullable,
this.typeArguments = const <TypeDeclaration>[],
});
/// Void constructor.
const TypeDeclaration.voidDeclaration()
: baseName = 'void',
isNullable = false,
typeArguments = const <TypeDeclaration>[];
/// The base name of the [TypeDeclaration] (ex 'Foo' to 'Foo<Bar>?').
final String baseName;
/// Returns true if the declaration represents 'void'.
bool get isVoid => baseName == 'void';
/// The type arguments to the entity (ex 'Bar' to 'Foo<Bar>?').
final List<TypeDeclaration> typeArguments;
/// True if the type is nullable.
final bool isNullable;
@override
int get hashCode {
// This has to be implemented because TypeDeclaration is used as a Key to a
// Map in generator_tools.dart.
int hash = 17;
hash = hash * 37 + baseName.hashCode;
hash = hash * 37 + isNullable.hashCode;
for (final TypeDeclaration typeArgument in typeArguments) {
hash = hash * 37 + typeArgument.hashCode;
}
return hash;
}
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) {
return false;
} else {
return other is TypeDeclaration &&
baseName == other.baseName &&
isNullable == other.isNullable &&
_listEquals(typeArguments, other.typeArguments);
}
}
@override
String toString() {
final String typeArgumentsStr =
typeArguments.isEmpty ? '' : 'typeArguments:$typeArguments';
return '(TypeDeclaration baseName:$baseName isNullable:$isNullable$typeArgumentsStr)';
}
}
/// Represents a named entity that has a type.
class NamedType extends Node {
/// Parametric constructor for [NamedType].
NamedType({
required this.name,
required this.type,
this.offset,
this.documentationComments = const <String>[],
});
/// The name of the entity.
String name;
/// The type.
TypeDeclaration type;
/// The offset in the source file where the [NamedType] appears.
int? offset;
/// List of documentation comments, separated by line.
///
/// Lines should not include the comment marker itself, but should include any
/// leading whitespace, so that any indentation in the original comment is preserved.
/// For example: [" List of documentation comments, separated by line.", ...]
List<String> documentationComments;
@override
String toString() {
return '(NamedType name:$name type:$type documentationComments:$documentationComments)';
}
}
/// Represents a class with fields.
class Class extends Node {
/// Parametric constructor for [Class].
Class({
required this.name,
required this.fields,
this.documentationComments = const <String>[],
});
/// The name of the class.
String name;
/// All the fields contained in the class.
List<NamedType> fields;
/// List of documentation comments, separated by line.
///
/// Lines should not include the comment marker itself, but should include any
/// leading whitespace, so that any indentation in the original comment is preserved.
/// For example: [" List of documentation comments, separated by line.", ...]
List<String> documentationComments;
@override
String toString() {
return '(Class name:$name fields:$fields documentationComments:$documentationComments)';
}
}
/// Represents a Enum.
class Enum extends Node {
/// Parametric constructor for [Enum].
Enum({
required this.name,
required this.members,
this.documentationComments = const <String>[],
});
/// The name of the enum.
String name;
/// All of the members of the enum.
List<EnumMember> members;
/// List of documentation comments, separated by line.
///
/// Lines should not include the comment marker itself, but should include any
/// leading whitespace, so that any indentation in the original comment is preserved.
/// For example: [" List of documentation comments, separated by line.", ...]
List<String> documentationComments;
@override
String toString() {
return '(Enum name:$name members:$members documentationComments:$documentationComments)';
}
}
/// Represents a Enum member.
class EnumMember extends Node {
/// Parametric constructor for [EnumMember].
EnumMember({
required this.name,
this.documentationComments = const <String>[],
});
/// The name of the enum member.
final String name;
/// List of documentation comments, separated by line.
///
/// Lines should not include the comment marker itself, but should include any
/// leading whitespace, so that any indentation in the original comment is preserved.
/// For example: [" List of documentation comments, separated by line.", ...]
final List<String> documentationComments;
@override
String toString() {
return '(EnumMember name:$name documentationComments:$documentationComments)';
}
}
/// Top-level node for the AST.
class Root extends Node {
/// Parametric constructor for [Root].
Root({
required this.classes,
required this.apis,
required this.enums,
});
/// Factory function for generating an empty root, usually used when early errors are encountered.
factory Root.makeEmpty() {
return Root(apis: <Api>[], classes: <Class>[], enums: <Enum>[]);
}
/// All the classes contained in the AST.
List<Class> classes;
/// All the API's contained in the AST.
List<Api> apis;
/// All of the enums contained in the AST.
List<Enum> enums;
@override
String toString() {
return '(Root classes:$classes apis:$apis enums:$enums)';
}
}