OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// ----------------------------------------------------------------------- | 5 /// ----------------------------------------------------------------------- |
6 /// ERROR HANDLING | 6 /// ERROR HANDLING |
7 /// ----------------------------------------------------------------------- | 7 /// ----------------------------------------------------------------------- |
8 /// | 8 /// |
9 /// As a rule of thumb, errors that can be detected statically are handled by | 9 /// As a rule of thumb, errors that can be detected statically are handled by |
10 /// the frontend, typically by translating the erroneous code into a 'throw' or | 10 /// the frontend, typically by translating the erroneous code into a 'throw' or |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 } | 221 } |
222 return node as Constructor; | 222 return node as Constructor; |
223 } | 223 } |
224 | 224 |
225 Procedure get asProcedure { | 225 Procedure get asProcedure { |
226 if (node == null) { | 226 if (node == null) { |
227 throw '$this is not bound to an AST node. A procedure was expected'; | 227 throw '$this is not bound to an AST node. A procedure was expected'; |
228 } | 228 } |
229 return node as Procedure; | 229 return node as Procedure; |
230 } | 230 } |
| 231 |
| 232 Typedef get asTypedef { |
| 233 if (node == null) { |
| 234 throw '$this is not bound to an AST node. A typedef was expected'; |
| 235 } |
| 236 return node as Typedef; |
| 237 } |
231 } | 238 } |
232 | 239 |
233 // ------------------------------------------------------------------------ | 240 // ------------------------------------------------------------------------ |
234 // LIBRARIES and CLASSES | 241 // LIBRARIES and CLASSES |
235 // ------------------------------------------------------------------------ | 242 // ------------------------------------------------------------------------ |
236 | 243 |
237 class Library extends NamedNode implements Comparable<Library> { | 244 class Library extends NamedNode implements Comparable<Library> { |
238 /// An import path to this library. | 245 /// An import path to this library. |
239 /// | 246 /// |
240 /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme. | 247 /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme. |
(...skipping 10 matching lines...) Expand all Loading... |
251 /// Classes of an external library are loaded at one of the [ClassLevel]s | 258 /// Classes of an external library are loaded at one of the [ClassLevel]s |
252 /// other than [ClassLevel.Body]. Members in an external library have no | 259 /// other than [ClassLevel.Body]. Members in an external library have no |
253 /// body, but have their typed interface present. | 260 /// body, but have their typed interface present. |
254 /// | 261 /// |
255 /// If the libary is non-external, then its classes are at [ClassLevel.Body] | 262 /// If the libary is non-external, then its classes are at [ClassLevel.Body] |
256 /// and all members are loaded. | 263 /// and all members are loaded. |
257 bool isExternal; | 264 bool isExternal; |
258 | 265 |
259 String name; | 266 String name; |
260 final List<DeferredImport> deferredImports; | 267 final List<DeferredImport> deferredImports; |
| 268 final List<Typedef> typedefs; |
261 final List<Class> classes; | 269 final List<Class> classes; |
262 final List<Procedure> procedures; | 270 final List<Procedure> procedures; |
263 final List<Field> fields; | 271 final List<Field> fields; |
264 | 272 |
265 Library(this.importUri, | 273 Library(this.importUri, |
266 {this.name, | 274 {this.name, |
267 this.isExternal: false, | 275 this.isExternal: false, |
268 List<DeferredImport> imports, | 276 List<DeferredImport> imports, |
| 277 List<Typedef> typedefs, |
269 List<Class> classes, | 278 List<Class> classes, |
270 List<Procedure> procedures, | 279 List<Procedure> procedures, |
271 List<Field> fields, | 280 List<Field> fields, |
272 this.fileUri, | 281 this.fileUri, |
273 Reference reference}) | 282 Reference reference}) |
274 : this.deferredImports = imports ?? <DeferredImport>[], | 283 : this.deferredImports = imports ?? <DeferredImport>[], |
| 284 this.typedefs = typedefs ?? <Typedef>[], |
275 this.classes = classes ?? <Class>[], | 285 this.classes = classes ?? <Class>[], |
276 this.procedures = procedures ?? <Procedure>[], | 286 this.procedures = procedures ?? <Procedure>[], |
277 this.fields = fields ?? <Field>[], | 287 this.fields = fields ?? <Field>[], |
278 super(reference) { | 288 super(reference) { |
| 289 setParents(this.deferredImports, this); |
| 290 setParents(this.typedefs, this); |
279 setParents(this.classes, this); | 291 setParents(this.classes, this); |
280 setParents(this.procedures, this); | 292 setParents(this.procedures, this); |
281 setParents(this.fields, this); | 293 setParents(this.fields, this); |
282 } | 294 } |
283 | 295 |
284 /// Returns the top-level fields and procedures defined in this library. | 296 /// Returns the top-level fields and procedures defined in this library. |
285 /// | 297 /// |
286 /// This getter is for convenience, not efficiency. Consider manually | 298 /// This getter is for convenience, not efficiency. Consider manually |
287 /// iterating the members to speed up code in production. | 299 /// iterating the members to speed up code in production. |
288 Iterable<Member> get members => | 300 Iterable<Member> get members => |
289 <Iterable<Member>>[fields, procedures].expand((x) => x); | 301 <Iterable<Member>>[fields, procedures].expand((x) => x); |
290 | 302 |
291 void addMember(Member member) { | 303 void addMember(Member member) { |
292 member.parent = this; | 304 member.parent = this; |
293 if (member is Procedure) { | 305 if (member is Procedure) { |
294 procedures.add(member); | 306 procedures.add(member); |
295 } else if (member is Field) { | 307 } else if (member is Field) { |
296 fields.add(member); | 308 fields.add(member); |
297 } else { | 309 } else { |
298 throw new ArgumentError(member); | 310 throw new ArgumentError(member); |
299 } | 311 } |
300 } | 312 } |
301 | 313 |
302 void addClass(Class class_) { | 314 void addClass(Class class_) { |
303 class_.parent = this; | 315 class_.parent = this; |
304 classes.add(class_); | 316 classes.add(class_); |
305 } | 317 } |
306 | 318 |
| 319 void addTypedef(Typedef typedef_) { |
| 320 typedef_.parent = this; |
| 321 typedefs.add(typedef_); |
| 322 } |
| 323 |
307 void computeCanonicalNames() { | 324 void computeCanonicalNames() { |
308 assert(canonicalName != null); | 325 assert(canonicalName != null); |
| 326 for (var typedef_ in typedefs) { |
| 327 canonicalName.getChildFromTypedef(typedef_).bindTo(typedef_.reference); |
| 328 } |
309 for (var field in fields) { | 329 for (var field in fields) { |
310 canonicalName.getChildFromMember(field).bindTo(field.reference); | 330 canonicalName.getChildFromMember(field).bindTo(field.reference); |
311 } | 331 } |
312 for (var member in procedures) { | 332 for (var member in procedures) { |
313 canonicalName.getChildFromMember(member).bindTo(member.reference); | 333 canonicalName.getChildFromMember(member).bindTo(member.reference); |
314 } | 334 } |
315 for (var class_ in classes) { | 335 for (var class_ in classes) { |
316 canonicalName.getChild(class_.name).bindTo(class_.reference); | 336 canonicalName.getChild(class_.name).bindTo(class_.reference); |
317 class_.computeCanonicalNames(); | 337 class_.computeCanonicalNames(); |
318 } | 338 } |
319 } | 339 } |
320 | 340 |
321 accept(TreeVisitor v) => v.visitLibrary(this); | 341 accept(TreeVisitor v) => v.visitLibrary(this); |
322 | 342 |
323 visitChildren(Visitor v) { | 343 visitChildren(Visitor v) { |
| 344 visitList(deferredImports, v); |
| 345 visitList(typedefs, v); |
324 visitList(classes, v); | 346 visitList(classes, v); |
325 visitList(procedures, v); | 347 visitList(procedures, v); |
326 visitList(fields, v); | 348 visitList(fields, v); |
327 } | 349 } |
328 | 350 |
329 transformChildren(Transformer v) { | 351 transformChildren(Transformer v) { |
| 352 transformList(deferredImports, v, this); |
| 353 transformList(typedefs, v, this); |
330 transformList(classes, v, this); | 354 transformList(classes, v, this); |
331 transformList(procedures, v, this); | 355 transformList(procedures, v, this); |
332 transformList(fields, v, this); | 356 transformList(fields, v, this); |
333 } | 357 } |
334 | 358 |
335 static int _libraryIdCounter = 0; | 359 static int _libraryIdCounter = 0; |
336 int _libraryId = ++_libraryIdCounter; | 360 int _libraryId = ++_libraryIdCounter; |
337 | 361 |
338 int compareTo(Library other) => _libraryId - other._libraryId; | 362 int compareTo(Library other) => _libraryId - other._libraryId; |
339 | 363 |
(...skipping 19 matching lines...) Expand all Loading... |
359 Library get enclosingLibrary => parent; | 383 Library get enclosingLibrary => parent; |
360 Library get importedLibrary => importedLibraryReference.asLibrary; | 384 Library get importedLibrary => importedLibraryReference.asLibrary; |
361 | 385 |
362 accept(TreeVisitor v) => v.visitDeferredImport(this); | 386 accept(TreeVisitor v) => v.visitDeferredImport(this); |
363 | 387 |
364 visitChildren(Visitor v) {} | 388 visitChildren(Visitor v) {} |
365 | 389 |
366 transformChildren(Transformer v) {} | 390 transformChildren(Transformer v) {} |
367 } | 391 } |
368 | 392 |
| 393 /// Declaration of a type alias. |
| 394 class Typedef extends NamedNode { |
| 395 /// The uri of the source file that contains the declaration of this typedef. |
| 396 String fileUri; |
| 397 List<Expression> annotations = const <Expression>[]; |
| 398 String name; |
| 399 final List<TypeParameter> typeParameters; |
| 400 DartType type; |
| 401 |
| 402 Typedef(this.name, this.type, |
| 403 {Reference reference, this.fileUri, List<TypeParameter> typeParameters}) |
| 404 : this.typeParameters = typeParameters ?? <TypeParameter>[], |
| 405 super(reference) { |
| 406 setParents(this.typeParameters, this); |
| 407 } |
| 408 |
| 409 Library get enclosingLibrary => parent; |
| 410 |
| 411 accept(TreeVisitor v) { |
| 412 return v.visitTypedef(this); |
| 413 } |
| 414 |
| 415 transformChildren(Transformer v) { |
| 416 transformList(annotations, v, this); |
| 417 transformList(typeParameters, v, this); |
| 418 if (type != null) { |
| 419 type = v.visitDartType(type); |
| 420 } |
| 421 } |
| 422 |
| 423 visitChildren(Visitor v) { |
| 424 visitList(annotations, v); |
| 425 visitList(typeParameters, v); |
| 426 type?.accept(v); |
| 427 } |
| 428 |
| 429 void addAnnotation(Expression node) { |
| 430 if (annotations.isEmpty) { |
| 431 annotations = <Expression>[]; |
| 432 } |
| 433 annotations.add(node); |
| 434 node.parent = this; |
| 435 } |
| 436 } |
| 437 |
369 /// The degree to which the contents of a class have been loaded into memory. | 438 /// The degree to which the contents of a class have been loaded into memory. |
370 /// | 439 /// |
371 /// Each level imply the requirements of the previous ones. | 440 /// Each level imply the requirements of the previous ones. |
372 enum ClassLevel { | 441 enum ClassLevel { |
373 /// Temporary loading level for internal use by IR producers. Consumers of | 442 /// Temporary loading level for internal use by IR producers. Consumers of |
374 /// kernel code should not expect to see classes at this level. | 443 /// kernel code should not expect to see classes at this level. |
375 Temporary, | 444 Temporary, |
376 | 445 |
377 /// The class may be used as a type, and it may contain members that are | 446 /// The class may be used as a type, and it may contain members that are |
378 /// referenced from this build unit. | 447 /// referenced from this build unit. |
(...skipping 3309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3688 /// cyclic structures that are constructed by mutation. | 3757 /// cyclic structures that are constructed by mutation. |
3689 /// | 3758 /// |
3690 /// The `==` operator on [DartType]s compare based on type equality, not | 3759 /// The `==` operator on [DartType]s compare based on type equality, not |
3691 /// object identity. | 3760 /// object identity. |
3692 abstract class DartType extends Node { | 3761 abstract class DartType extends Node { |
3693 const DartType(); | 3762 const DartType(); |
3694 | 3763 |
3695 accept(DartTypeVisitor v); | 3764 accept(DartTypeVisitor v); |
3696 | 3765 |
3697 bool operator ==(Object other); | 3766 bool operator ==(Object other); |
| 3767 |
| 3768 /// If this is a typedef type, repeatedly unfolds its type definition until |
| 3769 /// the root term is not a typedef type, otherwise returns the type itself. |
| 3770 /// |
| 3771 /// Will never return a typedef type. |
| 3772 DartType get unalias => this; |
| 3773 |
| 3774 /// If this is a typedef type, unfolds its type definition once, otherwise |
| 3775 /// returns the type itself. |
| 3776 DartType get unaliasOnce => this; |
3698 } | 3777 } |
3699 | 3778 |
3700 /// The type arising from invalid type annotations. | 3779 /// The type arising from invalid type annotations. |
3701 /// | 3780 /// |
3702 /// Can usually be treated as 'dynamic', but should occasionally be handled | 3781 /// Can usually be treated as 'dynamic', but should occasionally be handled |
3703 /// differently, e.g. `x is ERROR` should evaluate to false. | 3782 /// differently, e.g. `x is ERROR` should evaluate to false. |
3704 class InvalidType extends DartType { | 3783 class InvalidType extends DartType { |
3705 final int hashCode = 12345; | 3784 final int hashCode = 12345; |
3706 | 3785 |
3707 const InvalidType(); | 3786 const InvalidType(); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3917 } | 3996 } |
3918 hash = 0x3fffffff & (hash * 31 + returnType.hashCode); | 3997 hash = 0x3fffffff & (hash * 31 + returnType.hashCode); |
3919 for (int i = 0; i < typeParameters.length; ++i) { | 3998 for (int i = 0; i < typeParameters.length; ++i) { |
3920 // Remove the type parameters from the scope again. | 3999 // Remove the type parameters from the scope again. |
3921 _temporaryHashCodeTable.remove(typeParameters[i]); | 4000 _temporaryHashCodeTable.remove(typeParameters[i]); |
3922 } | 4001 } |
3923 return hash; | 4002 return hash; |
3924 } | 4003 } |
3925 } | 4004 } |
3926 | 4005 |
| 4006 /// A use of a [Typedef] as a type. |
| 4007 /// |
| 4008 /// The underlying type can be extracted using [unalias]. |
| 4009 class TypedefType extends DartType { |
| 4010 final Reference typedefReference; |
| 4011 final List<DartType> typeArguments; |
| 4012 |
| 4013 TypedefType(Typedef typedefNode, [List<DartType> typeArguments]) |
| 4014 : this.byReference( |
| 4015 typedefNode.reference, typeArguments ?? const <DartType>[]); |
| 4016 |
| 4017 TypedefType.byReference(this.typedefReference, this.typeArguments); |
| 4018 |
| 4019 Typedef get typedefNode => typedefReference.asTypedef; |
| 4020 |
| 4021 accept(DartTypeVisitor v) => v.visitTypedefType(this); |
| 4022 |
| 4023 visitChildren(Visitor v) { |
| 4024 visitList(typeArguments, v); |
| 4025 v.visitTypedefReference(typedefNode); |
| 4026 } |
| 4027 |
| 4028 DartType get unaliasOnce { |
| 4029 return Substitution.fromTypedefType(this).substituteType(typedefNode.type); |
| 4030 } |
| 4031 |
| 4032 DartType get unalias { |
| 4033 return unaliasOnce.unalias; |
| 4034 } |
| 4035 |
| 4036 bool operator ==(Object other) { |
| 4037 if (identical(this, other)) return true; |
| 4038 if (other is TypedefType) { |
| 4039 if (typedefReference != other.typedefReference || |
| 4040 typeArguments.length != other.typeArguments.length) { |
| 4041 return false; |
| 4042 } |
| 4043 for (int i = 0; i < typeArguments.length; ++i) { |
| 4044 if (typeArguments[i] != other.typeArguments[i]) return false; |
| 4045 } |
| 4046 return true; |
| 4047 } |
| 4048 return false; |
| 4049 } |
| 4050 |
| 4051 int get hashCode { |
| 4052 int hash = 0x3fffffff & typedefNode.hashCode; |
| 4053 for (int i = 0; i < typeArguments.length; ++i) { |
| 4054 hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode)); |
| 4055 } |
| 4056 return hash; |
| 4057 } |
| 4058 } |
| 4059 |
3927 /// A named parameter in [FunctionType]. | 4060 /// A named parameter in [FunctionType]. |
3928 class NamedType extends Node implements Comparable<NamedType> { | 4061 class NamedType extends Node implements Comparable<NamedType> { |
3929 final String name; | 4062 final String name; |
3930 final DartType type; | 4063 final DartType type; |
3931 | 4064 |
3932 NamedType(this.name, this.type); | 4065 NamedType(this.name, this.type); |
3933 | 4066 |
3934 bool operator ==(Object other) { | 4067 bool operator ==(Object other) { |
3935 return other is NamedType && name == other.name && type == other.type; | 4068 return other is NamedType && name == other.name && type == other.type; |
3936 } | 4069 } |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4316 /// library has not been assigned a canonical name yet. | 4449 /// library has not been assigned a canonical name yet. |
4317 /// | 4450 /// |
4318 /// Returns `null` if the library is `null`. | 4451 /// Returns `null` if the library is `null`. |
4319 CanonicalName getCanonicalNameOfLibrary(Library library) { | 4452 CanonicalName getCanonicalNameOfLibrary(Library library) { |
4320 if (library == null) return null; | 4453 if (library == null) return null; |
4321 if (library.canonicalName == null) { | 4454 if (library.canonicalName == null) { |
4322 throw '$library has no canonical name'; | 4455 throw '$library has no canonical name'; |
4323 } | 4456 } |
4324 return library.canonicalName; | 4457 return library.canonicalName; |
4325 } | 4458 } |
| 4459 |
| 4460 /// Returns the canonical name of [typedef_], or throws an exception if the |
| 4461 /// typedef has not been assigned a canonical name yet. |
| 4462 /// |
| 4463 /// Returns `null` if the typedef is `null`. |
| 4464 CanonicalName getCanonicalNameOfTypedef(Typedef typedef_) { |
| 4465 if (typedef_ == null) return null; |
| 4466 if (typedef_.canonicalName == null) { |
| 4467 throw '$typedef_ has no canonical name'; |
| 4468 } |
| 4469 return typedef_.canonicalName; |
| 4470 } |
OLD | NEW |