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 library fasta.kernel_target; | 5 library fasta.kernel_target; |
6 | 6 |
7 import 'dart:async' show Future; | 7 import 'dart:async' show Future; |
8 | 8 |
9 import 'dart:io' show File, IOSink; | 9 import 'dart:io' show File, IOSink; |
10 | 10 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 | 107 |
108 KernelTarget(DillTarget dillTarget, TranslateUri uriTranslator, | 108 KernelTarget(DillTarget dillTarget, TranslateUri uriTranslator, |
109 [Map<String, Source> uriToSource]) | 109 [Map<String, Source> uriToSource]) |
110 : dillTarget = dillTarget, | 110 : dillTarget = dillTarget, |
111 uriToSource = uriToSource ?? CompilerContext.current.uriToSource, | 111 uriToSource = uriToSource ?? CompilerContext.current.uriToSource, |
112 super(dillTarget.ticker, uriTranslator) { | 112 super(dillTarget.ticker, uriTranslator) { |
113 resetCrashReporting(); | 113 resetCrashReporting(); |
114 loader = createLoader(); | 114 loader = createLoader(); |
115 } | 115 } |
116 | 116 |
| 117 void addError(file, int charOffset, String message) { |
| 118 Uri uri = file is String ? Uri.parse(file) : file; |
| 119 InputError error = new InputError(uri, charOffset, message); |
| 120 print(error.format()); |
| 121 errors.add(error); |
| 122 } |
| 123 |
117 SourceLoader<Library> createLoader() => new SourceLoader<Library>(this); | 124 SourceLoader<Library> createLoader() => new SourceLoader<Library>(this); |
118 | 125 |
119 void addSourceInformation( | 126 void addSourceInformation( |
120 Uri uri, List<int> lineStarts, List<int> sourceCode) { | 127 Uri uri, List<int> lineStarts, List<int> sourceCode) { |
121 String fileUri = relativizeUri(uri); | 128 String fileUri = relativizeUri(uri); |
122 uriToSource[fileUri] = new Source(lineStarts, sourceCode); | 129 uriToSource[fileUri] = new Source(lineStarts, sourceCode); |
123 } | 130 } |
124 | 131 |
125 void read(Uri uri) { | 132 void read(Uri uri) { |
126 loader.read(uri); | 133 loader.read(uri); |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 ticker.logMs("Finished constructors"); | 551 ticker.logMs("Finished constructors"); |
545 } | 552 } |
546 | 553 |
547 /// Ensure constructors of [cls] have the correct initializers and other | 554 /// Ensure constructors of [cls] have the correct initializers and other |
548 /// requirements. | 555 /// requirements. |
549 void finishConstructors(Class cls) { | 556 void finishConstructors(Class cls) { |
550 /// Quotes below are from [Dart Programming Language Specification, 4th | 557 /// Quotes below are from [Dart Programming Language Specification, 4th |
551 /// Edition](http://www.ecma-international.org/publications/files/ECMA-ST/EC
MA-408.pdf): | 558 /// Edition](http://www.ecma-international.org/publications/files/ECMA-ST/EC
MA-408.pdf): |
552 Constructor superTarget; | 559 Constructor superTarget; |
553 List<Field> uninitializedFields = <Field>[]; | 560 List<Field> uninitializedFields = <Field>[]; |
| 561 List<Field> nonFinalFields = <Field>[]; |
554 for (Field field in cls.fields) { | 562 for (Field field in cls.fields) { |
| 563 if (field.isInstanceMember && !field.isFinal) { |
| 564 nonFinalFields.add(field); |
| 565 } |
555 if (field.initializer == null) { | 566 if (field.initializer == null) { |
556 uninitializedFields.add(field); | 567 uninitializedFields.add(field); |
557 } | 568 } |
558 } | 569 } |
559 Map<Constructor, List<FieldInitializer>> fieldInitializers = | 570 Map<Constructor, List<FieldInitializer>> fieldInitializers = |
560 <Constructor, List<FieldInitializer>>{}; | 571 <Constructor, List<FieldInitializer>>{}; |
561 for (Constructor constructor in cls.constructors) { | 572 for (Constructor constructor in cls.constructors) { |
562 if (!isRedirectingGenerativeConstructor(constructor)) { | 573 if (!isRedirectingGenerativeConstructor(constructor)) { |
563 /// >If no superinitializer is provided, an implicit superinitializer | 574 /// >If no superinitializer is provided, an implicit superinitializer |
564 /// >of the form super() is added at the end of k’s initializer list, | 575 /// >of the form super() is added at the end of k’s initializer list, |
565 /// >unless the enclosing class is class Object. | 576 /// >unless the enclosing class is class Object. |
566 if (!constructor.initializers.any(isSuperinitializerOrInvalid)) { | 577 if (!constructor.initializers.any(isSuperinitializerOrInvalid)) { |
567 superTarget ??= defaultSuperConstructor(cls); | 578 superTarget ??= defaultSuperConstructor(cls); |
568 Initializer initializer; | 579 Initializer initializer; |
569 if (superTarget == null) { | 580 if (superTarget == null) { |
570 Uri uri = constructor.enclosingClass.fileUri == null | 581 addError( |
571 ? null | 582 constructor.enclosingClass.fileUri, |
572 : Uri.parse(constructor.enclosingClass.fileUri); | |
573 InputError error = new InputError( | |
574 uri, | |
575 constructor.fileOffset, | 583 constructor.fileOffset, |
576 "${cls.superclass.name} has no constructor that takes zero" | 584 "${cls.superclass.name} has no constructor that takes zero" |
577 " arguments."); | 585 " arguments."); |
578 print(error.format()); | |
579 errors.add(error); | |
580 initializer = new InvalidInitializer(); | 586 initializer = new InvalidInitializer(); |
581 } else { | 587 } else { |
582 initializer = | 588 initializer = |
583 new SuperInitializer(superTarget, new Arguments.empty()); | 589 new SuperInitializer(superTarget, new Arguments.empty()); |
584 } | 590 } |
585 constructor.initializers.add(initializer); | 591 constructor.initializers.add(initializer); |
586 initializer.parent = constructor; | 592 initializer.parent = constructor; |
587 } | 593 } |
588 if (constructor.function.body == null) { | 594 if (constructor.function.body == null) { |
589 /// >If a generative constructor c is not a redirecting constructor | 595 /// >If a generative constructor c is not a redirecting constructor |
590 /// >and no body is provided, then c implicitly has an empty body {}. | 596 /// >and no body is provided, then c implicitly has an empty body {}. |
591 /// We use an empty statement instead. | 597 /// We use an empty statement instead. |
592 constructor.function.body = new EmptyStatement(); | 598 constructor.function.body = new EmptyStatement(); |
593 constructor.function.body.parent = constructor.function; | 599 constructor.function.body.parent = constructor.function; |
594 } | 600 } |
595 List<FieldInitializer> myFieldInitializers = <FieldInitializer>[]; | 601 List<FieldInitializer> myFieldInitializers = <FieldInitializer>[]; |
596 for (Initializer initializer in constructor.initializers) { | 602 for (Initializer initializer in constructor.initializers) { |
597 if (initializer is FieldInitializer) { | 603 if (initializer is FieldInitializer) { |
598 myFieldInitializers.add(initializer); | 604 myFieldInitializers.add(initializer); |
599 } | 605 } |
600 } | 606 } |
601 fieldInitializers[constructor] = myFieldInitializers; | 607 fieldInitializers[constructor] = myFieldInitializers; |
| 608 if (constructor.isConst && nonFinalFields.isNotEmpty) { |
| 609 addError(constructor.enclosingClass.fileUri, constructor.fileOffset, |
| 610 "Constructor is marked 'const' so all fields must be final."); |
| 611 for (Field field in nonFinalFields) { |
| 612 addError(constructor.enclosingClass.fileUri, field.fileOffset, |
| 613 "Field isn't final, but constructor is 'const'."); |
| 614 } |
| 615 nonFinalFields.clear(); |
| 616 } |
602 } | 617 } |
603 } | 618 } |
604 Set<Field> initializedFields; | 619 Set<Field> initializedFields; |
605 fieldInitializers.forEach( | 620 fieldInitializers.forEach( |
606 (Constructor constructor, List<FieldInitializer> initializers) { | 621 (Constructor constructor, List<FieldInitializer> initializers) { |
607 Iterable<Field> fields = initializers.map((i) => i.field); | 622 Iterable<Field> fields = initializers.map((i) => i.field); |
608 if (initializedFields == null) { | 623 if (initializedFields == null) { |
609 initializedFields = new Set<Field>.from(fields); | 624 initializedFields = new Set<Field>.from(fields); |
610 } else { | 625 } else { |
611 initializedFields.addAll(fields); | 626 initializedFields.addAll(fields); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 } | 699 } |
685 for (Constructor constructor in superclass.constructors) { | 700 for (Constructor constructor in superclass.constructors) { |
686 if (constructor.name.name.isEmpty) { | 701 if (constructor.name.name.isEmpty) { |
687 return constructor.function.requiredParameterCount == 0 | 702 return constructor.function.requiredParameterCount == 0 |
688 ? constructor | 703 ? constructor |
689 : null; | 704 : null; |
690 } | 705 } |
691 } | 706 } |
692 return null; | 707 return null; |
693 } | 708 } |
OLD | NEW |