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

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: Created 3 years, 7 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 /// Interface for computing all native classes in a set of libraries.
Siggi Cherem (dart-lang) 2017/04/25 19:45:53 nit: " Interface for computing ..." => " Deter
Johnni Winther 2017/04/26 07:40:19 Done.
349 abstract class NativeClassResolver { 348 abstract class NativeClassResolver {
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 NativeClassResolverImpl implements NativeClassResolver {
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 NativeClassResolverImpl(
359 this._elementEnvironment, this._commonElements, this._nativeBasicData);
360 360
361 NativeClassResolverImpl(this._resolution, this._reporter, 361 Iterable<ClassEntity> computeNativeClasses(
362 this._commonElements, this._nativeBasicData); 362 Iterable<LibraryEntity> libraries) {
363 363 Set<ClassEntity> nativeClasses = new Set<ClassEntity>();
364 Iterable<ClassElement> computeNativeClasses(
365 Iterable<LibraryElement> libraries) {
366 Set<ClassElement> nativeClasses = new Set<ClassElement>();
367 libraries.forEach((l) => _processNativeClassesInLibrary(l, nativeClasses)); 364 libraries.forEach((l) => _processNativeClassesInLibrary(l, nativeClasses));
368 if (_commonElements.isolateHelperLibrary != null) { 365 if (_commonElements.isolateHelperLibrary != null) {
369 _processNativeClassesInLibrary( 366 _processNativeClassesInLibrary(
370 _commonElements.isolateHelperLibrary, nativeClasses); 367 _commonElements.isolateHelperLibrary, nativeClasses);
371 } 368 }
372 _processSubclassesOfNativeClasses(libraries, nativeClasses); 369 _processSubclassesOfNativeClasses(libraries, nativeClasses);
373 return nativeClasses; 370 return nativeClasses;
374 } 371 }
375 372
373 /// Adds all directly native classes declared in [library] to [nativeClasses].
376 void _processNativeClassesInLibrary( 374 void _processNativeClassesInLibrary(
377 LibraryElement library, Set<ClassElement> nativeClasses) { 375 LibraryEntity library, Set<ClassEntity> nativeClasses) {
378 // Use implementation to ensure the inclusion of injected members. 376 _elementEnvironment.forEachClass(library, (ClassEntity cls) {
379 library.implementation.forEachLocalMember((Element element) { 377 if (_nativeBasicData.isNativeClass(cls)) {
380 if (element.isClass) { 378 _processNativeClass(cls, nativeClasses);
381 ClassElement cls = element;
382 if (_nativeBasicData.isNativeClass(cls)) {
383 _processNativeClass(element, nativeClasses);
384 }
385 } 379 }
386 }); 380 });
387 } 381 }
388 382
389 void _processNativeClass( 383 /// Adds [cls] to [nativeClasses] and performs further processing of [cls],
390 ClassElement classElement, Set<ClassElement> nativeClasses) { 384 /// if necessary.
391 nativeClasses.add(classElement); 385 void _processNativeClass(ClassEntity cls, Set<ClassEntity> nativeClasses) {
392 // Resolve class to ensure the class has valid inheritance info. 386 nativeClasses.add(cls);
393 classElement.ensureResolved(_resolution);
394 // Js Interop interfaces do not have tags.
395 if (_nativeBasicData.isJsInteropClass(classElement)) return;
396 // Since we map from dispatch tags to classes, a dispatch tag must be used
397 // on only one native class.
398 for (String tag in _nativeBasicData.getNativeTagsOfClass(classElement)) {
399 ClassElement owner = _tagOwner[tag];
400 if (owner != null) {
401 if (owner != classElement) {
402 _reporter.internalError(
403 classElement, "Tag '$tag' already in use by '${owner.name}'");
404 }
405 } else {
406 _tagOwner[tag] = classElement;
407 }
408 }
409 } 387 }
410 388
389 /// Returns the name of the super class of [cls] or `null` of [cls] has
390 /// no explicit superclass.
391 String _findExtendsNameOfClass(ClassEntity cls) {
392 return _elementEnvironment.getSuperClass(cls)?.name;
393 }
394
395 /// Adds all subclasses of [nativeClasses] found in [libraries] to
396 /// [nativeClasses].
411 void _processSubclassesOfNativeClasses( 397 void _processSubclassesOfNativeClasses(
412 Iterable<LibraryElement> libraries, Set<ClassElement> nativeClasses) { 398 Iterable<LibraryEntity> libraries, Set<ClassEntity> nativeClasses) {
413 Set<ClassElement> nativeClassesAndSubclasses = new Set<ClassElement>(); 399 Set<ClassEntity> nativeClassesAndSubclasses = new Set<ClassEntity>();
414 // Collect potential subclasses, e.g. 400 // Collect potential subclasses, e.g.
415 // 401 //
416 // class B extends foo.A {} 402 // class B extends foo.A {}
417 // 403 //
418 // String "A" has a potential subclass B. 404 // String "A" has a potential subclass B.
419 405
420 var potentialExtends = new Map<String, Set<ClassElement>>(); 406 Map<String, Set<ClassEntity>> potentialExtends =
407 <String, Set<ClassEntity>>{};
421 408
422 libraries.forEach((library) { 409 libraries.forEach((LibraryEntity library) {
423 library.implementation.forEachLocalMember((element) { 410 _elementEnvironment.forEachClass(library, (ClassEntity cls) {
424 if (element.isClass) { 411 String extendsName = _findExtendsNameOfClass(cls);
425 String extendsName = _findExtendsNameOfClass(element); 412 if (extendsName != null) {
426 if (extendsName != null) { 413 Set<ClassEntity> potentialSubclasses = potentialExtends.putIfAbsent(
427 Set<ClassElement> potentialSubclasses = potentialExtends 414 extendsName, () => new Set<ClassEntity>());
428 .putIfAbsent(extendsName, () => new Set<ClassElement>()); 415 potentialSubclasses.add(cls);
429 potentialSubclasses.add(element);
430 }
431 } 416 }
432 }); 417 });
433 }); 418 });
434 419
435 // Resolve all the native classes and any classes that might extend them in 420 // 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 421 // [potentialExtends], and then check that the properly resolved class is in
437 // fact a subclass of a native class. 422 // fact a subclass of a native class.
438 423
439 ClassElement nativeSuperclassOf(ClassElement classElement) { 424 ClassEntity nativeSuperclassOf(ClassEntity cls) {
440 if (_nativeBasicData.isNativeClass(classElement)) return classElement; 425 if (_nativeBasicData.isNativeClass(cls)) return cls;
441 if (classElement.superclass == null) return null; 426 ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
442 return nativeSuperclassOf(classElement.superclass); 427 if (superclass == null) return null;
428 return nativeSuperclassOf(superclass);
443 } 429 }
444 430
445 void walkPotentialSubclasses(ClassElement element) { 431 void walkPotentialSubclasses(ClassEntity element) {
446 if (nativeClassesAndSubclasses.contains(element)) return; 432 if (nativeClassesAndSubclasses.contains(element)) return;
447 element.ensureResolved(_resolution); 433 ClassEntity nativeSuperclass = nativeSuperclassOf(element);
448 ClassElement nativeSuperclass = nativeSuperclassOf(element);
449 if (nativeSuperclass != null) { 434 if (nativeSuperclass != null) {
450 nativeClassesAndSubclasses.add(element); 435 nativeClassesAndSubclasses.add(element);
451 Set<ClassElement> potentialSubclasses = potentialExtends[element.name]; 436 Set<ClassEntity> potentialSubclasses = potentialExtends[element.name];
452 if (potentialSubclasses != null) { 437 if (potentialSubclasses != null) {
453 potentialSubclasses.forEach(walkPotentialSubclasses); 438 potentialSubclasses.forEach(walkPotentialSubclasses);
454 } 439 }
455 } 440 }
456 } 441 }
457 442
458 nativeClasses.forEach(walkPotentialSubclasses); 443 nativeClasses.forEach(walkPotentialSubclasses);
459 nativeClasses.addAll(nativeClassesAndSubclasses); 444 nativeClasses.addAll(nativeClassesAndSubclasses);
460 } 445 }
446 }
447
448 /// Native class resolver that extends [NativeClassResolverImpl] to handle
449 /// unresolved classes encountered during the native classes computation.
450 class ResolutionNativeClassResolver extends NativeClassResolverImpl {
Siggi Cherem (dart-lang) 2017/04/25 19:45:53 I don't mind resolver, but another idea: rename "r
Johnni Winther 2017/04/26 07:40:19 Done.
451 final DiagnosticReporter _reporter;
452 final Resolution _resolution;
453
454 Map<String, ClassElement> _tagOwner = new Map<String, ClassElement>();
455
456 ResolutionNativeClassResolver(
457 this._resolution,
458 this._reporter,
459 ElementEnvironment elementEnvironment,
460 CommonElements commonElements,
461 NativeBasicData nativeBasicData)
462 : super(elementEnvironment, commonElements, nativeBasicData);
463
464 void _processNativeClass(
465 ClassElement classElement, Set<ClassEntity> nativeClasses) {
466 nativeClasses.add(classElement);
467 // Resolve class to ensure the class has valid inheritance info.
468 classElement.ensureResolved(_resolution);
469 // Js Interop interfaces do not have tags.
470 if (_nativeBasicData.isJsInteropClass(classElement)) return;
471 // Since we map from dispatch tags to classes, a dispatch tag must be used
472 // on only one native class.
Siggi Cherem (dart-lang) 2017/04/25 19:45:53 don't we need this validation with Kernel too?
Johnni Winther 2017/04/26 07:40:19 We do. Moved this to BaseNativeClassFinder._proces
473 for (String tag in _nativeBasicData.getNativeTagsOfClass(classElement)) {
474 ClassElement owner = _tagOwner[tag];
475 if (owner != null) {
476 if (owner != classElement) {
477 _reporter.internalError(
478 classElement, "Tag '$tag' already in use by '${owner.name}'");
479 }
480 } else {
481 _tagOwner[tag] = classElement;
482 }
483 }
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

Powered by Google App Engine
This is Rietveld 408576698