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

Side by Side Diff: pkg/kernel/lib/analyzer/loader.dart

Issue 2669303002: Support for modular mixin resolution. (Closed)
Patch Set: Fix a bug Created 3 years, 10 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 | « pkg/kernel/binary.md ('k') | pkg/kernel/lib/ast.dart » ('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 library kernel.analyzer.loader; 4 library kernel.analyzer.loader;
5 5
6 import 'dart:async'; 6 import 'dart:async';
7 import 'dart:io' as io; 7 import 'dart:io' as io;
8 8
9 import 'package:analyzer/analyzer.dart'; 9 import 'package:analyzer/analyzer.dart';
10 import 'package:analyzer/file_system/file_system.dart'; 10 import 'package:analyzer/file_system/file_system.dart';
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 <ast.Library, Map<String, ast.Class>>{}; 99 <ast.Library, Map<String, ast.Class>>{};
100 final AnalysisContext context; 100 final AnalysisContext context;
101 LibraryElement _dartCoreLibrary; 101 LibraryElement _dartCoreLibrary;
102 final List errors = []; 102 final List errors = [];
103 final List libraryElements = []; 103 final List libraryElements = [];
104 104
105 /// Classes that have been referenced, and must be promoted to type level 105 /// Classes that have been referenced, and must be promoted to type level
106 /// so as not to expose partially initialized classes. 106 /// so as not to expose partially initialized classes.
107 final List<ast.Class> temporaryClassWorklist = []; 107 final List<ast.Class> temporaryClassWorklist = [];
108 108
109 final Map<LibraryElement, List<ClassElement>> mixinLibraryWorklist = {};
110
109 final bool ignoreRedirectingFactories; 111 final bool ignoreRedirectingFactories;
110 112
111 LibraryElement _libraryBeingLoaded = null; 113 LibraryElement _libraryBeingLoaded = null;
112 114
113 bool get strongMode => context.analysisOptions.strongMode; 115 bool get strongMode => context.analysisOptions.strongMode;
114 116
115 DartLoader(this.repository, DartOptions options, Packages packages, 117 DartLoader(this.repository, DartOptions options, Packages packages,
116 {DartSdk dartSdk, AnalysisContext context, 118 {DartSdk dartSdk,
117 this.ignoreRedirectingFactories: true}) 119 AnalysisContext context,
120 this.ignoreRedirectingFactories: true})
118 : this.context = 121 : this.context =
119 context ?? createContext(options, packages, dartSdk: dartSdk), 122 context ?? createContext(options, packages, dartSdk: dartSdk),
120 this.applicationRoot = options.applicationRoot; 123 this.applicationRoot = options.applicationRoot;
121 124
122 String getLibraryName(LibraryElement element) { 125 String getLibraryName(LibraryElement element) {
123 return element.name.isEmpty ? null : element.name; 126 return element.name.isEmpty ? null : element.name;
124 } 127 }
125 128
126 ast.Library getLibraryReference(LibraryElement element) { 129 ast.Library getLibraryReference(LibraryElement element) {
127 var uri = applicationRoot.relativeUri(element.source.uri); 130 var uri = applicationRoot.relativeUri(element.source.uri);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 loadField(declaration); 195 loadField(declaration);
193 } else if (declaration is FunctionTypeAlias) { 196 } else if (declaration is FunctionTypeAlias) {
194 // Nothing to do. Typedefs are handled lazily while constructing type 197 // Nothing to do. Typedefs are handled lazily while constructing type
195 // references. 198 // references.
196 } else { 199 } else {
197 throw "unexpected node: ${declaration.runtimeType} $declaration"; 200 throw "unexpected node: ${declaration.runtimeType} $declaration";
198 } 201 }
199 } 202 }
200 } 203 }
201 libraryElements.add(element); 204 libraryElements.add(element);
202 _iterateWorklist(); 205 _iterateTemporaryClassWorklist();
203 // Ensure everything is stored in the original declaration order. 206 // Ensure everything is stored in the original declaration order.
204 library.classes 207 library.classes
205 ..clear() 208 ..clear()
206 ..addAll(classes) 209 ..addAll(classes)
207 ..addAll(_mixinApplications[library]?.values ?? const []); 210 ..addAll(_mixinApplications[library]?.values ?? const []);
208 library.fields 211 library.fields
209 ..clear() 212 ..clear()
210 ..addAll(fields); 213 ..addAll(fields);
211 library.procedures 214 library.procedures
212 ..clear() 215 ..clear()
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 if (!method.isStatic && !method.isSynthetic) { 384 if (!method.isStatic && !method.isSynthetic) {
382 getMemberReference(method); 385 getMemberReference(method);
383 } 386 }
384 } 387 }
385 } 388 }
386 for (var supertype in classNode.supers) { 389 for (var supertype in classNode.supers) {
387 promoteToHierarchyLevel(supertype.classNode); 390 promoteToHierarchyLevel(supertype.classNode);
388 } 391 }
389 } 392 }
390 393
394 void promoteToMixinLevel(ast.Class classNode, ClassElement element,
395 NamedCompilationUnitMember astNode) {
396 if (classNode.level.index >= ast.ClassLevel.Mixin.index) return;
397 promoteToHierarchyLevel(classNode);
398 classNode.level = ast.ClassLevel.Mixin;
399 // Clear out the member references that were put in the class.
400 // The AST builder will load them all put back in the right order.
401 classNode..fields.clear()..procedures.clear()..constructors.clear();
402 new ClassBodyBuilder(this, classNode, element).build(astNode);
403
404 // Ensure mixed-in classes are available.
405 for (var mixin in element.mixins) {
406 _ensureMixinBecomesLoaded(mixin.element);
407 }
408 }
409
410 /// Ensures that [element] eventually becomes loaded at least at mixin level.
411 void _ensureMixinBecomesLoaded(ClassElement element) {
412 if (isLibraryBeingLoaded(element.library)) {
413 return;
414 }
415 var class_ = getClassReference(element);
416 if (class_.level.index >= ast.ClassLevel.Mixin.index) {
417 return;
418 }
419 var list = mixinLibraryWorklist[element.library] ??= <ClassElement>[];
420 list.add(element);
421 }
422
391 void promoteToBodyLevel(ast.Class classNode, ClassElement element, 423 void promoteToBodyLevel(ast.Class classNode, ClassElement element,
392 NamedCompilationUnitMember astNode) { 424 NamedCompilationUnitMember astNode) {
393 if (classNode.level == ast.ClassLevel.Body) return; 425 if (classNode.level == ast.ClassLevel.Body) return;
394 promoteToHierarchyLevel(classNode); 426 promoteToMixinLevel(classNode, element, astNode);
395 classNode.level = ast.ClassLevel.Body; 427 classNode.level = ast.ClassLevel.Body;
396 // Clear out the member references that were put in the class. 428 // This frontend delivers the same contents for classes at body and mixin
397 // The AST builder will load them all put back in the right order. 429 // levels, even though as specified, the mixin level does not require all
398 classNode..fields.clear()..procedures.clear()..constructors.clear(); 430 // the static members to be present. So no additional work is needed.
399 new ClassBodyBuilder(this, classNode, element).build(astNode);
400 } 431 }
401 432
402 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element) { 433 ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element) {
403 return _classTypeParameters[element]; 434 return _classTypeParameters[element];
404 } 435 }
405 436
406 Element getMemberElement(ast.Member node) { 437 Element getMemberElement(ast.Member node) {
407 return _members.inverse[node]; 438 return _members.inverse[node];
408 } 439 }
409 440
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 641
611 String formatErrorMessage( 642 String formatErrorMessage(
612 AnalysisError error, String filename, LineInfo lines) { 643 AnalysisError error, String filename, LineInfo lines) {
613 var location = lines.getLocation(error.offset); 644 var location = lines.getLocation(error.offset);
614 return '[error] ${error.message} ($filename, ' 645 return '[error] ${error.message} ($filename, '
615 'line ${location.lineNumber}, ' 646 'line ${location.lineNumber}, '
616 'col ${location.columnNumber})'; 647 'col ${location.columnNumber})';
617 } 648 }
618 649
619 void ensureLibraryIsLoaded(ast.Library node) { 650 void ensureLibraryIsLoaded(ast.Library node) {
651 _ensureLibraryIsLoaded(node);
652 _iterateMixinLibraryWorklist();
653 }
654
655 void _ensureLibraryIsLoaded(ast.Library node) {
620 if (!node.isExternal) return; 656 if (!node.isExternal) return;
621 node.isExternal = false; 657 node.isExternal = false;
622 var source = context.sourceFactory 658 var source = context.sourceFactory
623 .forUri2(applicationRoot.absoluteUri(node.importUri)); 659 .forUri2(applicationRoot.absoluteUri(node.importUri));
624 assert(source != null); 660 assert(source != null);
625 var element = context.computeLibraryElement(source); 661 var element = context.computeLibraryElement(source);
626 var units = <CompilationUnit>[]; 662 var units = <CompilationUnit>[];
627 bool reportErrors = node.importUri.scheme != 'dart'; 663 bool reportErrors = node.importUri.scheme != 'dart';
628 var tree = context.resolveCompilationUnit(source, element); 664 var tree = context.resolveCompilationUnit(source, element);
629 units.add(tree); 665 units.add(tree);
(...skipping 12 matching lines...) Expand all
642 if (error.errorCode is CompileTimeErrorCode || 678 if (error.errorCode is CompileTimeErrorCode ||
643 error.errorCode is ParserErrorCode || 679 error.errorCode is ParserErrorCode ||
644 error.errorCode is ScannerErrorCode || 680 error.errorCode is ScannerErrorCode ||
645 error.errorCode is StrongModeCode) { 681 error.errorCode is StrongModeCode) {
646 lines ??= context.computeLineInfo(source); 682 lines ??= context.computeLineInfo(source);
647 errors.add(formatErrorMessage(error, source.shortName, lines)); 683 errors.add(formatErrorMessage(error, source.shortName, lines));
648 } 684 }
649 } 685 }
650 } 686 }
651 687
688 void loadSdkInterface(ast.Program program, Target target) {
689 var requiredSdkMembers = target.requiredSdkClasses;
690 for (var libraryUri in requiredSdkMembers.keys) {
691 var source = context.sourceFactory.forUri2(Uri.parse(libraryUri));
692 var libraryElement = context.computeLibraryElement(source);
693 for (var member in requiredSdkMembers[libraryUri]) {
694 var type = libraryElement.getType(member);
695 if (type == null) {
696 throw 'Could not find $member in $libraryUri';
697 }
698 promoteToTypeLevel(getClassReference(type));
699 }
700 }
701 _iterateTemporaryClassWorklist();
702 _iterateMixinLibraryWorklist();
703 }
704
652 void loadEverything({Target target, bool compileSdk}) { 705 void loadEverything({Target target, bool compileSdk}) {
653 compileSdk ??= true; 706 compileSdk ??= true;
654 if (compileSdk) { 707 if (compileSdk) {
655 ensureLibraryIsLoaded(getLibraryReference(getDartCoreLibrary())); 708 ensureLibraryIsLoaded(getLibraryReference(getDartCoreLibrary()));
656 if (target != null) { 709 if (target != null) {
657 for (var uri in target.extraRequiredLibraries) { 710 for (var uri in target.extraRequiredLibraries) {
658 var library = _findLibraryElement(uri); 711 var library = _findLibraryElement(uri);
659 if (library == null) { 712 if (library == null) {
660 errors.add('Could not find required library $uri'); 713 errors.add('Could not find required library $uri');
661 continue; 714 continue;
(...skipping 19 matching lines...) Expand all
681 LibraryElement element = context.computeLibraryElement(context 734 LibraryElement element = context.computeLibraryElement(context
682 .sourceFactory 735 .sourceFactory
683 .forUri2(applicationRoot.absoluteUri(library.importUri))); 736 .forUri2(applicationRoot.absoluteUri(library.importUri)));
684 for (var unit in element.units) { 737 for (var unit in element.units) {
685 list.add(unit.source.fullName); 738 list.add(unit.source.fullName);
686 } 739 }
687 } 740 }
688 return list; 741 return list;
689 } 742 }
690 743
691 void _iterateWorklist() { 744 void _iterateTemporaryClassWorklist() {
692 while (temporaryClassWorklist.isNotEmpty) { 745 while (temporaryClassWorklist.isNotEmpty) {
693 var element = temporaryClassWorklist.removeLast(); 746 var element = temporaryClassWorklist.removeLast();
694 promoteToTypeLevel(element); 747 promoteToTypeLevel(element);
695 } 748 }
696 } 749 }
697 750
751 void _iterateMixinLibraryWorklist() {
752 // The worklist groups classes in the same library together so that we
753 // request resolved ASTs for each library only once.
754 while (mixinLibraryWorklist.isNotEmpty) {
755 LibraryElement library = mixinLibraryWorklist.keys.first;
756 _libraryBeingLoaded = library;
757 List<ClassElement> classes = mixinLibraryWorklist.remove(library);
758 for (var class_ in classes) {
759 var classNode = getClassReference(class_);
760 promoteToMixinLevel(classNode, class_, class_.computeNode());
761 }
762 _libraryBeingLoaded = null;
763 }
764 _iterateTemporaryClassWorklist();
765 }
766
698 ast.Procedure _getMainMethod(Uri uri) { 767 ast.Procedure _getMainMethod(Uri uri) {
699 Source source = context.sourceFactory.forUri2(uri); 768 Source source = context.sourceFactory.forUri2(uri);
700 LibraryElement library = context.computeLibraryElement(source); 769 LibraryElement library = context.computeLibraryElement(source);
701 var mainElement = library.entryPoint; 770 var mainElement = library.entryPoint;
702 if (mainElement == null) return null; 771 if (mainElement == null) return null;
703 var mainMember = getMemberReference(mainElement); 772 var mainMember = getMemberReference(mainElement);
704 if (mainMember is ast.Procedure && !mainMember.isAccessor) { 773 if (mainMember is ast.Procedure && !mainMember.isAccessor) {
705 return mainMember; 774 return mainMember;
706 } 775 }
707 // Top-level 'main' getters are not supported at the moment. 776 // Top-level 'main' getters are not supported at the moment.
708 return null; 777 return null;
709 } 778 }
710 779
711 ast.Procedure _makeMissingMainMethod(ast.Library library) { 780 ast.Procedure _makeMissingMainMethod(ast.Library library) {
712 var main = new ast.Procedure( 781 var main = new ast.Procedure(
713 new ast.Name('main'), 782 new ast.Name('main'),
714 ast.ProcedureKind.Method, 783 ast.ProcedureKind.Method,
715 new ast.FunctionNode(new ast.ExpressionStatement(new ast.Throw( 784 new ast.FunctionNode(new ast.ExpressionStatement(new ast.Throw(
716 new ast.StringLiteral('Program has no main method')))), 785 new ast.StringLiteral('Program has no main method')))),
717 isStatic: true) 786 isStatic: true)..fileUri = library.fileUri;
718 ..fileUri = library.fileUri;
719 library.addMember(main); 787 library.addMember(main);
720 return main; 788 return main;
721 } 789 }
722 790
723 ast.Program loadProgram(Uri mainLibrary, {Target target, bool compileSdk}) { 791 ast.Program loadProgram(Uri mainLibrary, {Target target, bool compileSdk}) {
724 Uri uri = applicationRoot.relativeUri(mainLibrary); 792 Uri uri = applicationRoot.relativeUri(mainLibrary);
725 ast.Library library = repository.getLibraryReference(uri); 793 ast.Library library = repository.getLibraryReference(uri);
726 ensureLibraryIsLoaded(library); 794 ensureLibraryIsLoaded(library);
727 var mainMethod = _getMainMethod(mainLibrary); 795 var mainMethod = _getMainMethod(mainLibrary);
728 loadEverything(target: target, compileSdk: compileSdk); 796 loadEverything(target: target, compileSdk: compileSdk);
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext() 972 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext()
905 ..sourceFactory = new SourceFactory(resolvers) 973 ..sourceFactory = new SourceFactory(resolvers)
906 ..analysisOptions = createAnalysisOptions(options.strongMode); 974 ..analysisOptions = createAnalysisOptions(options.strongMode);
907 975
908 options.declaredVariables.forEach((String name, String value) { 976 options.declaredVariables.forEach((String name, String value) {
909 context.declaredVariables.define(name, value); 977 context.declaredVariables.define(name, value);
910 }); 978 });
911 979
912 return context; 980 return context;
913 } 981 }
OLDNEW
« no previous file with comments | « pkg/kernel/binary.md ('k') | pkg/kernel/lib/ast.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698