Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library fasta.source_loader; | |
| 6 | |
| 7 import 'dart:async' show | |
| 8 Future; | |
| 9 | |
| 10 import 'dart:io' show | |
| 11 FileSystemException; | |
| 12 | |
| 13 import 'package:dart_scanner/io.dart' show | |
| 14 readBytesFromFile; | |
| 15 | |
| 16 import 'package:dart_scanner/src/token.dart' show | |
| 17 Token; | |
| 18 | |
| 19 import 'package:dart_scanner/dart_scanner.dart' show | |
| 20 scan; | |
| 21 | |
| 22 import 'package:dart_parser/src/class_member_parser.dart' show | |
| 23 ClassMemberParser; | |
| 24 | |
| 25 import 'package:kernel/ast.dart' show | |
| 26 Program; | |
| 27 | |
| 28 import 'package:kernel/class_hierarchy.dart' show | |
| 29 ClassHierarchy; | |
| 30 | |
| 31 import 'package:kernel/core_types.dart' show | |
| 32 CoreTypes; | |
| 33 | |
| 34 import '../errors.dart' show | |
| 35 inputError; | |
| 36 | |
| 37 import '../export.dart' show | |
| 38 Export; | |
| 39 | |
| 40 import '../analyzer/element_store.dart' show | |
| 41 ElementStore; | |
| 42 | |
| 43 import '../builder/builder.dart' show | |
| 44 Builder, | |
| 45 ClassBuilder, | |
| 46 LibraryBuilder; | |
| 47 | |
| 48 import 'outline_builder.dart' show | |
| 49 OutlineBuilder; | |
| 50 | |
| 51 import '../loader.dart' show | |
| 52 Loader; | |
| 53 | |
| 54 import '../target_implementation.dart' show | |
| 55 TargetImplementation; | |
| 56 | |
| 57 import 'diet_listener.dart' show | |
| 58 DietListener; | |
| 59 | |
| 60 import 'diet_parser.dart' show | |
| 61 DietParser; | |
| 62 | |
| 63 import 'source_library_builder.dart' show | |
| 64 SourceLibraryBuilder; | |
| 65 | |
| 66 import '../ast_kind.dart' show | |
| 67 AstKind; | |
| 68 | |
| 69 class SourceLoader<L> extends Loader<L> { | |
| 70 // Used when building directly to kernel. | |
| 71 ClassHierarchy hierarchy; | |
| 72 CoreTypes coreTypes; | |
| 73 | |
| 74 // Used when building analyzer ASTs. | |
| 75 ElementStore elementStore; | |
| 76 | |
| 77 SourceLoader(TargetImplementation target) | |
| 78 : super(target); | |
| 79 | |
| 80 Future<Token> tokenize(SourceLibraryBuilder library) async { | |
| 81 Uri uri = library.uri; | |
| 82 if (uri.scheme != "file") { | |
| 83 uri = target.translateUri(uri); | |
| 84 if (uri == null) { | |
| 85 print("Skipping ${library.uri}"); | |
| 86 return null; | |
| 87 } | |
| 88 library.fileUri = uri; | |
| 89 } | |
| 90 try { | |
| 91 List<int> bytes = await readBytesFromFile(uri); | |
| 92 byteCount += bytes.length - 1; | |
| 93 return scan(bytes).tokens; | |
| 94 } on FileSystemException catch (e) { | |
| 95 String message = e.message; | |
| 96 String osMessage = e.osError?.message; | |
| 97 if (osMessage != null && osMessage.isNotEmpty) { | |
| 98 message = osMessage; | |
| 99 } | |
| 100 return inputError(uri, -1, message); | |
| 101 } | |
| 102 } | |
| 103 | |
| 104 Future<Null> buildOutline(SourceLibraryBuilder library) async { | |
| 105 Token tokens = await tokenize(library); | |
| 106 if (tokens == null) return; | |
| 107 OutlineBuilder listener = new OutlineBuilder(library); | |
| 108 new ClassMemberParser(listener).parseUnit(tokens); | |
| 109 } | |
| 110 | |
| 111 Future<Null> buildBody(LibraryBuilder library, AstKind astKind) async { | |
| 112 if (library is SourceLibraryBuilder) { | |
| 113 Token tokens = await tokenize(library); | |
| 114 if (tokens == null) return; | |
| 115 DietListener listener = new DietListener( | |
| 116 library, elementStore, hierarchy, coreTypes, astKind); | |
| 117 DietParser parser = new DietParser(listener); | |
| 118 parser.parseUnit(tokens); | |
| 119 for (SourceLibraryBuilder part in library.parts) { | |
| 120 Token tokens = await tokenize(part); | |
| 121 if (tokens != null) { | |
| 122 parser.parseUnit(tokens); | |
| 123 } | |
| 124 } | |
| 125 } | |
| 126 } | |
| 127 | |
| 128 void resolveParts() { | |
| 129 List<Uri> parts = <Uri>[]; | |
| 130 builders.forEach((Uri uri, LibraryBuilder library) { | |
| 131 if (library is SourceLibraryBuilder) { | |
| 132 if (library.isPart) { | |
| 133 library.validatePart(); | |
| 134 parts.add(uri); | |
| 135 } else { | |
| 136 library.includeParts(); | |
| 137 } | |
| 138 } | |
| 139 }); | |
| 140 parts.forEach(builders.remove); | |
| 141 ticker.logMs("Resolved parts"); | |
| 142 } | |
| 143 | |
| 144 void computeLibraryScopes() { | |
| 145 Set<LibraryBuilder> exporters = new Set<LibraryBuilder>(); | |
| 146 Set<LibraryBuilder> exportees = new Set<LibraryBuilder>(); | |
| 147 builders.forEach((Uri uri, LibraryBuilder library) { | |
| 148 if (library is SourceLibraryBuilder) { | |
| 149 library.buildInitialScopes(); | |
| 150 } | |
| 151 if (library.exporters.isNotEmpty) { | |
| 152 exportees.add(library); | |
| 153 for (Export exporter in library.exporters) { | |
| 154 exporters.add(exporter.exporter); | |
| 155 } | |
| 156 } | |
| 157 }); | |
| 158 Set<SourceLibraryBuilder> both = new Set<SourceLibraryBuilder>(); | |
| 159 for (LibraryBuilder exported in exportees) { | |
| 160 if (exporters.contains(exported)) { | |
| 161 both.add(exported); | |
| 162 } | |
| 163 for (Export export in exported.exporters) { | |
| 164 exported.exports.forEach(export.addToExportScope); | |
| 165 } | |
| 166 } | |
| 167 bool wasChanged = false; | |
| 168 do { | |
| 169 wasChanged = false; | |
| 170 for (SourceLibraryBuilder exported in both) { | |
| 171 for (Export export in exported.exporters) { | |
| 172 SourceLibraryBuilder exporter = export.exporter; | |
| 173 exported.exports.forEach((String name, Builder member) { | |
| 174 if (exporter.addToExportScope(name, member)) { | |
| 175 wasChanged = true; | |
| 176 } | |
| 177 }); | |
| 178 } | |
| 179 } | |
| 180 } while (wasChanged); | |
| 181 builders.forEach((Uri uri, LibraryBuilder library) { | |
| 182 if (library is SourceLibraryBuilder) { | |
| 183 library.addImportsToScope(); | |
| 184 } | |
| 185 }); | |
| 186 ticker.logMs("Computed library scopes"); | |
| 187 // debugPrintExports(); | |
| 188 } | |
| 189 | |
| 190 void debugPrintExports() { | |
| 191 builders.forEach((Uri uri, SourceLibraryBuilder library) { | |
| 192 Set<Builder> members = new Set<Builder>(); | |
| 193 library.members.forEach((String name, Builder member) { | |
| 194 while (member != null) { | |
| 195 members.add(member); | |
| 196 member = member.next; | |
| 197 } | |
| 198 }); | |
| 199 List<String> exports = <String>[]; | |
| 200 library.exports.forEach((String name, Builder member) { | |
| 201 while (member != null) { | |
| 202 if (!members.contains(member)) { | |
| 203 exports.add(name); | |
| 204 } | |
| 205 member = member.next; | |
| 206 } | |
| 207 }); | |
| 208 if (exports.isNotEmpty) { | |
| 209 print("$uri exports $exports"); | |
| 210 } | |
| 211 }); | |
| 212 } | |
| 213 | |
| 214 void resolveTypes() { | |
| 215 int typeCount = 0; | |
| 216 builders.forEach((Uri uri, LibraryBuilder library) { | |
| 217 typeCount += library.resolveTypes(null); | |
| 218 }); | |
| 219 ticker.logMs("Resolved $typeCount types"); | |
| 220 } | |
| 221 | |
| 222 void convertConstructors() { | |
| 223 int count = 0; | |
| 224 builders.forEach((Uri uri, LibraryBuilder library) { | |
| 225 count += library.convertConstructors(null); | |
| 226 }); | |
| 227 ticker.logMs("Converted $count constructors"); | |
| 228 } | |
| 229 | |
| 230 void finishStaticInvocations() { | |
| 231 int count = 0; | |
| 232 builders.forEach((Uri uri, LibraryBuilder library) { | |
| 233 count += library.finishStaticInvocations(); | |
| 234 }); | |
| 235 ticker.logMs("Finished static invocations $count"); | |
| 236 } | |
| 237 | |
| 238 void resolveConstructors() { | |
| 239 int count = 0; | |
| 240 builders.forEach((Uri uri, LibraryBuilder library) { | |
| 241 count += library.resolveConstructors(null); | |
| 242 }); | |
| 243 ticker.logMs("Resolved $count constructors"); | |
| 244 } | |
| 245 | |
| 246 Set<ClassBuilder> allSupertypes(ClassBuilder cls) { | |
|
Johnni Winther
2017/01/19 09:21:34
Add dartdoc (it is strict supertypes, right?)
ahe
2017/01/19 10:48:31
Depends on what you mean by "strict". Since [cls]
| |
| 247 int length = 0; | |
| 248 Set<ClassBuilder> result = new Set<ClassBuilder>()..add(cls); | |
| 249 while (length != result.length) { | |
| 250 length = result.length; | |
| 251 result.addAll(directSupertypes(result)); | |
| 252 } | |
| 253 return result; | |
| 254 } | |
| 255 | |
| 256 Set<ClassBuilder> directSupertypes(Iterable<ClassBuilder> classes) { | |
|
Johnni Winther
2017/01/19 09:21:34
Add dartdoc
ahe
2017/01/19 10:48:31
Done.
| |
| 257 Set<ClassBuilder> result = new Set<ClassBuilder>(); | |
| 258 for (ClassBuilder cls in classes) { | |
| 259 target.addDirectSupertype(cls, result); | |
| 260 } | |
| 261 return result; | |
| 262 } | |
| 263 | |
| 264 Iterable<ClassBuilder> cyclicCandidates(Iterable<ClassBuilder> classes) { | |
|
Johnni Winther
2017/01/19 09:21:34
Document how/why this works.
ahe
2017/01/19 10:48:30
Done.
| |
| 265 Iterable<ClassBuilder> input = const []; | |
| 266 Iterable<ClassBuilder> output = classes; | |
| 267 while (input.length != output.length) { | |
| 268 input = output; | |
| 269 output = directSupertypes(input); | |
| 270 } | |
| 271 return output; | |
| 272 } | |
| 273 | |
| 274 void checkSemantics() { | |
| 275 List<ClassBuilder> allClasses = target.collectAllClasses(); | |
| 276 Iterable<ClassBuilder> candidates = cyclicCandidates(allClasses); | |
|
Johnni Winther
2017/01/19 09:21:34
Return early if [candidate] is empty?
ahe
2017/01/19 10:48:30
Then it wouldn't print the log message.
| |
| 277 Map<ClassBuilder, Set<ClassBuilder>> realCycles = | |
| 278 <ClassBuilder, Set<ClassBuilder>>{}; | |
| 279 for (ClassBuilder cls in candidates) { | |
| 280 Set<ClassBuilder> cycles = cyclicCandidates(allSupertypes(cls)); | |
| 281 if (cycles.isNotEmpty) { | |
| 282 realCycles[cls] = cycles; | |
| 283 } | |
| 284 } | |
| 285 Set<ClassBuilder> reported = new Set<ClassBuilder>(); | |
| 286 realCycles.forEach((ClassBuilder cls, Set<ClassBuilder> cycles) { | |
| 287 target.breakCycle(cls); | |
| 288 if (reported.add(cls)) { | |
| 289 List<ClassBuilder> involved = <ClassBuilder>[]; | |
| 290 for (ClassBuilder cls in cycles) { | |
| 291 if (realCycles.containsKey(cls)) { | |
| 292 involved.add(cls); | |
| 293 reported.add(cls); | |
| 294 } | |
| 295 } | |
| 296 print("${cls.name} is a supertype of itself via " | |
| 297 "${involved.map((c) => c.name).join(' ')}"); | |
| 298 } | |
| 299 }); | |
| 300 ticker.logMs("Found cycles"); | |
| 301 } | |
| 302 | |
| 303 void buildProgram() { | |
| 304 builders.forEach((Uri uri, LibraryBuilder library) { | |
| 305 if (library is SourceLibraryBuilder) { | |
| 306 libraries.add(library.build()); | |
| 307 } | |
| 308 }); | |
| 309 ticker.logMs("Built program"); | |
| 310 } | |
| 311 | |
| 312 void buildElementStore() { | |
| 313 elementStore = new ElementStore(coreLibrary, builders); | |
| 314 ticker.logMs("Built analyzer element model."); | |
| 315 } | |
| 316 | |
| 317 void computeHierarchy(Program program) { | |
| 318 hierarchy = new ClassHierarchy(program); | |
| 319 ticker.logMs("Computed class hierarchy"); | |
| 320 coreTypes = new CoreTypes(program); | |
| 321 ticker.logMs("Computed core types"); | |
| 322 } | |
| 323 } | |
| OLD | NEW |