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

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

Issue 2836993003: Handle instantiation of native classes in closed_world2_test (Closed)
Patch Set: Fixes 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
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 import 'package:front_end/src/fasta/scanner.dart' 5 import 'package:front_end/src/fasta/scanner.dart'
6 show BeginGroupToken, StringToken, Token; 6 show BeginGroupToken, StringToken, Token;
7 import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN; 7 import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN;
8 8
9 import '../common.dart'; 9 import '../common.dart';
10 import '../common_elements.dart' show CommonElements; 10 import '../common_elements.dart' show CommonElements, ElementEnvironment;
11 import '../common/backend_api.dart'; 11 import '../common/backend_api.dart';
12 import '../common/resolution.dart'; 12 import '../common/resolution.dart';
13 import '../compiler.dart' show Compiler; 13 import '../compiler.dart' show Compiler;
14 import '../constants/values.dart'; 14 import '../constants/values.dart';
15 import '../elements/elements.dart' 15 import '../elements/elements.dart'
16 show 16 show
17 ClassElement, 17 ClassElement,
18 Element, 18 Element,
19 FieldElement, 19 FieldElement,
20 LibraryElement,
21 MemberElement, 20 MemberElement,
22 MetadataAnnotation, 21 MetadataAnnotation,
23 MethodElement; 22 MethodElement;
24 import '../elements/entities.dart'; 23 import '../elements/entities.dart';
25 import '../elements/modelx.dart' show FunctionElementX, MetadataAnnotationX; 24 import '../elements/modelx.dart' show FunctionElementX, MetadataAnnotationX;
26 import '../elements/resolution_types.dart' show ResolutionDartType; 25 import '../elements/resolution_types.dart' show ResolutionDartType;
27 import '../js_backend/js_backend.dart'; 26 import '../js_backend/js_backend.dart';
28 import '../js_backend/native_data.dart'; 27 import '../js_backend/native_data.dart';
29 import '../patch_parser.dart'; 28 import '../patch_parser.dart';
30 import '../tree/tree.dart'; 29 import '../tree/tree.dart';
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 ResolutionDartType type = constant.getType(compiler.commonElements); 337 ResolutionDartType type = constant.getType(compiler.commonElements);
339 if (type.element != compiler.commonElements.jsAnnotationClass) { 338 if (type.element != compiler.commonElements.jsAnnotationClass) {
340 compiler.reporter 339 compiler.reporter
341 .internalError(annotation, 'Invalid @JS(...) annotation.'); 340 .internalError(annotation, 'Invalid @JS(...) annotation.');
342 } 341 }
343 } 342 }
344 343
345 bool get defaultResult => false; 344 bool get defaultResult => false;
346 } 345 }
347 346
348 /// Interface for computing all native classes in a set of libraries. 347 /// Determines all native classes in a set of libraries.
349 abstract class NativeClassResolver { 348 abstract class NativeClassFinder {
349 /// Returns the set of all native classes declared in [libraries].
350 Iterable<ClassEntity> computeNativeClasses(Iterable<LibraryEntity> libraries); 350 Iterable<ClassEntity> computeNativeClasses(Iterable<LibraryEntity> libraries);
351 } 351 }
352 352
353 class NativeClassResolverImpl implements NativeClassResolver { 353 class BaseNativeClassFinder implements NativeClassFinder {
354 final DiagnosticReporter _reporter; 354 final ElementEnvironment _elementEnvironment;
355 final Resolution _resolution;
356 final CommonElements _commonElements; 355 final CommonElements _commonElements;
357 final NativeBasicData _nativeBasicData; 356 final NativeBasicData _nativeBasicData;
358 357
359 Map<String, ClassElement> _tagOwner = new Map<String, ClassElement>(); 358 Map<String, ClassEntity> _tagOwner = new Map<String, ClassEntity>();
360 359
361 NativeClassResolverImpl(this._resolution, this._reporter, 360 BaseNativeClassFinder(
362 this._commonElements, this._nativeBasicData); 361 this._elementEnvironment, this._commonElements, this._nativeBasicData);
363 362
364 Iterable<ClassElement> computeNativeClasses( 363 Iterable<ClassEntity> computeNativeClasses(
365 Iterable<LibraryElement> libraries) { 364 Iterable<LibraryEntity> libraries) {
366 Set<ClassElement> nativeClasses = new Set<ClassElement>(); 365 Set<ClassEntity> nativeClasses = new Set<ClassEntity>();
367 libraries.forEach((l) => _processNativeClassesInLibrary(l, nativeClasses)); 366 libraries.forEach((l) => _processNativeClassesInLibrary(l, nativeClasses));
368 if (_commonElements.isolateHelperLibrary != null) { 367 if (_commonElements.isolateHelperLibrary != null) {
369 _processNativeClassesInLibrary( 368 _processNativeClassesInLibrary(
370 _commonElements.isolateHelperLibrary, nativeClasses); 369 _commonElements.isolateHelperLibrary, nativeClasses);
371 } 370 }
372 _processSubclassesOfNativeClasses(libraries, nativeClasses); 371 _processSubclassesOfNativeClasses(libraries, nativeClasses);
373 return nativeClasses; 372 return nativeClasses;
374 } 373 }
375 374
375 /// Adds all directly native classes declared in [library] to [nativeClasses].
376 void _processNativeClassesInLibrary( 376 void _processNativeClassesInLibrary(
377 LibraryElement library, Set<ClassElement> nativeClasses) { 377 LibraryEntity library, Set<ClassEntity> nativeClasses) {
378 // Use implementation to ensure the inclusion of injected members. 378 _elementEnvironment.forEachClass(library, (ClassEntity cls) {
379 library.implementation.forEachLocalMember((Element element) { 379 if (_nativeBasicData.isNativeClass(cls)) {
380 if (element.isClass) { 380 _processNativeClass(cls, nativeClasses);
381 ClassElement cls = element;
382 if (_nativeBasicData.isNativeClass(cls)) {
383 _processNativeClass(element, nativeClasses);
384 }
385 } 381 }
386 }); 382 });
387 } 383 }
388 384
389 void _processNativeClass( 385 /// Adds [cls] to [nativeClasses] and performs further processing of [cls],
390 ClassElement classElement, Set<ClassElement> nativeClasses) { 386 /// if necessary.
391 nativeClasses.add(classElement); 387 void _processNativeClass(ClassEntity cls, Set<ClassEntity> nativeClasses) {
392 // Resolve class to ensure the class has valid inheritance info. 388 nativeClasses.add(cls);
393 classElement.ensureResolved(_resolution);
394 // Js Interop interfaces do not have tags. 389 // Js Interop interfaces do not have tags.
395 if (_nativeBasicData.isJsInteropClass(classElement)) return; 390 if (_nativeBasicData.isJsInteropClass(cls)) return;
396 // Since we map from dispatch tags to classes, a dispatch tag must be used 391 // Since we map from dispatch tags to classes, a dispatch tag must be used
397 // on only one native class. 392 // on only one native class.
398 for (String tag in _nativeBasicData.getNativeTagsOfClass(classElement)) { 393 for (String tag in _nativeBasicData.getNativeTagsOfClass(cls)) {
399 ClassElement owner = _tagOwner[tag]; 394 ClassEntity owner = _tagOwner[tag];
400 if (owner != null) { 395 if (owner != null) {
401 if (owner != classElement) { 396 if (owner != cls) {
402 _reporter.internalError( 397 throw new SpannableAssertionFailure(
403 classElement, "Tag '$tag' already in use by '${owner.name}'"); 398 cls, "Tag '$tag' already in use by '${owner.name}'");
404 } 399 }
405 } else { 400 } else {
406 _tagOwner[tag] = classElement; 401 _tagOwner[tag] = cls;
407 } 402 }
408 } 403 }
409 } 404 }
410 405
406 /// Returns the name of the super class of [cls] or `null` of [cls] has
407 /// no explicit superclass.
408 String _findExtendsNameOfClass(ClassEntity cls) {
409 return _elementEnvironment.getSuperClass(cls)?.name;
410 }
411
412 /// Adds all subclasses of [nativeClasses] found in [libraries] to
413 /// [nativeClasses].
411 void _processSubclassesOfNativeClasses( 414 void _processSubclassesOfNativeClasses(
412 Iterable<LibraryElement> libraries, Set<ClassElement> nativeClasses) { 415 Iterable<LibraryEntity> libraries, Set<ClassEntity> nativeClasses) {
413 Set<ClassElement> nativeClassesAndSubclasses = new Set<ClassElement>(); 416 Set<ClassEntity> nativeClassesAndSubclasses = new Set<ClassEntity>();
414 // Collect potential subclasses, e.g. 417 // Collect potential subclasses, e.g.
415 // 418 //
416 // class B extends foo.A {} 419 // class B extends foo.A {}
417 // 420 //
418 // String "A" has a potential subclass B. 421 // String "A" has a potential subclass B.
419 422
420 var potentialExtends = new Map<String, Set<ClassElement>>(); 423 Map<String, Set<ClassEntity>> potentialExtends =
424 <String, Set<ClassEntity>>{};
421 425
422 libraries.forEach((library) { 426 libraries.forEach((LibraryEntity library) {
423 library.implementation.forEachLocalMember((element) { 427 _elementEnvironment.forEachClass(library, (ClassEntity cls) {
424 if (element.isClass) { 428 String extendsName = _findExtendsNameOfClass(cls);
425 String extendsName = _findExtendsNameOfClass(element); 429 if (extendsName != null) {
426 if (extendsName != null) { 430 Set<ClassEntity> potentialSubclasses = potentialExtends.putIfAbsent(
427 Set<ClassElement> potentialSubclasses = potentialExtends 431 extendsName, () => new Set<ClassEntity>());
428 .putIfAbsent(extendsName, () => new Set<ClassElement>()); 432 potentialSubclasses.add(cls);
429 potentialSubclasses.add(element);
430 }
431 } 433 }
432 }); 434 });
433 }); 435 });
434 436
435 // Resolve all the native classes and any classes that might extend them in 437 // Resolve all the native classes and any classes that might extend them in
436 // [potentialExtends], and then check that the properly resolved class is in 438 // [potentialExtends], and then check that the properly resolved class is in
437 // fact a subclass of a native class. 439 // fact a subclass of a native class.
438 440
439 ClassElement nativeSuperclassOf(ClassElement classElement) { 441 ClassEntity nativeSuperclassOf(ClassEntity cls) {
440 if (_nativeBasicData.isNativeClass(classElement)) return classElement; 442 if (_nativeBasicData.isNativeClass(cls)) return cls;
441 if (classElement.superclass == null) return null; 443 ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
442 return nativeSuperclassOf(classElement.superclass); 444 if (superclass == null) return null;
445 return nativeSuperclassOf(superclass);
443 } 446 }
444 447
445 void walkPotentialSubclasses(ClassElement element) { 448 void walkPotentialSubclasses(ClassEntity element) {
446 if (nativeClassesAndSubclasses.contains(element)) return; 449 if (nativeClassesAndSubclasses.contains(element)) return;
447 element.ensureResolved(_resolution); 450 ClassEntity nativeSuperclass = nativeSuperclassOf(element);
448 ClassElement nativeSuperclass = nativeSuperclassOf(element);
449 if (nativeSuperclass != null) { 451 if (nativeSuperclass != null) {
450 nativeClassesAndSubclasses.add(element); 452 nativeClassesAndSubclasses.add(element);
451 Set<ClassElement> potentialSubclasses = potentialExtends[element.name]; 453 Set<ClassEntity> potentialSubclasses = potentialExtends[element.name];
452 if (potentialSubclasses != null) { 454 if (potentialSubclasses != null) {
453 potentialSubclasses.forEach(walkPotentialSubclasses); 455 potentialSubclasses.forEach(walkPotentialSubclasses);
454 } 456 }
455 } 457 }
456 } 458 }
457 459
458 nativeClasses.forEach(walkPotentialSubclasses); 460 nativeClasses.forEach(walkPotentialSubclasses);
459 nativeClasses.addAll(nativeClassesAndSubclasses); 461 nativeClasses.addAll(nativeClassesAndSubclasses);
460 } 462 }
463 }
464
465 /// Native class finder that extends [BaseNativeClassFinder] to handle
466 /// unresolved classes encountered during the native classes computation.
467 class ResolutionNativeClassFinder extends BaseNativeClassFinder {
468 final DiagnosticReporter _reporter;
469 final Resolution _resolution;
470
471 ResolutionNativeClassFinder(
472 this._resolution,
473 this._reporter,
474 ElementEnvironment elementEnvironment,
475 CommonElements commonElements,
476 NativeBasicData nativeBasicData)
477 : super(elementEnvironment, commonElements, nativeBasicData);
478
479 void _processNativeClass(
480 ClassElement classElement, Set<ClassEntity> nativeClasses) {
481 // Resolve class to ensure the class has valid inheritance info.
482 classElement.ensureResolved(_resolution);
483 super._processNativeClass(classElement, nativeClasses);
484 }
461 485
462 /** 486 /**
463 * Returns the source string of the class named in the extends clause, or 487 * Returns the source string of the class named in the extends clause, or
464 * `null` if there is no extends clause. 488 * `null` if there is no extends clause.
465 */ 489 */
466 String _findExtendsNameOfClass(ClassElement classElement) { 490 String _findExtendsNameOfClass(ClassElement classElement) {
467 if (classElement.isResolved) { 491 if (classElement.isResolved) {
468 ClassElement superClass = classElement.superclass; 492 ClassElement superClass = classElement.superclass;
469 while (superClass != null) { 493 while (superClass != null) {
470 if (!superClass.isUnnamedMixinApplication) { 494 if (!superClass.isUnnamedMixinApplication) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 564
541 Iterable<ConstantValue> fields = constructedObject.fields.values; 565 Iterable<ConstantValue> fields = constructedObject.fields.values;
542 // TODO(sra): Better validation of the constant. 566 // TODO(sra): Better validation of the constant.
543 if (fields.length != 1 || fields.single is! StringConstantValue) { 567 if (fields.length != 1 || fields.single is! StringConstantValue) {
544 throw new SpannableAssertionFailure( 568 throw new SpannableAssertionFailure(
545 spannable, 'Annotations needs one string: ${value.toStructuredText()}'); 569 spannable, 'Annotations needs one string: ${value.toStructuredText()}');
546 } 570 }
547 StringConstantValue specStringConstant = fields.single; 571 StringConstantValue specStringConstant = fields.single;
548 return specStringConstant.toDartString().slowToString(); 572 return specStringConstant.toDartString().slowToString();
549 } 573 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/native/enqueue.dart ('k') | pkg/compiler/lib/src/resolution/resolution_strategy.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698