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

Side by Side Diff: pkg/compiler/lib/src/native/enqueue.dart

Issue 1383483006: Extract DiagnosticReporter implementation from Compiler. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 part of native; 5 part of native;
6 6
7 /** 7 /**
8 * This could be an abstract class but we use it as a stub for the dart_backend. 8 * This could be an abstract class but we use it as a stub for the dart_backend.
9 */ 9 */
10 class NativeEnqueuer { 10 class NativeEnqueuer {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 ClassElement _annotationJsNameClass; 90 ClassElement _annotationJsNameClass;
91 91
92 /// Subclasses of [NativeEnqueuerBase] are constructed by the backend. 92 /// Subclasses of [NativeEnqueuerBase] are constructed by the backend.
93 NativeEnqueuerBase(this.world, Compiler compiler, this.enableLiveTypeAnalysis) 93 NativeEnqueuerBase(this.world, Compiler compiler, this.enableLiveTypeAnalysis)
94 : this.compiler = compiler, 94 : this.compiler = compiler,
95 processedLibraries = compiler.cacheStrategy.newSet(); 95 processedLibraries = compiler.cacheStrategy.newSet();
96 96
97 JavaScriptBackend get backend => compiler.backend; 97 JavaScriptBackend get backend => compiler.backend;
98 Resolution get resolution => compiler.resolution; 98 Resolution get resolution => compiler.resolution;
99 99
100 DiagnosticReporter get reporter => compiler.reporter;
101
100 void processNativeClasses(Iterable<LibraryElement> libraries) { 102 void processNativeClasses(Iterable<LibraryElement> libraries) {
101 if (compiler.hasIncrementalSupport) { 103 if (compiler.hasIncrementalSupport) {
102 // Since [Set.add] returns bool if an element was added, this restricts 104 // Since [Set.add] returns bool if an element was added, this restricts
103 // [libraries] to ones that haven't already been processed. This saves 105 // [libraries] to ones that haven't already been processed. This saves
104 // time during incremental compiles. 106 // time during incremental compiles.
105 libraries = libraries.where(processedLibraries.add); 107 libraries = libraries.where(processedLibraries.add);
106 } 108 }
107 libraries.forEach(processNativeClassesInLibrary); 109 libraries.forEach(processNativeClassesInLibrary);
108 if (backend.isolateHelperLibrary != null) { 110 if (backend.isolateHelperLibrary != null) {
109 processNativeClassesInLibrary(backend.isolateHelperLibrary); 111 processNativeClassesInLibrary(backend.isolateHelperLibrary);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 token = token.next; 238 token = token.next;
237 if (token.stringValue != '.') break; 239 if (token.stringValue != '.') break;
238 token = token.next; 240 token = token.next;
239 if (!token.isIdentifier()) return null; 241 if (!token.isIdentifier()) return null;
240 id = token; 242 id = token;
241 } 243 }
242 // Should be at '{', 'with', 'implements', '<' or 'native'. 244 // Should be at '{', 'with', 'implements', '<' or 'native'.
243 return id.value; 245 return id.value;
244 } 246 }
245 247
246 return compiler.withCurrentElement(classElement, () { 248 return reporter.withCurrentElement(classElement, () {
247 return scanForExtendsName(classElement.position); 249 return scanForExtendsName(classElement.position);
248 }); 250 });
249 } 251 }
250 252
251 ClassElement get annotationCreatesClass { 253 ClassElement get annotationCreatesClass {
252 findAnnotationClasses(); 254 findAnnotationClasses();
253 return _annotationCreatesClass; 255 return _annotationCreatesClass;
254 } 256 }
255 257
256 ClassElement get annotationReturnsClass { 258 ClassElement get annotationReturnsClass {
257 findAnnotationClasses(); 259 findAnnotationClasses();
258 return _annotationReturnsClass; 260 return _annotationReturnsClass;
259 } 261 }
260 262
261 ClassElement get annotationJsNameClass { 263 ClassElement get annotationJsNameClass {
262 findAnnotationClasses(); 264 findAnnotationClasses();
263 return _annotationJsNameClass; 265 return _annotationJsNameClass;
264 } 266 }
265 267
266 void findAnnotationClasses() { 268 void findAnnotationClasses() {
267 if (_annotationCreatesClass != null) return; 269 if (_annotationCreatesClass != null) return;
268 ClassElement find(name) { 270 ClassElement find(name) {
269 Element e = backend.findHelper(name); 271 Element e = backend.findHelper(name);
270 if (e == null || e is! ClassElement) { 272 if (e == null || e is! ClassElement) {
271 compiler.internalError(NO_LOCATION_SPANNABLE, 273 reporter.internalError(NO_LOCATION_SPANNABLE,
272 "Could not find implementation class '${name}'."); 274 "Could not find implementation class '${name}'.");
273 } 275 }
274 return e; 276 return e;
275 } 277 }
276 _annotationCreatesClass = find('Creates'); 278 _annotationCreatesClass = find('Creates');
277 _annotationReturnsClass = find('Returns'); 279 _annotationReturnsClass = find('Returns');
278 _annotationJsNameClass = find('JSName'); 280 _annotationJsNameClass = find('JSName');
279 } 281 }
280 282
281 /// Returns the JSName annotation string or `null` if no JSName annotation is 283 /// Returns the JSName annotation string or `null` if no JSName annotation is
282 /// present. 284 /// present.
283 String findJsNameFromAnnotation(Element element) { 285 String findJsNameFromAnnotation(Element element) {
284 String name = null; 286 String name = null;
285 ClassElement annotationClass = annotationJsNameClass; 287 ClassElement annotationClass = annotationJsNameClass;
286 for (MetadataAnnotation annotation in element.implementation.metadata) { 288 for (MetadataAnnotation annotation in element.implementation.metadata) {
287 annotation.ensureResolved(resolution); 289 annotation.ensureResolved(resolution);
288 ConstantValue value = 290 ConstantValue value =
289 compiler.constants.getConstantValue(annotation.constant); 291 compiler.constants.getConstantValue(annotation.constant);
290 if (!value.isConstructedObject) continue; 292 if (!value.isConstructedObject) continue;
291 ConstructedConstantValue constructedObject = value; 293 ConstructedConstantValue constructedObject = value;
292 if (constructedObject.type.element != annotationClass) continue; 294 if (constructedObject.type.element != annotationClass) continue;
293 295
294 Iterable<ConstantValue> fields = constructedObject.fields.values; 296 Iterable<ConstantValue> fields = constructedObject.fields.values;
295 // TODO(sra): Better validation of the constant. 297 // TODO(sra): Better validation of the constant.
296 if (fields.length != 1 || fields.single is! StringConstantValue) { 298 if (fields.length != 1 || fields.single is! StringConstantValue) {
297 compiler.internalError(annotation, 299 reporter.internalError(annotation,
298 'Annotations needs one string: ${annotation.node}'); 300 'Annotations needs one string: ${annotation.node}');
299 } 301 }
300 StringConstantValue specStringConstant = fields.single; 302 StringConstantValue specStringConstant = fields.single;
301 String specString = specStringConstant.toDartString().slowToString(); 303 String specString = specStringConstant.toDartString().slowToString();
302 if (name == null) { 304 if (name == null) {
303 name = specString; 305 name = specString;
304 } else { 306 } else {
305 compiler.internalError(annotation, 307 reporter.internalError(annotation,
306 'Too many JSName annotations: ${annotation.node}'); 308 'Too many JSName annotations: ${annotation.node}');
307 } 309 }
308 } 310 }
309 return name; 311 return name;
310 } 312 }
311 313
312 enqueueClass(ClassElement classElement, cause) { 314 enqueueClass(ClassElement classElement, cause) {
313 assert(unusedClasses.contains(classElement)); 315 assert(unusedClasses.contains(classElement));
314 unusedClasses.remove(classElement); 316 unusedClasses.remove(classElement);
315 pendingClasses.add(classElement); 317 pendingClasses.add(classElement);
(...skipping 22 matching lines...) Expand all
338 classElement.ensureResolved(resolution); 340 classElement.ensureResolved(resolution);
339 compiler.backend.registerInstantiatedType( 341 compiler.backend.registerInstantiatedType(
340 classElement.rawType, world, compiler.globalDependencies); 342 classElement.rawType, world, compiler.globalDependencies);
341 343
342 if (firstTime) { 344 if (firstTime) {
343 queue.add(onFirstNativeClass); 345 queue.add(onFirstNativeClass);
344 } 346 }
345 } 347 }
346 348
347 registerElement(Element element) { 349 registerElement(Element element) {
348 compiler.withCurrentElement(element, () { 350 reporter.withCurrentElement(element, () {
349 if (element.isFunction || element.isGetter || element.isSetter) { 351 if (element.isFunction || element.isGetter || element.isSetter) {
350 handleMethodAnnotations(element); 352 handleMethodAnnotations(element);
351 if (element.isNative) { 353 if (element.isNative) {
352 registerMethodUsed(element); 354 registerMethodUsed(element);
353 } 355 }
354 } else if (element.isField) { 356 } else if (element.isField) {
355 handleFieldAnnotations(element); 357 handleFieldAnnotations(element);
356 if (element.isNative) { 358 if (element.isNative) {
357 registerFieldLoad(element); 359 registerFieldLoad(element);
358 registerFieldStore(element); 360 registerFieldStore(element);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 /// 2. If [element] has a @JSName annotation that is not an identifier, 400 /// 2. If [element] has a @JSName annotation that is not an identifier,
399 /// use the declared @JSName as the expression 401 /// use the declared @JSName as the expression
400 /// 3. If [element] does not have a @JSName annotation, qualify the name of 402 /// 3. If [element] does not have a @JSName annotation, qualify the name of
401 /// the method with the @Native name of the enclosing class. 403 /// the method with the @Native name of the enclosing class.
402 void setNativeNameForStaticMethod(ElementX element) { 404 void setNativeNameForStaticMethod(ElementX element) {
403 String name = findJsNameFromAnnotation(element); 405 String name = findJsNameFromAnnotation(element);
404 if (name == null) name = element.name; 406 if (name == null) name = element.name;
405 if (isIdentifier(name)) { 407 if (isIdentifier(name)) {
406 List<String> nativeNames = nativeTagsOfClassRaw(element.enclosingClass); 408 List<String> nativeNames = nativeTagsOfClassRaw(element.enclosingClass);
407 if (nativeNames.length != 1) { 409 if (nativeNames.length != 1) {
408 compiler.internalError(element, 410 reporter.internalError(element,
409 'Unable to determine a native name for the enclosing class, ' 411 'Unable to determine a native name for the enclosing class, '
410 'options: $nativeNames'); 412 'options: $nativeNames');
411 } 413 }
412 element.setNative('${nativeNames[0]}.$name'); 414 element.setNative('${nativeNames[0]}.$name');
413 } else { 415 } else {
414 element.setNative(name); 416 element.setNative(name);
415 } 417 }
416 } 418 }
417 419
418 bool isIdentifier(String s) => _identifier.hasMatch(s); 420 bool isIdentifier(String s) => _identifier.hasMatch(s);
419 421
420 bool isNativeMethod(FunctionElementX element) { 422 bool isNativeMethod(FunctionElementX element) {
421 if (!element.library.canUseNative) return false; 423 if (!element.library.canUseNative) return false;
422 // Native method? 424 // Native method?
423 return compiler.withCurrentElement(element, () { 425 return reporter.withCurrentElement(element, () {
424 Node node = element.parseNode(resolution.parsing); 426 Node node = element.parseNode(resolution.parsing);
425 if (node is! FunctionExpression) return false; 427 if (node is! FunctionExpression) return false;
426 FunctionExpression functionExpression = node; 428 FunctionExpression functionExpression = node;
427 node = functionExpression.body; 429 node = functionExpression.body;
428 Token token = node.getBeginToken(); 430 Token token = node.getBeginToken();
429 if (identical(token.stringValue, 'native')) return true; 431 if (identical(token.stringValue, 'native')) return true;
430 return false; 432 return false;
431 }); 433 });
432 } 434 }
433 435
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 assert(type is DartType); 490 assert(type is DartType);
489 enqueueUnusedClassesMatching( 491 enqueueUnusedClassesMatching(
490 (nativeClass) => compiler.types.isSubtype(nativeClass.thisType, type), 492 (nativeClass) => compiler.types.isSubtype(nativeClass.thisType, type),
491 cause, 493 cause,
492 'subtypeof($type)'); 494 'subtypeof($type)');
493 } 495 }
494 496
495 // Give an info so that library developers can compile with -v to find why 497 // Give an info so that library developers can compile with -v to find why
496 // all the native classes are included. 498 // all the native classes are included.
497 if (unusedClasses.isEmpty && !allUsedBefore) { 499 if (unusedClasses.isEmpty && !allUsedBefore) {
498 compiler.log('All native types marked as used due to $cause.'); 500 reporter.log('All native types marked as used due to $cause.');
499 } 501 }
500 } 502 }
501 503
502 enqueueUnusedClassesMatching(bool predicate(classElement), 504 enqueueUnusedClassesMatching(bool predicate(classElement),
503 cause, 505 cause,
504 [String reason]) { 506 [String reason]) {
505 Iterable matches = unusedClasses.where(predicate); 507 Iterable matches = unusedClasses.where(predicate);
506 matches.toList().forEach((c) => enqueueClass(c, cause)); 508 matches.toList().forEach((c) => enqueueClass(c, cause));
507 } 509 }
508 510
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 543
542 void processNativeClass(ClassElement classElement) { 544 void processNativeClass(ClassElement classElement) {
543 super.processNativeClass(classElement); 545 super.processNativeClass(classElement);
544 546
545 // Since we map from dispatch tags to classes, a dispatch tag must be used 547 // Since we map from dispatch tags to classes, a dispatch tag must be used
546 // on only one native class. 548 // on only one native class.
547 for (String tag in nativeTagsOfClass(classElement)) { 549 for (String tag in nativeTagsOfClass(classElement)) {
548 ClassElement owner = tagOwner[tag]; 550 ClassElement owner = tagOwner[tag];
549 if (owner != null) { 551 if (owner != null) {
550 if (owner != classElement) { 552 if (owner != classElement) {
551 compiler.internalError( 553 reporter.internalError(
552 classElement, "Tag '$tag' already in use by '${owner.name}'"); 554 classElement, "Tag '$tag' already in use by '${owner.name}'");
553 } 555 }
554 } else { 556 } else {
555 tagOwner[tag] = classElement; 557 tagOwner[tag] = classElement;
556 } 558 }
557 } 559 }
558 } 560 }
559 561
560 void logSummary(log(message)) { 562 void logSummary(log(message)) {
561 log('Resolved ${registeredClasses.length} native elements used, ' 563 log('Resolved ${registeredClasses.length} native elements used, '
562 '${unusedClasses.length} native elements dead.'); 564 '${unusedClasses.length} native elements dead.');
563 } 565 }
564 566
565 /** 567 /**
566 * Handles JS-calls, which can be an instantiation point for types. 568 * Handles JS-calls, which can be an instantiation point for types.
567 * 569 *
568 * For example, the following code instantiates and returns native classes 570 * For example, the following code instantiates and returns native classes
569 * that are `_DOMWindowImpl` or a subtype. 571 * that are `_DOMWindowImpl` or a subtype.
570 * 572 *
571 * JS('_DOMWindowImpl', 'window') 573 * JS('_DOMWindowImpl', 'window')
572 * 574 *
573 */ 575 */
574 void registerJsCall(Send node, ForeignResolver resolver) { 576 void registerJsCall(Send node, ForeignResolver resolver) {
575 NativeBehavior behavior = NativeBehavior.ofJsCall(node, compiler, resolver); 577 NativeBehavior behavior = NativeBehavior.ofJsCall(
578 node, reporter, compiler.parsing, compiler.coreTypes, resolver);
576 registerNativeBehavior(behavior, node); 579 registerNativeBehavior(behavior, node);
577 nativeBehaviors[node] = behavior; 580 nativeBehaviors[node] = behavior;
578 } 581 }
579 582
580 583
581 /** 584 /**
582 * Handles JS-embedded global calls, which can be an instantiation point for 585 * Handles JS-embedded global calls, which can be an instantiation point for
583 * types. 586 * types.
584 * 587 *
585 * For example, the following code instantiates and returns a String class 588 * For example, the following code instantiates and returns a String class
586 * 589 *
587 * JS_EMBEDDED_GLOBAL('String', 'foo') 590 * JS_EMBEDDED_GLOBAL('String', 'foo')
588 * 591 *
589 */ 592 */
590 void registerJsEmbeddedGlobalCall(Send node, ForeignResolver resolver) { 593 void registerJsEmbeddedGlobalCall(Send node, ForeignResolver resolver) {
591 NativeBehavior behavior = 594 NativeBehavior behavior = NativeBehavior.ofJsEmbeddedGlobalCall(
592 NativeBehavior.ofJsEmbeddedGlobalCall(node, compiler, resolver); 595 node, reporter, compiler.parsing, compiler.coreTypes, resolver);
593 registerNativeBehavior(behavior, node); 596 registerNativeBehavior(behavior, node);
594 nativeBehaviors[node] = behavior; 597 nativeBehaviors[node] = behavior;
595 } 598 }
596 599
597 600
598 /** 601 /**
599 * Handles JS-compiler builtin calls, which can be an instantiation point for 602 * Handles JS-compiler builtin calls, which can be an instantiation point for
600 * types. 603 * types.
601 * 604 *
602 * For example, the following code instantiates and returns a String class 605 * For example, the following code instantiates and returns a String class
603 * 606 *
604 * JS_BUILTIN('String', 'int2string', 0) 607 * JS_BUILTIN('String', 'int2string', 0)
605 * 608 *
606 */ 609 */
607 void registerJsBuiltinCall(Send node, ForeignResolver resolver) { 610 void registerJsBuiltinCall(Send node, ForeignResolver resolver) {
608 NativeBehavior behavior = 611 NativeBehavior behavior = NativeBehavior.ofJsBuiltinCall(
609 NativeBehavior.ofJsBuiltinCall(node, compiler, resolver); 612 node, reporter, compiler.parsing, compiler.coreTypes, resolver);
610 registerNativeBehavior(behavior, node); 613 registerNativeBehavior(behavior, node);
611 nativeBehaviors[node] = behavior; 614 nativeBehaviors[node] = behavior;
612 } 615 }
613 } 616 }
614 617
615 618
616 class NativeCodegenEnqueuer extends NativeEnqueuerBase { 619 class NativeCodegenEnqueuer extends NativeEnqueuerBase {
617 620
618 final CodeEmitterTask emitter; 621 final CodeEmitterTask emitter;
619 622
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 superclass, 674 superclass,
672 () => <ClassElement>[]); 675 () => <ClassElement>[]);
673 directSubtypes.add(cls); 676 directSubtypes.add(cls);
674 } 677 }
675 678
676 void logSummary(log(message)) { 679 void logSummary(log(message)) {
677 log('Compiled ${registeredClasses.length} native classes, ' 680 log('Compiled ${registeredClasses.length} native classes, '
678 '${unusedClasses.length} native classes omitted.'); 681 '${unusedClasses.length} native classes omitted.');
679 } 682 }
680 } 683 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698