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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 /// | 257 /// |
258 /// 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 |
259 /// other than [ClassLevel.Body]. Members in an external library have no | 259 /// other than [ClassLevel.Body]. Members in an external library have no |
260 /// body, but have their typed interface present. | 260 /// body, but have their typed interface present. |
261 /// | 261 /// |
262 /// 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] |
263 /// and all members are loaded. | 263 /// and all members are loaded. |
264 bool isExternal; | 264 bool isExternal; |
265 | 265 |
266 String name; | 266 String name; |
267 final List<DeferredImport> deferredImports; | 267 final List<LibraryDependency> dependencies; |
268 final List<Typedef> typedefs; | 268 final List<Typedef> typedefs; |
269 final List<Class> classes; | 269 final List<Class> classes; |
270 final List<Procedure> procedures; | 270 final List<Procedure> procedures; |
271 final List<Field> fields; | 271 final List<Field> fields; |
272 | 272 |
273 Library(this.importUri, | 273 Library(this.importUri, |
274 {this.name, | 274 {this.name, |
275 this.isExternal: false, | 275 this.isExternal: false, |
276 List<DeferredImport> imports, | 276 List<LibraryDependency> dependencies, |
277 List<Typedef> typedefs, | 277 List<Typedef> typedefs, |
278 List<Class> classes, | 278 List<Class> classes, |
279 List<Procedure> procedures, | 279 List<Procedure> procedures, |
280 List<Field> fields, | 280 List<Field> fields, |
281 this.fileUri, | 281 this.fileUri, |
282 Reference reference}) | 282 Reference reference}) |
283 : this.deferredImports = imports ?? <DeferredImport>[], | 283 : this.dependencies = dependencies ?? <LibraryDependency>[], |
284 this.typedefs = typedefs ?? <Typedef>[], | 284 this.typedefs = typedefs ?? <Typedef>[], |
285 this.classes = classes ?? <Class>[], | 285 this.classes = classes ?? <Class>[], |
286 this.procedures = procedures ?? <Procedure>[], | 286 this.procedures = procedures ?? <Procedure>[], |
287 this.fields = fields ?? <Field>[], | 287 this.fields = fields ?? <Field>[], |
288 super(reference) { | 288 super(reference) { |
289 setParents(this.deferredImports, this); | 289 setParents(this.dependencies, this); |
290 setParents(this.typedefs, this); | 290 setParents(this.typedefs, this); |
291 setParents(this.classes, this); | 291 setParents(this.classes, this); |
292 setParents(this.procedures, this); | 292 setParents(this.procedures, this); |
293 setParents(this.fields, this); | 293 setParents(this.fields, this); |
294 } | 294 } |
295 | 295 |
296 /// Returns the top-level fields and procedures defined in this library. | 296 /// Returns the top-level fields and procedures defined in this library. |
297 /// | 297 /// |
298 /// This getter is for convenience, not efficiency. Consider manually | 298 /// This getter is for convenience, not efficiency. Consider manually |
299 /// iterating the members to speed up code in production. | 299 /// iterating the members to speed up code in production. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 } | 331 } |
332 for (var member in procedures) { | 332 for (var member in procedures) { |
333 canonicalName.getChildFromMember(member).bindTo(member.reference); | 333 canonicalName.getChildFromMember(member).bindTo(member.reference); |
334 } | 334 } |
335 for (var class_ in classes) { | 335 for (var class_ in classes) { |
336 canonicalName.getChild(class_.name).bindTo(class_.reference); | 336 canonicalName.getChild(class_.name).bindTo(class_.reference); |
337 class_.computeCanonicalNames(); | 337 class_.computeCanonicalNames(); |
338 } | 338 } |
339 } | 339 } |
340 | 340 |
| 341 void addDependency(LibraryDependency node) { |
| 342 dependencies.add(node..parent = this); |
| 343 } |
| 344 |
341 accept(TreeVisitor v) => v.visitLibrary(this); | 345 accept(TreeVisitor v) => v.visitLibrary(this); |
342 | 346 |
343 visitChildren(Visitor v) { | 347 visitChildren(Visitor v) { |
344 visitList(deferredImports, v); | 348 visitList(dependencies, v); |
345 visitList(typedefs, v); | 349 visitList(typedefs, v); |
346 visitList(classes, v); | 350 visitList(classes, v); |
347 visitList(procedures, v); | 351 visitList(procedures, v); |
348 visitList(fields, v); | 352 visitList(fields, v); |
349 } | 353 } |
350 | 354 |
351 transformChildren(Transformer v) { | 355 transformChildren(Transformer v) { |
352 transformList(deferredImports, v, this); | 356 transformList(dependencies, v, this); |
353 transformList(typedefs, v, this); | 357 transformList(typedefs, v, this); |
354 transformList(classes, v, this); | 358 transformList(classes, v, this); |
355 transformList(procedures, v, this); | 359 transformList(procedures, v, this); |
356 transformList(fields, v, this); | 360 transformList(fields, v, this); |
357 } | 361 } |
358 | 362 |
359 static int _libraryIdCounter = 0; | 363 static int _libraryIdCounter = 0; |
360 int _libraryId = ++_libraryIdCounter; | 364 int _libraryId = ++_libraryIdCounter; |
361 | 365 |
362 int compareTo(Library other) => _libraryId - other._libraryId; | 366 int compareTo(Library other) => _libraryId - other._libraryId; |
363 | 367 |
364 /// Returns a possibly synthesized name for this library, consistent with | 368 /// Returns a possibly synthesized name for this library, consistent with |
365 /// the names across all [toString] calls. | 369 /// the names across all [toString] calls. |
366 String toString() => debugLibraryName(this); | 370 String toString() => debugLibraryName(this); |
367 | 371 |
368 Location _getLocationInEnclosingFile(int offset) { | 372 Location _getLocationInEnclosingFile(int offset) { |
369 return enclosingProgram.getLocation(fileUri, offset); | 373 return enclosingProgram.getLocation(fileUri, offset); |
370 } | 374 } |
371 } | 375 } |
372 | 376 |
373 /// An import of form: `import <url> deferred as <name>;`. | 377 /// An import or export declaration in a library. |
374 class DeferredImport extends TreeNode { | 378 /// |
| 379 /// It can represent any of the following forms, |
| 380 /// |
| 381 /// import <url>; |
| 382 /// import <url> as <name>; |
| 383 /// import <url> deferred as <name>; |
| 384 /// export <url>; |
| 385 /// |
| 386 /// optionally with metadata and [Combinators]. |
| 387 class LibraryDependency extends TreeNode { |
| 388 int flags; |
| 389 |
| 390 final List<Expression> annotations; |
| 391 |
375 Reference importedLibraryReference; | 392 Reference importedLibraryReference; |
| 393 |
| 394 /// The name of the import prefix, if any, or `null` if this is not an import |
| 395 /// with a prefix. |
| 396 /// |
| 397 /// Must be non-null for deferred imports, and must be null for exports. |
376 String name; | 398 String name; |
377 | 399 |
378 DeferredImport(Library importedLibrary, String name) | 400 final List<Combinator> combinators; |
379 : this.byReference(importedLibrary.reference, name); | |
380 | 401 |
381 DeferredImport.byReference(this.importedLibraryReference, this.name); | 402 LibraryDependency(int flags, List<Expression> annotations, |
| 403 Library importedLibrary, String name, List<Combinator> combinators) |
| 404 : this.byReference( |
| 405 flags, annotations, importedLibrary.reference, name, combinators); |
| 406 |
| 407 LibraryDependency.deferredImport(Library importedLibrary, String name, |
| 408 {List<Combinator> combinators, List<Expression> annotations}) |
| 409 : this.byReference(DeferredFlag, annotations ?? <Expression>[], |
| 410 importedLibrary.reference, name, combinators ?? <Combinator>[]); |
| 411 |
| 412 LibraryDependency.import(Library importedLibrary, |
| 413 {String name, List<Combinator> combinators, List<Expression> annotations}) |
| 414 : this.byReference(0, annotations ?? <Expression>[], |
| 415 importedLibrary.reference, name, combinators ?? <Combinator>[]); |
| 416 |
| 417 LibraryDependency.export(Library importedLibrary, |
| 418 {List<Combinator> combinators, List<Expression> annotations}) |
| 419 : this.byReference(ExportFlag, annotations ?? <Expression>[], |
| 420 importedLibrary.reference, null, combinators ?? <Combinator>[]); |
| 421 |
| 422 LibraryDependency.byReference(this.flags, this.annotations, |
| 423 this.importedLibraryReference, this.name, this.combinators) { |
| 424 setParents(annotations, this); |
| 425 setParents(combinators, this); |
| 426 } |
382 | 427 |
383 Library get enclosingLibrary => parent; | 428 Library get enclosingLibrary => parent; |
384 Library get importedLibrary => importedLibraryReference.asLibrary; | 429 Library get targetLibrary => importedLibraryReference.asLibrary; |
385 | 430 |
386 accept(TreeVisitor v) => v.visitDeferredImport(this); | 431 static const int ExportFlag = 1 << 0; |
| 432 static const int DeferredFlag = 1 << 1; |
387 | 433 |
| 434 bool get isExport => flags & ExportFlag != 0; |
| 435 bool get isImport => !isExport; |
| 436 bool get isDeferred => flags & DeferredFlag != 0; |
| 437 |
| 438 void addAnnotation(Expression annotation) { |
| 439 annotations.add(annotation..parent = this); |
| 440 } |
| 441 |
| 442 accept(TreeVisitor v) => v.visitLibraryDependency(this); |
| 443 |
| 444 visitChildren(Visitor v) { |
| 445 visitList(annotations, v); |
| 446 visitList(combinators, v); |
| 447 } |
| 448 |
| 449 transformChildren(Transformer v) { |
| 450 transformList(annotations, v, this); |
| 451 transformList(combinators, v, this); |
| 452 } |
| 453 } |
| 454 |
| 455 /// A `show` or `hide` clause for an import or export. |
| 456 class Combinator extends TreeNode { |
| 457 bool isShow; |
| 458 final List<String> names; |
| 459 |
| 460 LibraryDependency get dependency => parent; |
| 461 |
| 462 Combinator(this.isShow, this.names); |
| 463 Combinator.show(this.names) : isShow = true; |
| 464 Combinator.hide(this.names) : isShow = false; |
| 465 |
| 466 bool get isHide => !isShow; |
| 467 |
| 468 @override |
| 469 accept(TreeVisitor v) => v.visitCombinator(this); |
| 470 |
| 471 @override |
388 visitChildren(Visitor v) {} | 472 visitChildren(Visitor v) {} |
389 | 473 |
| 474 @override |
390 transformChildren(Transformer v) {} | 475 transformChildren(Transformer v) {} |
391 } | 476 } |
392 | 477 |
393 /// Declaration of a type alias. | 478 /// Declaration of a type alias. |
394 class Typedef extends NamedNode { | 479 class Typedef extends NamedNode { |
395 /// The uri of the source file that contains the declaration of this typedef. | 480 /// The uri of the source file that contains the declaration of this typedef. |
396 String fileUri; | 481 String fileUri; |
397 List<Expression> annotations = const <Expression>[]; | 482 List<Expression> annotations = const <Expression>[]; |
398 String name; | 483 String name; |
399 final List<TypeParameter> typeParameters; | 484 final List<TypeParameter> typeParameters; |
(...skipping 2386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2786 /// - keeping track of whether the library code has already been downloaded | 2871 /// - keeping track of whether the library code has already been downloaded |
2787 /// - actually downloading and linking the library | 2872 /// - actually downloading and linking the library |
2788 /// | 2873 /// |
2789 /// Should return a future. The value in this future will be the same value | 2874 /// Should return a future. The value in this future will be the same value |
2790 /// seen by callers of `loadLibrary` functions. | 2875 /// seen by callers of `loadLibrary` functions. |
2791 /// | 2876 /// |
2792 /// On backends that link the entire program eagerly, this instruction needs | 2877 /// On backends that link the entire program eagerly, this instruction needs |
2793 /// to mark the deferred import as 'loaded' and return a future. | 2878 /// to mark the deferred import as 'loaded' and return a future. |
2794 class LoadLibrary extends Expression { | 2879 class LoadLibrary extends Expression { |
2795 /// Reference to a deferred import in the enclosing library. | 2880 /// Reference to a deferred import in the enclosing library. |
2796 DeferredImport import; | 2881 LibraryDependency import; |
2797 | 2882 |
2798 LoadLibrary(this.import); | 2883 LoadLibrary(this.import); |
2799 | 2884 |
2800 DartType getStaticType(TypeEnvironment types) { | 2885 DartType getStaticType(TypeEnvironment types) { |
2801 return types.futureType(const DynamicType()); | 2886 return types.futureType(const DynamicType()); |
2802 } | 2887 } |
2803 | 2888 |
2804 accept(ExpressionVisitor v) => v.visitLoadLibrary(this); | 2889 accept(ExpressionVisitor v) => v.visitLoadLibrary(this); |
2805 accept1(ExpressionVisitor1 v, arg) => v.visitLoadLibrary(this, arg); | 2890 accept1(ExpressionVisitor1 v, arg) => v.visitLoadLibrary(this, arg); |
2806 | 2891 |
2807 visitChildren(Visitor v) {} | 2892 visitChildren(Visitor v) {} |
2808 transformChildren(Transformer v) {} | 2893 transformChildren(Transformer v) {} |
2809 } | 2894 } |
2810 | 2895 |
2811 /// Checks that the given deferred import has been marked as 'loaded'. | 2896 /// Checks that the given deferred import has been marked as 'loaded'. |
2812 class CheckLibraryIsLoaded extends Expression { | 2897 class CheckLibraryIsLoaded extends Expression { |
2813 /// Reference to a deferred import in the enclosing library. | 2898 /// Reference to a deferred import in the enclosing library. |
2814 DeferredImport import; | 2899 LibraryDependency import; |
2815 | 2900 |
2816 CheckLibraryIsLoaded(this.import); | 2901 CheckLibraryIsLoaded(this.import); |
2817 | 2902 |
2818 DartType getStaticType(TypeEnvironment types) { | 2903 DartType getStaticType(TypeEnvironment types) { |
2819 return types.objectType; | 2904 return types.objectType; |
2820 } | 2905 } |
2821 | 2906 |
2822 accept(ExpressionVisitor v) => v.visitCheckLibraryIsLoaded(this); | 2907 accept(ExpressionVisitor v) => v.visitCheckLibraryIsLoaded(this); |
2823 accept1(ExpressionVisitor1 v, arg) => v.visitCheckLibraryIsLoaded(this, arg); | 2908 accept1(ExpressionVisitor1 v, arg) => v.visitCheckLibraryIsLoaded(this, arg); |
2824 | 2909 |
(...skipping 1686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4511 /// typedef has not been assigned a canonical name yet. | 4596 /// typedef has not been assigned a canonical name yet. |
4512 /// | 4597 /// |
4513 /// Returns `null` if the typedef is `null`. | 4598 /// Returns `null` if the typedef is `null`. |
4514 CanonicalName getCanonicalNameOfTypedef(Typedef typedef_) { | 4599 CanonicalName getCanonicalNameOfTypedef(Typedef typedef_) { |
4515 if (typedef_ == null) return null; | 4600 if (typedef_ == null) return null; |
4516 if (typedef_.canonicalName == null) { | 4601 if (typedef_.canonicalName == null) { |
4517 throw '$typedef_ has no canonical name'; | 4602 throw '$typedef_ has no canonical name'; |
4518 } | 4603 } |
4519 return typedef_.canonicalName; | 4604 return typedef_.canonicalName; |
4520 } | 4605 } |
OLD | NEW |