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 import 'dart:collection' show HashSet; | 5 import 'dart:collection' show HashSet, Queue; |
6 import 'package:args/args.dart' show ArgParser, ArgResults; | 6 import 'package:analyzer/dart/element/element.dart' show LibraryElement; |
7 import 'package:args/src/usage_exception.dart' show UsageException; | |
8 import 'package:analyzer/analyzer.dart' | 7 import 'package:analyzer/analyzer.dart' |
9 show | 8 show AnalysisError, CompilationUnit, ErrorSeverity; |
10 AnalysisError, | |
11 CompilationUnit, | |
12 CompileTimeErrorCode, | |
13 ErrorSeverity, | |
14 StaticWarningCode; | |
15 import 'package:analyzer/file_system/file_system.dart' show ResourceProvider; | 9 import 'package:analyzer/file_system/file_system.dart' show ResourceProvider; |
16 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; | 10 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
17 import 'package:analyzer/src/generated/source.dart' show DartUriResolver; | 11 import 'package:analyzer/src/generated/source.dart' show DartUriResolver; |
18 import 'package:analyzer/src/generated/source_io.dart' | 12 import 'package:analyzer/src/generated/source_io.dart' |
19 show Source, SourceKind, UriResolver; | 13 show Source, SourceKind, UriResolver; |
| 14 import 'package:analyzer/src/summary/package_bundle_reader.dart' |
| 15 show InSummarySource; |
| 16 import 'package:args/args.dart' show ArgParser, ArgResults; |
| 17 import 'package:args/src/usage_exception.dart' show UsageException; |
20 import 'package:func/func.dart' show Func1; | 18 import 'package:func/func.dart' show Func1; |
21 import 'package:path/path.dart' as path; | 19 import 'package:path/path.dart' as path; |
22 | 20 |
23 import '../analyzer/context.dart' | 21 import '../analyzer/context.dart' |
24 show AnalyzerOptions, createAnalysisContextWithSources; | 22 show AnalyzerOptions, createAnalysisContextWithSources; |
25 import 'extension_types.dart' show ExtensionTypeSet; | 23 import 'extension_types.dart' show ExtensionTypeSet; |
26 import 'code_generator.dart' show CodeGenerator; | 24 import 'code_generator.dart' show CodeGenerator; |
27 import 'error_helpers.dart' show errorSeverity, formatError, sortErrors; | 25 import 'error_helpers.dart' show errorSeverity, formatError, sortErrors; |
28 | 26 |
29 /// Compiles a set of Dart files into a single JavaScript module. | 27 /// Compiles a set of Dart files into a single JavaScript module. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 | 67 |
70 /// Compiles a single Dart build unit into a JavaScript module. | 68 /// Compiles a single Dart build unit into a JavaScript module. |
71 /// | 69 /// |
72 /// *Warning* - this may require resolving the entire world. | 70 /// *Warning* - this may require resolving the entire world. |
73 /// If that is not desired, the analysis context must be pre-configured using | 71 /// If that is not desired, the analysis context must be pre-configured using |
74 /// summaries before calling this method. | 72 /// summaries before calling this method. |
75 JSModuleFile compile(BuildUnit unit, CompilerOptions options) { | 73 JSModuleFile compile(BuildUnit unit, CompilerOptions options) { |
76 var trees = <CompilationUnit>[]; | 74 var trees = <CompilationUnit>[]; |
77 var errors = <AnalysisError>[]; | 75 var errors = <AnalysisError>[]; |
78 | 76 |
79 // Validate that all parts were explicitly passed in. | 77 var librariesToCompile = new Queue<LibraryElement>(); |
80 // If not, it's an error. | 78 |
81 var explicitParts = new HashSet<Source>(); | 79 var compilingSdk = false; |
82 var usedParts = new HashSet<Source>(); | |
83 for (var sourcePath in unit.sources) { | 80 for (var sourcePath in unit.sources) { |
84 var sourceUri = Uri.parse(sourcePath); | 81 var sourceUri = Uri.parse(sourcePath); |
85 if (sourceUri.scheme == '') { | 82 if (sourceUri.scheme == '') { |
86 sourceUri = path.toUri(path.absolute(sourcePath)); | 83 sourceUri = path.toUri(path.absolute(sourcePath)); |
| 84 } else if (sourceUri.scheme == 'dart') { |
| 85 compilingSdk = true; |
87 } | 86 } |
88 Source source = context.sourceFactory.forUri2(sourceUri); | 87 Source source = context.sourceFactory.forUri2(sourceUri); |
89 | 88 |
90 var fileUsage = 'You need to pass at least one existing .dart file as an' | 89 var fileUsage = 'You need to pass at least one existing .dart file as an' |
91 ' argument.'; | 90 ' argument.'; |
92 if (source == null) { | 91 if (source == null) { |
93 throw new UsageException( | 92 throw new UsageException( |
94 'Could not create a source for "$sourcePath". The file name is in' | 93 'Could not create a source for "$sourcePath". The file name is in' |
95 ' the wrong format or was not found.', | 94 ' the wrong format or was not found.', |
96 fileUsage); | 95 fileUsage); |
97 } else if (!source.exists()) { | 96 } else if (!source.exists()) { |
98 throw new UsageException( | 97 throw new UsageException( |
99 'Given file "$sourcePath" does not exist.', fileUsage); | 98 'Given file "$sourcePath" does not exist.', fileUsage); |
100 } | 99 } |
101 | 100 |
102 // Ignore parts. They need to be handled in the context of their library. | 101 // Ignore parts. They need to be handled in the context of their library. |
103 if (context.computeKindOf(source) == SourceKind.PART) { | 102 if (context.computeKindOf(source) == SourceKind.PART) { |
104 explicitParts.add(source); | |
105 continue; | 103 continue; |
106 } | 104 } |
107 | 105 |
108 var resolvedTree = context.resolveCompilationUnit2(source, source); | 106 librariesToCompile.add(context.computeLibraryElement(source)); |
109 trees.add(resolvedTree); | 107 } |
110 errors.addAll(context.computeErrors(source)); | |
111 | 108 |
112 var library = resolvedTree.element.library; | 109 var libraries = new HashSet<LibraryElement>(); |
| 110 while (librariesToCompile.isNotEmpty) { |
| 111 var library = librariesToCompile.removeFirst(); |
| 112 if (library.source is InSummarySource) continue; |
| 113 if (!compilingSdk && library.source.isInSystemLibrary) continue; |
| 114 if (!libraries.add(library)) continue; |
| 115 |
| 116 librariesToCompile.addAll(library.importedLibraries); |
| 117 librariesToCompile.addAll(library.exportedLibraries); |
| 118 |
| 119 var tree = context.resolveCompilationUnit(library.source, library); |
| 120 trees.add(tree); |
| 121 errors.addAll(context.computeErrors(library.source)); |
| 122 |
113 for (var part in library.parts) { | 123 for (var part in library.parts) { |
114 if (!library.isInSdk) usedParts.add(part.source); | |
115 trees.add(context.resolveCompilationUnit(part.source, library)); | 124 trees.add(context.resolveCompilationUnit(part.source, library)); |
116 errors.addAll(context.computeErrors(part.source)); | 125 errors.addAll(context.computeErrors(part.source)); |
117 } | 126 } |
118 } | 127 } |
119 | 128 |
120 // Check if all parts were explicitly passed in. | |
121 // Also verify all explicitly parts were used. | |
122 var missingParts = usedParts.difference(explicitParts); | |
123 var unusedParts = explicitParts.difference(usedParts); | |
124 errors.addAll(missingParts | |
125 .map((s) => new AnalysisError(s, 0, 0, missingPartErrorCode))); | |
126 errors.addAll(unusedParts | |
127 .map((s) => new AnalysisError(s, 0, 0, unusedPartWarningCode))); | |
128 | |
129 sortErrors(context, errors); | 129 sortErrors(context, errors); |
130 var messages = <String>[]; | 130 var messages = <String>[]; |
131 for (var e in errors) { | 131 for (var e in errors) { |
132 var m = formatError(context, e); | 132 var m = formatError(context, e); |
133 if (m != null) messages.add(m); | 133 if (m != null) messages.add(m); |
134 } | 134 } |
135 | 135 |
136 if (!options.unsafeForceCompile && | 136 if (!options.unsafeForceCompile && |
137 errors.any((e) => errorSeverity(context, e) == ErrorSeverity.ERROR)) { | 137 errors.any((e) => errorSeverity(context, e) == ErrorSeverity.ERROR)) { |
138 return new JSModuleFile.invalid(unit.name, messages); | 138 return new JSModuleFile.invalid(unit.name, messages); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 | 358 |
359 var map = new Map.from(this.sourceMap); | 359 var map = new Map.from(this.sourceMap); |
360 List list = new List.from(map['sources']); | 360 List list = new List.from(map['sources']); |
361 map['sources'] = list; | 361 map['sources'] = list; |
362 for (int i = 0; i < list.length; i++) { | 362 for (int i = 0; i < list.length; i++) { |
363 list[i] = path.relative(list[i], from: dir); | 363 list[i] = path.relative(list[i], from: dir); |
364 } | 364 } |
365 return map; | 365 return map; |
366 } | 366 } |
367 } | 367 } |
368 | |
369 /// (Public for tests) the error code used when a part is missing. | |
370 final missingPartErrorCode = const CompileTimeErrorCode( | |
371 'MISSING_PART', 'The part was not supplied as an input to the compiler.'); | |
372 | |
373 /// (Public for tests) the error code used when a part is unused. | |
374 final unusedPartWarningCode = const StaticWarningCode('UNUSED_PART', | |
375 'The part was not used by any libraries being compiled.', null, false); | |
OLD | NEW |