Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/kernel_target.dart

Issue 2775633004: Report errors on non-final fields in const classes. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/co19/co19-kernel.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | tests/co19/co19-kernel.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698