| 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 } | |
| 238 } | 231 } |
| 239 | 232 |
| 240 // ------------------------------------------------------------------------ | 233 // ------------------------------------------------------------------------ |
| 241 // LIBRARIES and CLASSES | 234 // LIBRARIES and CLASSES |
| 242 // ------------------------------------------------------------------------ | 235 // ------------------------------------------------------------------------ |
| 243 | 236 |
| 244 class Library extends NamedNode implements Comparable<Library> { | 237 class Library extends NamedNode implements Comparable<Library> { |
| 245 /// An import path to this library. | 238 /// An import path to this library. |
| 246 /// | 239 /// |
| 247 /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme. | 240 /// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 258 /// Classes of an external library are loaded at one of the [ClassLevel]s | 251 /// Classes of an external library are loaded at one of the [ClassLevel]s |
| 259 /// other than [ClassLevel.Body]. Members in an external library have no | 252 /// other than [ClassLevel.Body]. Members in an external library have no |
| 260 /// body, but have their typed interface present. | 253 /// body, but have their typed interface present. |
| 261 /// | 254 /// |
| 262 /// If the libary is non-external, then its classes are at [ClassLevel.Body] | 255 /// If the libary is non-external, then its classes are at [ClassLevel.Body] |
| 263 /// and all members are loaded. | 256 /// and all members are loaded. |
| 264 bool isExternal; | 257 bool isExternal; |
| 265 | 258 |
| 266 String name; | 259 String name; |
| 267 final List<DeferredImport> deferredImports; | 260 final List<DeferredImport> deferredImports; |
| 268 final List<Typedef> typedefs; | |
| 269 final List<Class> classes; | 261 final List<Class> classes; |
| 270 final List<Procedure> procedures; | 262 final List<Procedure> procedures; |
| 271 final List<Field> fields; | 263 final List<Field> fields; |
| 272 | 264 |
| 273 Library(this.importUri, | 265 Library(this.importUri, |
| 274 {this.name, | 266 {this.name, |
| 275 this.isExternal: false, | 267 this.isExternal: false, |
| 276 List<DeferredImport> imports, | 268 List<DeferredImport> imports, |
| 277 List<Typedef> typedefs, | |
| 278 List<Class> classes, | 269 List<Class> classes, |
| 279 List<Procedure> procedures, | 270 List<Procedure> procedures, |
| 280 List<Field> fields, | 271 List<Field> fields, |
| 281 this.fileUri, | 272 this.fileUri, |
| 282 Reference reference}) | 273 Reference reference}) |
| 283 : this.deferredImports = imports ?? <DeferredImport>[], | 274 : this.deferredImports = imports ?? <DeferredImport>[], |
| 284 this.typedefs = typedefs ?? <Typedef>[], | |
| 285 this.classes = classes ?? <Class>[], | 275 this.classes = classes ?? <Class>[], |
| 286 this.procedures = procedures ?? <Procedure>[], | 276 this.procedures = procedures ?? <Procedure>[], |
| 287 this.fields = fields ?? <Field>[], | 277 this.fields = fields ?? <Field>[], |
| 288 super(reference) { | 278 super(reference) { |
| 289 setParents(this.deferredImports, this); | |
| 290 setParents(this.typedefs, this); | |
| 291 setParents(this.classes, this); | 279 setParents(this.classes, this); |
| 292 setParents(this.procedures, this); | 280 setParents(this.procedures, this); |
| 293 setParents(this.fields, this); | 281 setParents(this.fields, this); |
| 294 } | 282 } |
| 295 | 283 |
| 296 /// Returns the top-level fields and procedures defined in this library. | 284 /// Returns the top-level fields and procedures defined in this library. |
| 297 /// | 285 /// |
| 298 /// This getter is for convenience, not efficiency. Consider manually | 286 /// This getter is for convenience, not efficiency. Consider manually |
| 299 /// iterating the members to speed up code in production. | 287 /// iterating the members to speed up code in production. |
| 300 Iterable<Member> get members => | 288 Iterable<Member> get members => |
| 301 <Iterable<Member>>[fields, procedures].expand((x) => x); | 289 <Iterable<Member>>[fields, procedures].expand((x) => x); |
| 302 | 290 |
| 303 void addMember(Member member) { | 291 void addMember(Member member) { |
| 304 member.parent = this; | 292 member.parent = this; |
| 305 if (member is Procedure) { | 293 if (member is Procedure) { |
| 306 procedures.add(member); | 294 procedures.add(member); |
| 307 } else if (member is Field) { | 295 } else if (member is Field) { |
| 308 fields.add(member); | 296 fields.add(member); |
| 309 } else { | 297 } else { |
| 310 throw new ArgumentError(member); | 298 throw new ArgumentError(member); |
| 311 } | 299 } |
| 312 } | 300 } |
| 313 | 301 |
| 314 void addClass(Class class_) { | 302 void addClass(Class class_) { |
| 315 class_.parent = this; | 303 class_.parent = this; |
| 316 classes.add(class_); | 304 classes.add(class_); |
| 317 } | 305 } |
| 318 | 306 |
| 319 void addTypedef(Typedef typedef_) { | |
| 320 typedef_.parent = this; | |
| 321 typedefs.add(typedef_); | |
| 322 } | |
| 323 | |
| 324 void computeCanonicalNames() { | 307 void computeCanonicalNames() { |
| 325 assert(canonicalName != null); | 308 assert(canonicalName != null); |
| 326 for (var typedef_ in typedefs) { | |
| 327 canonicalName.getChildFromTypedef(typedef_).bindTo(typedef_.reference); | |
| 328 } | |
| 329 for (var field in fields) { | 309 for (var field in fields) { |
| 330 canonicalName.getChildFromMember(field).bindTo(field.reference); | 310 canonicalName.getChildFromMember(field).bindTo(field.reference); |
| 331 } | 311 } |
| 332 for (var member in procedures) { | 312 for (var member in procedures) { |
| 333 canonicalName.getChildFromMember(member).bindTo(member.reference); | 313 canonicalName.getChildFromMember(member).bindTo(member.reference); |
| 334 } | 314 } |
| 335 for (var class_ in classes) { | 315 for (var class_ in classes) { |
| 336 canonicalName.getChild(class_.name).bindTo(class_.reference); | 316 canonicalName.getChild(class_.name).bindTo(class_.reference); |
| 337 class_.computeCanonicalNames(); | 317 class_.computeCanonicalNames(); |
| 338 } | 318 } |
| 339 } | 319 } |
| 340 | 320 |
| 341 accept(TreeVisitor v) => v.visitLibrary(this); | 321 accept(TreeVisitor v) => v.visitLibrary(this); |
| 342 | 322 |
| 343 visitChildren(Visitor v) { | 323 visitChildren(Visitor v) { |
| 344 visitList(deferredImports, v); | |
| 345 visitList(typedefs, v); | |
| 346 visitList(classes, v); | 324 visitList(classes, v); |
| 347 visitList(procedures, v); | 325 visitList(procedures, v); |
| 348 visitList(fields, v); | 326 visitList(fields, v); |
| 349 } | 327 } |
| 350 | 328 |
| 351 transformChildren(Transformer v) { | 329 transformChildren(Transformer v) { |
| 352 transformList(deferredImports, v, this); | |
| 353 transformList(typedefs, v, this); | |
| 354 transformList(classes, v, this); | 330 transformList(classes, v, this); |
| 355 transformList(procedures, v, this); | 331 transformList(procedures, v, this); |
| 356 transformList(fields, v, this); | 332 transformList(fields, v, this); |
| 357 } | 333 } |
| 358 | 334 |
| 359 static int _libraryIdCounter = 0; | 335 static int _libraryIdCounter = 0; |
| 360 int _libraryId = ++_libraryIdCounter; | 336 int _libraryId = ++_libraryIdCounter; |
| 361 | 337 |
| 362 int compareTo(Library other) => _libraryId - other._libraryId; | 338 int compareTo(Library other) => _libraryId - other._libraryId; |
| 363 | 339 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 383 Library get enclosingLibrary => parent; | 359 Library get enclosingLibrary => parent; |
| 384 Library get importedLibrary => importedLibraryReference.asLibrary; | 360 Library get importedLibrary => importedLibraryReference.asLibrary; |
| 385 | 361 |
| 386 accept(TreeVisitor v) => v.visitDeferredImport(this); | 362 accept(TreeVisitor v) => v.visitDeferredImport(this); |
| 387 | 363 |
| 388 visitChildren(Visitor v) {} | 364 visitChildren(Visitor v) {} |
| 389 | 365 |
| 390 transformChildren(Transformer v) {} | 366 transformChildren(Transformer v) {} |
| 391 } | 367 } |
| 392 | 368 |
| 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 | |
| 438 /// The degree to which the contents of a class have been loaded into memory. | 369 /// The degree to which the contents of a class have been loaded into memory. |
| 439 /// | 370 /// |
| 440 /// Each level imply the requirements of the previous ones. | 371 /// Each level imply the requirements of the previous ones. |
| 441 enum ClassLevel { | 372 enum ClassLevel { |
| 442 /// Temporary loading level for internal use by IR producers. Consumers of | 373 /// Temporary loading level for internal use by IR producers. Consumers of |
| 443 /// kernel code should not expect to see classes at this level. | 374 /// kernel code should not expect to see classes at this level. |
| 444 Temporary, | 375 Temporary, |
| 445 | 376 |
| 446 /// The class may be used as a type, and it may contain members that are | 377 /// The class may be used as a type, and it may contain members that are |
| 447 /// referenced from this build unit. | 378 /// referenced from this build unit. |
| (...skipping 3309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3757 /// cyclic structures that are constructed by mutation. | 3688 /// cyclic structures that are constructed by mutation. |
| 3758 /// | 3689 /// |
| 3759 /// The `==` operator on [DartType]s compare based on type equality, not | 3690 /// The `==` operator on [DartType]s compare based on type equality, not |
| 3760 /// object identity. | 3691 /// object identity. |
| 3761 abstract class DartType extends Node { | 3692 abstract class DartType extends Node { |
| 3762 const DartType(); | 3693 const DartType(); |
| 3763 | 3694 |
| 3764 accept(DartTypeVisitor v); | 3695 accept(DartTypeVisitor v); |
| 3765 | 3696 |
| 3766 bool operator ==(Object other); | 3697 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; | |
| 3777 } | 3698 } |
| 3778 | 3699 |
| 3779 /// The type arising from invalid type annotations. | 3700 /// The type arising from invalid type annotations. |
| 3780 /// | 3701 /// |
| 3781 /// Can usually be treated as 'dynamic', but should occasionally be handled | 3702 /// Can usually be treated as 'dynamic', but should occasionally be handled |
| 3782 /// differently, e.g. `x is ERROR` should evaluate to false. | 3703 /// differently, e.g. `x is ERROR` should evaluate to false. |
| 3783 class InvalidType extends DartType { | 3704 class InvalidType extends DartType { |
| 3784 final int hashCode = 12345; | 3705 final int hashCode = 12345; |
| 3785 | 3706 |
| 3786 const InvalidType(); | 3707 const InvalidType(); |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3996 } | 3917 } |
| 3997 hash = 0x3fffffff & (hash * 31 + returnType.hashCode); | 3918 hash = 0x3fffffff & (hash * 31 + returnType.hashCode); |
| 3998 for (int i = 0; i < typeParameters.length; ++i) { | 3919 for (int i = 0; i < typeParameters.length; ++i) { |
| 3999 // Remove the type parameters from the scope again. | 3920 // Remove the type parameters from the scope again. |
| 4000 _temporaryHashCodeTable.remove(typeParameters[i]); | 3921 _temporaryHashCodeTable.remove(typeParameters[i]); |
| 4001 } | 3922 } |
| 4002 return hash; | 3923 return hash; |
| 4003 } | 3924 } |
| 4004 } | 3925 } |
| 4005 | 3926 |
| 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 | |
| 4060 /// A named parameter in [FunctionType]. | 3927 /// A named parameter in [FunctionType]. |
| 4061 class NamedType extends Node implements Comparable<NamedType> { | 3928 class NamedType extends Node implements Comparable<NamedType> { |
| 4062 final String name; | 3929 final String name; |
| 4063 final DartType type; | 3930 final DartType type; |
| 4064 | 3931 |
| 4065 NamedType(this.name, this.type); | 3932 NamedType(this.name, this.type); |
| 4066 | 3933 |
| 4067 bool operator ==(Object other) { | 3934 bool operator ==(Object other) { |
| 4068 return other is NamedType && name == other.name && type == other.type; | 3935 return other is NamedType && name == other.name && type == other.type; |
| 4069 } | 3936 } |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4449 /// library has not been assigned a canonical name yet. | 4316 /// library has not been assigned a canonical name yet. |
| 4450 /// | 4317 /// |
| 4451 /// Returns `null` if the library is `null`. | 4318 /// Returns `null` if the library is `null`. |
| 4452 CanonicalName getCanonicalNameOfLibrary(Library library) { | 4319 CanonicalName getCanonicalNameOfLibrary(Library library) { |
| 4453 if (library == null) return null; | 4320 if (library == null) return null; |
| 4454 if (library.canonicalName == null) { | 4321 if (library.canonicalName == null) { |
| 4455 throw '$library has no canonical name'; | 4322 throw '$library has no canonical name'; |
| 4456 } | 4323 } |
| 4457 return library.canonicalName; | 4324 return library.canonicalName; |
| 4458 } | 4325 } |
| 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 |