| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /// Test that the @MirrorsUsed annotation suppress hints and that only | 5 /// Test that the @MirrorsUsed annotation suppress hints and that only |
| 6 /// requested elements are retained for reflection. | 6 /// requested elements are retained for reflection. |
| 7 library dart2js.test.mirrors_used_test; | 7 library dart2js.test.mirrors_used_test; |
| 8 | 8 |
| 9 import 'package:expect/expect.dart'; | 9 import 'package:expect/expect.dart'; |
| 10 import "package:async_helper/async_helper.dart"; |
| 10 | 11 |
| 11 import 'memory_compiler.dart' show | 12 import 'memory_compiler.dart' show |
| 12 compilerFor; | 13 compilerFor; |
| 13 | 14 |
| 14 import '../../../sdk/lib/_internal/compiler/implementation/apiimpl.dart' show | 15 import '../../../sdk/lib/_internal/compiler/implementation/apiimpl.dart' show |
| 15 Compiler; | 16 Compiler; |
| 16 | 17 |
| 17 import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart' show | 18 import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart' show |
| 18 Constant, | 19 Constant, |
| 19 SourceString, | 20 SourceString, |
| 20 TypeConstant; | 21 TypeConstant; |
| 21 | 22 |
| 22 import | 23 import |
| 23 '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart' | 24 '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart' |
| 24 show | 25 show |
| 25 Elements; | 26 Elements; |
| 26 | 27 |
| 27 void expectOnlyVerboseInfo(Uri uri, int begin, int end, String message, kind) { | 28 void expectOnlyVerboseInfo(Uri uri, int begin, int end, String message, kind) { |
| 28 if (kind.name == 'verbose info') { | 29 if (kind.name == 'verbose info') { |
| 29 print(message); | 30 print(message); |
| 30 return; | 31 return; |
| 31 } | 32 } |
| 32 throw '$uri:$begin:$end: $kind: $message'; | 33 throw '$uri:$begin:$end: $kind: $message'; |
| 33 } | 34 } |
| 34 | 35 |
| 35 void main() { | 36 void main() { |
| 36 Compiler compiler = compilerFor( | 37 Compiler compiler = compilerFor( |
| 37 MEMORY_SOURCE_FILES, diagnosticHandler: expectOnlyVerboseInfo); | 38 MEMORY_SOURCE_FILES, diagnosticHandler: expectOnlyVerboseInfo); |
| 38 compiler.runCompiler(Uri.parse('memory:main.dart')); | 39 asyncTest(() => compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) { |
| 40 print(''); |
| 41 List generatedCode = |
| 42 Elements.sortedByPosition(compiler.enqueuer.codegen.generatedCode.keys); |
| 43 for (var element in generatedCode) { |
| 44 print(element); |
| 45 } |
| 46 print(''); |
| 39 | 47 |
| 40 print(''); | 48 // This assertion can fail for two reasons: |
| 41 List generatedCode = | 49 // 1. Too many elements retained for reflection. |
| 42 Elements.sortedByPosition(compiler.enqueuer.codegen.generatedCode.keys); | 50 // 2. Some code was refactored, and there are more methods. |
| 43 for (var element in generatedCode) { | 51 // Either situation could be problematic, but in situation 2, it is often |
| 44 print(element); | 52 // acceptable to increase [expectedMethodCount] a little. |
| 45 } | 53 int expectedMethodCount = 322; |
| 46 print(''); | 54 Expect.isTrue( |
| 55 generatedCode.length <= expectedMethodCount, |
| 56 'Too many compiled methods: ' |
| 57 '${generatedCode.length} > $expectedMethodCount'); |
| 47 | 58 |
| 48 // This assertion can fail for two reasons: | 59 // The following names should be retained: |
| 49 // 1. Too many elements retained for reflection. | 60 List expectedNames = [ |
| 50 // 2. Some code was refactored, and there are more methods. | 61 'Foo', // The name of class Foo. |
| 51 // Either situation could be problematic, but in situation 2, it is often | 62 r'Foo$', // The name of class Foo's constructor. |
| 52 // acceptable to increase [expectedMethodCount] a little. | 63 'Foo_staticMethod', // The name of Foo.staticMethod. |
| 53 int expectedMethodCount = 322; | 64 r'get$field', // The (getter) name of Foo.field. |
| 54 Expect.isTrue( | 65 r'instanceMethod$0']; // The name of Foo.instanceMethod. |
| 55 generatedCode.length <= expectedMethodCount, | 66 Set recordedNames = new Set() |
| 56 'Too many compiled methods: ' | 67 ..addAll(compiler.backend.emitter.recordedMangledNames) |
| 57 '${generatedCode.length} > $expectedMethodCount'); | 68 ..addAll(compiler.backend.emitter.mangledFieldNames.keys) |
| 69 ..addAll(compiler.backend.emitter.mangledGlobalFieldNames.keys); |
| 70 Expect.setEquals(new Set.from(expectedNames), recordedNames); |
| 58 | 71 |
| 59 // The following names should be retained: | 72 for (var library in compiler.libraries.values) { |
| 60 List expectedNames = [ | 73 library.forEachLocalMember((member) { |
| 61 'Foo', // The name of class Foo. | 74 if (library == compiler.mainApp |
| 62 r'Foo$', // The name of class Foo's constructor. | 75 && member.name == const SourceString('Foo')) { |
| 63 'Foo_staticMethod', // The name of Foo.staticMethod. | 76 Expect.isTrue( |
| 64 r'get$field', // The (getter) name of Foo.field. | 77 compiler.backend.isNeededForReflection(member), '$member'); |
| 65 r'instanceMethod$0']; // The name of Foo.instanceMethod. | 78 member.forEachLocalMember((classMember) { |
| 66 Set recordedNames = new Set() | 79 Expect.isTrue( |
| 67 ..addAll(compiler.backend.emitter.recordedMangledNames) | 80 compiler.backend.isNeededForReflection(classMember), |
| 68 ..addAll(compiler.backend.emitter.mangledFieldNames.keys) | 81 '$classMember'); |
| 69 ..addAll(compiler.backend.emitter.mangledGlobalFieldNames.keys); | 82 }); |
| 70 Expect.setEquals(new Set.from(expectedNames), recordedNames); | 83 } else { |
| 84 Expect.isFalse( |
| 85 compiler.backend.isNeededForReflection(member), '$member'); |
| 86 } |
| 87 }); |
| 88 } |
| 71 | 89 |
| 72 for (var library in compiler.libraries.values) { | 90 // There should at least be three metadata constants: |
| 73 library.forEachLocalMember((member) { | 91 // 1. The type literal 'Foo'. |
| 74 if (library == compiler.mainApp | 92 // 2. The list 'const [Foo]'. |
| 75 && member.name == const SourceString('Foo')) { | 93 // 3. The constructed constant for 'MirrorsUsed'. |
| 76 Expect.isTrue( | 94 Expect.isTrue(compiler.metadataHandler.compiledConstants.length >= 3); |
| 77 compiler.backend.isNeededForReflection(member), '$member'); | 95 |
| 78 member.forEachLocalMember((classMember) { | 96 // Make sure that most of the metadata constants aren't included in the |
| 79 Expect.isTrue( | 97 // generated code. |
| 80 compiler.backend.isNeededForReflection(classMember), | 98 for (Constant constant in compiler.metadataHandler.compiledConstants) { |
| 81 '$classMember'); | 99 if (constant is TypeConstant && '${constant.representedType}' == 'Foo') { |
| 82 }); | 100 // The type literal 'Foo' is retained as a constant because it is being |
| 83 } else { | 101 // passed to reflectClass. |
| 84 Expect.isFalse( | 102 continue; |
| 85 compiler.backend.isNeededForReflection(member), '$member'); | |
| 86 } | 103 } |
| 87 }); | 104 Expect.isFalse( |
| 88 } | 105 compiler.constantHandler.compiledConstants.contains(constant), |
| 106 '$constant'); |
| 107 } |
| 89 | 108 |
| 90 // There should at least be three metadata constants: | 109 // The type literal 'Foo' is both used as metadata, and as a plain value in |
| 91 // 1. The type literal 'Foo'. | 110 // the program. Make sure that it isn't duplicated. |
| 92 // 2. The list 'const [Foo]'. | 111 int fooConstantCount = 0; |
| 93 // 3. The constructed constant for 'MirrorsUsed'. | 112 for (Constant constant in compiler.metadataHandler.compiledConstants) { |
| 94 Expect.isTrue(compiler.metadataHandler.compiledConstants.length >= 3); | 113 if (constant is TypeConstant && '${constant.representedType}' == 'Foo') { |
| 95 | 114 fooConstantCount++; |
| 96 // Make sure that most of the metadata constants aren't included in the | 115 } |
| 97 // generated code. | |
| 98 for (Constant constant in compiler.metadataHandler.compiledConstants) { | |
| 99 if (constant is TypeConstant && '${constant.representedType}' == 'Foo') { | |
| 100 // The type literal 'Foo' is retained as a constant because it is being | |
| 101 // passed to reflectClass. | |
| 102 continue; | |
| 103 } | 116 } |
| 104 Expect.isFalse( | 117 Expect.equals( |
| 105 compiler.constantHandler.compiledConstants.contains(constant), | 118 1, fooConstantCount, |
| 106 '$constant'); | 119 "The type literal 'Foo' is duplicated or missing."); |
| 107 } | 120 })); |
| 108 | |
| 109 // The type literal 'Foo' is both used as metadata, and as a plain value in | |
| 110 // the program. Make sure that it isn't duplicated. | |
| 111 int fooConstantCount = 0; | |
| 112 for (Constant constant in compiler.metadataHandler.compiledConstants) { | |
| 113 if (constant is TypeConstant && '${constant.representedType}' == 'Foo') { | |
| 114 fooConstantCount++; | |
| 115 } | |
| 116 } | |
| 117 Expect.equals( | |
| 118 1, fooConstantCount, "The type literal 'Foo' is duplicated or missing."); | |
| 119 } | 121 } |
| 120 | 122 |
| 121 const MEMORY_SOURCE_FILES = const <String, String> { | 123 const MEMORY_SOURCE_FILES = const <String, String> { |
| 122 'main.dart': """ | 124 'main.dart': """ |
| 123 @MirrorsUsed(targets: const [Foo], override: '*') | 125 @MirrorsUsed(targets: const [Foo], override: '*') |
| 124 import 'dart:mirrors'; | 126 import 'dart:mirrors'; |
| 125 | 127 |
| 126 import 'library.dart'; | 128 import 'library.dart'; |
| 127 | 129 |
| 128 class Foo { | 130 class Foo { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 142 library lib; | 144 library lib; |
| 143 | 145 |
| 144 import 'dart:mirrors'; | 146 import 'dart:mirrors'; |
| 145 | 147 |
| 146 useReflect(type) { | 148 useReflect(type) { |
| 147 print(new Symbol('Foo')); | 149 print(new Symbol('Foo')); |
| 148 print(MirrorSystem.getName(reflectClass(type).owner.qualifiedName)); | 150 print(MirrorSystem.getName(reflectClass(type).owner.qualifiedName)); |
| 149 } | 151 } |
| 150 """, | 152 """, |
| 151 }; | 153 }; |
| OLD | NEW |