[cfe] Support patching of extension methods

Change-Id: I453e17e63f97a0ca2477371541c6a9602bee2404
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/119322
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther
2019-09-30 09:51:31 +00:00
committed by commit-bot@chromium.org
parent bb600e99e2
commit dd028547ce
27 changed files with 525 additions and 54 deletions
@@ -26,7 +26,9 @@ class MemoryFileSystem implements FileSystem {
Uri currentDirectory;
MemoryFileSystem(Uri currentDirectory)
: currentDirectory = _addTrailingSlash(currentDirectory);
: currentDirectory = _addTrailingSlash(currentDirectory) {
_directories.add(currentDirectory);
}
@override
MemoryFileSystemEntity entityForUri(Uri uri) {
+6
View File
@@ -0,0 +1,6 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// If `true`, data that would not otherwise be kept is stored for testing.
bool retainDataForTesting = false;
@@ -53,6 +53,8 @@ import 'package:kernel/type_algebra.dart' as type_algebra
import 'package:kernel/type_environment.dart' show TypeEnvironment;
import '../../base/common.dart';
import '../dill/dill_member_builder.dart' show DillMemberBuilder;
import 'builder.dart'
@@ -166,6 +168,8 @@ abstract class ClassBuilder extends DeclarationBuilder {
ClassBuilder actualOrigin;
ClassBuilder patchForTesting;
ClassBuilder(
List<MetadataBuilder> metadata,
int modifiers,
@@ -1523,6 +1527,9 @@ abstract class ClassBuilder extends DeclarationBuilder {
void applyPatch(Builder patch) {
if (patch is ClassBuilder) {
patch.actualOrigin = this;
if (retainDataForTesting) {
patchForTesting = patch;
}
// TODO(ahe): Complain if `patch.supertype` isn't null.
scope.local.forEach((String name, Builder member) {
Builder memberPatch = patch.scope.local[name];
@@ -74,5 +74,6 @@ abstract class ModifierBuilder extends Builder {
return buffer..write(name ?? fullNameForErrors);
}
String toString() => "$debugName(${printOn(new StringBuffer())})";
String toString() =>
"${isPatch ? 'patch ' : ''}$debugName(${printOn(new StringBuffer())})";
}
@@ -11,6 +11,8 @@ import 'package:kernel/ast.dart' hide Variance;
import 'package:kernel/type_algebra.dart';
import '../../base/common.dart';
import 'builder.dart'
show
Builder,
@@ -459,6 +461,7 @@ class ProcedureBuilder extends FunctionBuilder {
final Procedure _procedure;
final int charOpenParenOffset;
final ProcedureKind kind;
ProcedureBuilder patchForTesting;
AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
@@ -553,8 +556,8 @@ class ProcedureBuilder extends FunctionBuilder {
_procedure.isConst = isConst;
if (isExtensionMethod) {
ExtensionBuilder extensionBuilder = parent;
procedure.isExtensionMember = true;
procedure.isStatic = true;
_procedure.isExtensionMember = true;
_procedure.isStatic = true;
String kindInfix = '';
if (isExtensionInstanceMember) {
// Instance getter and setter are converted to methods so we use an
@@ -574,18 +577,18 @@ class ProcedureBuilder extends FunctionBuilder {
throw new UnsupportedError(
'Unexpected extension method kind ${kind}');
}
procedure.kind = ProcedureKind.Method;
_procedure.kind = ProcedureKind.Method;
}
procedure.name = new Name(
_procedure.name = new Name(
'${extensionBuilder.name}|${kindInfix}${name}',
libraryBuilder.library);
} else {
_procedure.isStatic = isStatic;
_procedure.name = new Name(name, libraryBuilder.library);
}
}
if (extensionTearOff != null) {
_buildExtensionTearOff(libraryBuilder, parent);
if (extensionTearOff != null) {
_buildExtensionTearOff(libraryBuilder, parent);
}
}
return _procedure;
}
@@ -698,7 +701,7 @@ class ProcedureBuilder extends FunctionBuilder {
Statement closureBody = new ReturnStatement(
new StaticInvocation(
procedure,
_procedure,
new Arguments(closurePositionalArguments,
types: typeArguments, named: closureNamedArguments))
..fileOffset = fileOffset)
@@ -709,10 +712,10 @@ class ProcedureBuilder extends FunctionBuilder {
typeParameters: closureTypeParameters,
positionalParameters: closurePositionalParameters,
namedParameters: closureNamedParameters,
requiredParameterCount: procedure.function.requiredParameterCount - 1,
requiredParameterCount: _procedure.function.requiredParameterCount - 1,
returnType: closureReturnType,
asyncMarker: procedure.function.asyncMarker,
dartAsyncMarker: procedure.function.dartAsyncMarker))
asyncMarker: _procedure.function.asyncMarker,
dartAsyncMarker: _procedure.function.dartAsyncMarker))
..fileOffset = fileOffset;
_extensionTearOff
@@ -783,6 +786,9 @@ class ProcedureBuilder extends FunctionBuilder {
if (patch is ProcedureBuilder) {
if (checkPatch(patch)) {
patch.actualOrigin = this;
if (retainDataForTesting) {
patchForTesting = patch;
}
}
} else {
reportPatchMismatch(patch);
@@ -807,6 +813,8 @@ class ConstructorBuilder extends FunctionBuilder {
@override
ConstructorBuilder actualOrigin;
ConstructorBuilder patchForTesting;
Constructor get actualConstructor => _constructor;
ConstructorBuilder(
@@ -998,6 +1006,9 @@ class ConstructorBuilder extends FunctionBuilder {
if (patch is ConstructorBuilder) {
if (checkPatch(patch)) {
patch.actualOrigin = this;
if (retainDataForTesting) {
patchForTesting = patch;
}
}
} else {
reportPatchMismatch(patch);
@@ -26,7 +26,7 @@ class DillExtensionMemberBuilder extends DillMemberBuilder {
bool get isStatic => _descriptor.isStatic;
@override
bool get isExternal => _descriptor.isExternal;
bool get isExternal => member.isExternal;
@override
Procedure get procedure {
@@ -3444,7 +3444,7 @@ class Parser {
beforeInitializers?.next, token);
break;
case DeclarationKind.Extension:
if (optional(';', bodyStart)) {
if (optional(';', bodyStart) && externalToken == null) {
reportRecoverableError(isOperator ? name.next : name,
fasta.messageExtensionDeclaresAbstractMember);
}
@@ -4,6 +4,7 @@
import 'dart:core' hide MapEntry;
import 'package:kernel/ast.dart';
import '../../base/common.dart';
import '../builder/declaration.dart';
import '../builder/extension_builder.dart';
import '../builder/library_builder.dart';
@@ -12,22 +13,25 @@ import '../builder/procedure_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_variable_builder.dart';
import '../scope.dart';
import 'source_library_builder.dart';
import '../kernel/kernel_builder.dart';
import '../problems.dart';
import '../fasta_codes.dart'
show
messagePatchDeclarationMismatch,
messagePatchDeclarationOrigin,
noLength,
templateConflictsWithMember,
templateConflictsWithMemberWarning,
templateConflictsWithSetter,
templateConflictsWithSetterWarning;
import 'source_library_builder.dart';
class SourceExtensionBuilder extends ExtensionBuilder {
final Extension _extension;
SourceExtensionBuilder _origin;
SourceExtensionBuilder patchForTesting;
SourceExtensionBuilder(
List<MetadataBuilder> metadata,
int modifiers,
@@ -48,7 +52,10 @@ class SourceExtensionBuilder extends ExtensionBuilder {
super(metadata, modifiers, name, parent, nameOffset, scope,
typeParameters, onType);
Extension get extension => _extension;
@override
SourceExtensionBuilder get origin => _origin ?? this;
Extension get extension => isPatch ? origin._extension : _extension;
/// Builds the [Extension] for this extension build and inserts the members
/// into the [Library] of [libraryBuilder].
@@ -75,7 +82,7 @@ class SourceExtensionBuilder extends ExtensionBuilder {
Field field = declaration.build(libraryBuilder);
if (addMembersToLibrary && declaration.next == null) {
libraryBuilder.library.addMember(field);
_extension.members.add(new ExtensionMemberDescriptor(
extension.members.add(new ExtensionMemberDescriptor(
name: new Name(declaration.name, libraryBuilder.library),
member: field.reference,
isStatic: declaration.isStatic,
@@ -83,7 +90,9 @@ class SourceExtensionBuilder extends ExtensionBuilder {
}
} else if (declaration is ProcedureBuilder) {
Member function = declaration.build(libraryBuilder);
if (addMembersToLibrary && declaration.next == null) {
if (addMembersToLibrary &&
!declaration.isPatch &&
declaration.next == null) {
libraryBuilder.library.addMember(function);
ExtensionMemberKind kind;
switch (declaration.kind) {
@@ -103,11 +112,10 @@ class SourceExtensionBuilder extends ExtensionBuilder {
unsupported("Extension method kind: ${declaration.kind}",
declaration.charOffset, declaration.fileUri);
}
_extension.members.add(new ExtensionMemberDescriptor(
extension.members.add(new ExtensionMemberDescriptor(
name: new Name(declaration.name, libraryBuilder.library),
member: function.reference,
isStatic: declaration.isStatic,
isExternal: declaration.isExternal,
kind: kind));
Procedure tearOff = declaration.extensionTearOff;
if (tearOff != null) {
@@ -116,7 +124,6 @@ class SourceExtensionBuilder extends ExtensionBuilder {
name: new Name(declaration.name, libraryBuilder.library),
member: tearOff.reference,
isStatic: false,
isExternal: false,
kind: ExtensionMemberKind.TearOff));
}
}
@@ -157,4 +164,46 @@ class SourceExtensionBuilder extends ExtensionBuilder {
return _extension;
}
@override
void applyPatch(Builder patch) {
if (patch is SourceExtensionBuilder) {
patch._origin = this;
if (retainDataForTesting) {
patchForTesting = patch;
}
scope.local.forEach((String name, Builder member) {
Builder memberPatch = patch.scope.local[name];
if (memberPatch != null) {
member.applyPatch(memberPatch);
}
});
scope.setters.forEach((String name, Builder member) {
Builder memberPatch = patch.scope.setters[name];
if (memberPatch != null) {
member.applyPatch(memberPatch);
}
});
// TODO(johnniwinther): Check that type parameters and on-type match
// with origin declaration.
} else {
library.addProblem(messagePatchDeclarationMismatch, patch.charOffset,
noLength, patch.fileUri, context: [
messagePatchDeclarationOrigin.withLocation(
fileUri, charOffset, noLength)
]);
}
}
@override
int finishPatch() {
if (!isPatch) return 0;
int count = 0;
scope.forEach((String name, Builder declaration) {
count += declaration.finishPatch();
});
return count;
}
}
@@ -61,9 +61,8 @@ abstract class DataExtractor<T> extends Visitor with DataRegistry<T> {
DataExtractor(this.actualMap);
void computeForLibrary(Library library, {bool useFileUri: false}) {
LibraryId id =
new LibraryId(useFileUri ? library.fileUri : library.importUri);
void computeForLibrary(Library library) {
LibraryId id = new LibraryId(library.fileUri);
T value = computeLibraryValue(id, library);
registerValue(library.fileUri, null, id, value, library);
}
@@ -214,6 +214,8 @@ TestData computeTestData(FileSystemEntity testFile,
entry;
}
}
assert(
mainTestFile != null, "No 'main.dart' test file found for $testFile.");
}
String annotatedCode = new File.fromUri(mainTestFile.uri).readAsStringSync();
@@ -8,6 +8,7 @@ import '../api_prototype/compiler_options.dart'
import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
import '../api_prototype/terminal_color_support.dart'
show printDiagnosticMessage;
import '../base/common.dart';
import '../fasta/messages.dart' show FormattedMessage;
import '../fasta/severity.dart' show Severity;
import '../kernel_generator_impl.dart' show InternalCompilerResult;
@@ -42,8 +43,10 @@ class TestConfig {
final String marker;
final String name;
final Map<ExperimentalFlag, bool> experimentalFlags;
final Uri librariesSpecificationUri;
const TestConfig(this.marker, this.name, {this.experimentalFlags = const {}});
const TestConfig(this.marker, this.name,
{this.experimentalFlags = const {}, this.librariesSpecificationUri});
void customizeCompilerOptions(CompilerOptions options) {}
}
@@ -180,6 +183,7 @@ void onFailure(String message) => throw new StateError(message);
/// Creates a test runner for [dataComputer] on [testedConfigs].
RunTestFunction runTestFor<T>(
DataComputer<T> dataComputer, List<TestConfig> testedConfigs) {
retainDataForTesting = true;
return (TestData testData,
{bool testAfterFailures, bool verbose, bool succinct, bool printCode}) {
return runTest(testData, dataComputer, testedConfigs,
@@ -242,6 +246,13 @@ Future<bool> runTestForConfig<T>(
};
options.debugDump = printCode;
options.experimentalFlags.addAll(config.experimentalFlags);
if (config.librariesSpecificationUri != null) {
Set<Uri> testFiles =
testData.memorySourceFiles.keys.map(createUriForFileName).toSet();
if (testFiles.contains(config.librariesSpecificationUri)) {
options.librariesSpecificationUri = config.librariesSpecificationUri;
}
}
config.customizeCompilerOptions(options);
InternalCompilerResult compilerResult = await compileScript(
testData.memorySourceFiles,
@@ -62,7 +62,7 @@ Extension lookupExtension(Library library, String extensionName,
(Extension extension) => extension.name == extensionName, orElse: () {
if (required) {
throw new ArgumentError(
"Extension '$extensionName' not found in '$library'.");
"Extension '$extensionName' not found in '${library.importUri}'.");
}
return null;
});
@@ -151,7 +151,7 @@ MemberBuilder lookupClassMemberBuilder(InternalCompilerResult compilerResult,
lookupClassBuilder(compilerResult, cls, required: required);
MemberBuilder memberBuilder;
if (classBuilder != null) {
if (member is Constructor) {
if (member is Constructor || member is Procedure && member.isFactory) {
memberBuilder = classBuilder.constructors.local[memberName];
} else if (member is Procedure && member.isSetter) {
memberBuilder = classBuilder.scope.setters[memberName];
@@ -527,9 +527,6 @@ String errorsToText(List<FormattedMessage> errors) {
/// Returns a textual representation of [descriptor] to be used in testing.
String extensionMethodDescriptorToText(ExtensionMemberDescriptor descriptor) {
StringBuffer sb = new StringBuffer();
if (descriptor.isExternal) {
sb.write('external ');
}
if (descriptor.isStatic) {
sb.write('static ');
}
@@ -0,0 +1,30 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/*library: scope=[Extension1]*/
/*class: Extension1:
builder-name=Extension1,
builder-onType=String,
extension-members=[
method1=Extension1|method1,
tearoff method1=Extension1|get#method1],
extension-name=Extension1,
extension-onType=String
*/
extension Extension1 on String {
/*member: Extension1|method1:
builder-name=method1,
builder-params=[#this],
member-name=Extension1|method1,
member-params=[#this]
*/
method1() {}
/*member: Extension1|get#method1:
builder-name=method1,
builder-params=[#this],
member-name=Extension1|get#method1,
member-params=[#this]*/
}
@@ -0,0 +1,9 @@
{
"none": {
"libraries": {
"test": {
"uri": "origin.dart"
}
}
}
}
@@ -0,0 +1,20 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/*library: scope=[lib.dart.Extension1,origin.dart.Extension2]*/
import 'lib.dart' as lib1;
import 'lib.dart' show Extension1;
// ignore: uri_does_not_exist
import 'dart:test' as lib2;
// ignore: uri_does_not_exist
import 'dart:test' show Extension2;
main() {
"".method1();
Extension1("").method1();
"".method2();
Extension2("").method2();
}
@@ -0,0 +1,30 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/*library: scope=[Extension2]*/
/*class: Extension2:
builder-name=Extension2,
builder-onType=String,
extension-members=[
method2=Extension2|method2,
tearoff method2=Extension2|get#method2],
extension-name=Extension2,
extension-onType=String
*/
extension Extension2 on String {
/*member: Extension2|method2:
builder-name=method2,
builder-params=[#this],
member-name=Extension2|method2,
member-params=[#this]
*/
method2() {}
/*member: Extension2|get#method2:
builder-name=method2,
builder-params=[#this],
member-name=Extension2|get#method2,
member-params=[#this]*/
}
@@ -0,0 +1,12 @@
{
"none": {
"libraries": {
"test": {
"patches": [
"patch.dart"
],
"uri": "origin.dart"
}
}
}
}
@@ -0,0 +1,23 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/*library: scope=[origin.dart.Extension,origin.dart.GenericExtension]*/
// ignore: uri_does_not_exist
import 'dart:test';
main() {
"".instanceMethod();
"".genericInstanceMethod<int>(0);
"".instanceProperty = "".instanceProperty;
Extension.staticMethod();
Extension.genericStaticMethod<int>(0);
Extension.staticProperty = Extension.staticProperty;
true.instanceMethod();
true.genericInstanceMethod<int>(0);
true.instanceProperty = true.instanceProperty;
GenericExtension.staticMethod();
GenericExtension.genericStaticMethod<int>(0);
GenericExtension.staticProperty = GenericExtension.staticProperty;
}
@@ -0,0 +1,108 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/*library: scope=[Extension,GenericExtension]*/
/*class: Extension:
builder-name=Extension,
builder-onType=String,
extension-members=[
genericInstanceMethod=Extension|genericInstanceMethod,
getter instanceProperty=Extension|get#instanceProperty,
instanceMethod=Extension|instanceMethod,
setter instanceProperty=Extension|set#instanceProperty,
static genericStaticMethod=Extension|genericStaticMethod,
static getter staticProperty=Extension|staticProperty,
static setter staticProperty=Extension|staticProperty=,
static staticMethod=Extension|staticMethod,
tearoff genericInstanceMethod=Extension|get#genericInstanceMethod,
tearoff instanceMethod=Extension|get#instanceMethod,
],
extension-name=Extension,
extension-onType=String
*/
extension Extension on String {
/*member: Extension|get#instanceMethod:
builder-name=instanceMethod,
builder-params=[#this],
member-name=Extension|get#instanceMethod,
member-params=[#this]
*/
external int instanceMethod();
/*member: Extension|get#genericInstanceMethod:
builder-name=genericInstanceMethod,
builder-params=[#this,t],
builder-type-params=[T],
member-name=Extension|get#genericInstanceMethod,
member-params=[#this]
*/
external T genericInstanceMethod<T>(T t);
external static int staticMethod();
external static T genericStaticMethod<T>(T t);
external int get instanceProperty;
external void set instanceProperty(int value);
external static int get staticProperty;
external static void set staticProperty(int value);
}
/*class: GenericExtension:
builder-name=GenericExtension,
builder-onType=T,
builder-type-params=[T],
extension-members=[
genericInstanceMethod=GenericExtension|genericInstanceMethod,
getter instanceProperty=GenericExtension|get#instanceProperty,
instanceMethod=GenericExtension|instanceMethod,
setter instanceProperty=GenericExtension|set#instanceProperty,
static genericStaticMethod=GenericExtension|genericStaticMethod,
static getter staticProperty=GenericExtension|staticProperty,
static setter staticProperty=GenericExtension|staticProperty=,
static staticMethod=GenericExtension|staticMethod,
tearoff genericInstanceMethod=GenericExtension|get#genericInstanceMethod,
tearoff instanceMethod=GenericExtension|get#instanceMethod
],
extension-name=GenericExtension,
extension-onType=T,
extension-type-params=[T]
*/
extension GenericExtension<T> on T {
/*member: GenericExtension|get#instanceMethod:
builder-name=instanceMethod,
builder-params=[#this],
builder-type-params=[T],
member-name=GenericExtension|get#instanceMethod,
member-params=[#this],
member-type-params=[T]
*/
external int instanceMethod();
/*member: GenericExtension|get#genericInstanceMethod:
builder-name=genericInstanceMethod,
builder-params=[#this,t],
builder-type-params=[T,T],
member-name=GenericExtension|get#genericInstanceMethod,
member-params=[#this],
member-type-params=[#T]
*/
external T genericInstanceMethod<T>(T t);
external static int staticMethod();
external static T genericStaticMethod<T>(T t);
external int get instanceProperty;
external void set instanceProperty(int value);
external static int get staticProperty;
external static void set staticProperty(int value);
}
@@ -0,0 +1,163 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// ignore: import_internal_library
import 'dart:_internal';
@patch
extension Extension on String {
/*member: Extension|instanceMethod:
builder-name=instanceMethod,
builder-params=[#this],
member-name=Extension|instanceMethod,
member-params=[#this]
*/
@patch
int instanceMethod() => 42;
/*member: Extension|genericInstanceMethod:
builder-name=genericInstanceMethod,
builder-params=[#this,t],
builder-type-params=[T],
member-name=Extension|genericInstanceMethod,
member-params=[#this,t],
member-type-params=[T]
*/
@patch
T genericInstanceMethod<T>(T t) => t;
/*member: Extension|staticMethod:
builder-name=staticMethod,
member-name=Extension|staticMethod
*/
@patch
static int staticMethod() => 87;
/*member: Extension|genericStaticMethod:
builder-name=genericStaticMethod,
builder-params=[t],
builder-type-params=[T],
member-name=Extension|genericStaticMethod,
member-params=[t],
member-type-params=[T]
*/
@patch
static T genericStaticMethod<T>(T t) => t;
/*member: Extension|get#instanceProperty:
builder-name=instanceProperty,
builder-params=[#this],
member-name=Extension|get#instanceProperty,
member-params=[#this]
*/
@patch
int get instanceProperty => 123;
/*member: Extension|set#instanceProperty:
builder-name=instanceProperty,
builder-params=[#this,value],
member-name=Extension|set#instanceProperty,
member-params=[#this,value]
*/
@patch
void set instanceProperty(int value) {}
/*member: Extension|staticProperty:
builder-name=staticProperty,
member-name=Extension|staticProperty
*/
@patch
static int get staticProperty => 237;
/*member: Extension|staticProperty=:
builder-name=staticProperty,
builder-params=[value],
member-name=Extension|staticProperty=,
member-params=[value]
*/
@patch
static void set staticProperty(int value) {}
}
@patch
extension GenericExtension<T> on T {
/*member: GenericExtension|instanceMethod:
builder-name=instanceMethod,
builder-params=[#this],
builder-type-params=[T],
member-name=GenericExtension|instanceMethod,
member-params=[#this],
member-type-params=[T]
*/
@patch
int instanceMethod() => 42;
/*member: GenericExtension|genericInstanceMethod:
builder-name=genericInstanceMethod,
builder-params=[#this,t],
builder-type-params=[T,T],
member-name=GenericExtension|genericInstanceMethod,
member-params=[#this,t],
member-type-params=[#T,T]
*/
@patch
T genericInstanceMethod<T>(T t) => t;
/*member: GenericExtension|staticMethod:
builder-name=staticMethod,
member-name=GenericExtension|staticMethod
*/
@patch
static int staticMethod() => 87;
/*member: GenericExtension|genericStaticMethod:
builder-name=genericStaticMethod,
builder-params=[t],
builder-type-params=[T],
member-name=GenericExtension|genericStaticMethod,
member-params=[t],
member-type-params=[T]
*/
@patch
static T genericStaticMethod<T>(T t) => t;
/*member: GenericExtension|get#instanceProperty:
builder-name=instanceProperty,
builder-params=[#this],
builder-type-params=[T],
member-name=GenericExtension|get#instanceProperty,
member-params=[#this],
member-type-params=[T]
*/
@patch
int get instanceProperty => 123;
/*member: GenericExtension|set#instanceProperty:
builder-name=instanceProperty,
builder-params=[#this,value],
builder-type-params=[T],
member-name=GenericExtension|set#instanceProperty,
member-params=[#this,value],
member-type-params=[T]
*/
@patch
void set instanceProperty(int value) {}
/*member: GenericExtension|staticProperty:
builder-name=staticProperty,
member-name=GenericExtension|staticProperty
*/
@patch
static int get staticProperty => 237;
/*member: GenericExtension|staticProperty=:
builder-name=staticProperty,
builder-params=[value],
member-name=GenericExtension|staticProperty=,
member-params=[value]
*/
@patch
static void set staticProperty(int value) {}
}
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io' show Directory, Platform;
import 'package:front_end/src/api_prototype/experimental_flags.dart'
show ExperimentalFlag;
import 'package:front_end/src/fasta/builder/builder.dart';
import 'package:front_end/src/fasta/builder/extension_builder.dart';
import 'package:front_end/src/fasta/kernel/kernel_builder.dart';
@@ -22,8 +24,11 @@ main(List<String> args) async {
supportedMarkers: sharedMarkers,
createUriForFileName: createUriForFileName,
onFailure: onFailure,
runTest: runTestFor(
const ExtensionsDataComputer(), [cfeExtensionMethodsConfig]));
runTest: runTestFor(const ExtensionsDataComputer(), [
new TestConfig(cfeMarker, 'cfe with extension methods',
experimentalFlags: const {ExperimentalFlag.extensionMethods: true},
librariesSpecificationUri: createUriForFileName('libraries.json'))
]));
}
class ExtensionsDataComputer extends DataComputer<Features> {
@@ -58,7 +58,7 @@ class IdTestingDataComputer extends DataComputer<String> {
Library library, Map<Id, ActualData<String>> actualMap,
{bool verbose}) {
new IdTestingDataExtractor(compilerResult, actualMap)
.computeForLibrary(library, useFileUri: true);
.computeForLibrary(library);
}
@override
@@ -52,7 +52,7 @@ class LanguageVersioningDataComputer extends DataComputer<String> {
Library library, Map<Id, ActualData<String>> actualMap,
{bool verbose}) {
new LanguageVersioningDataExtractor(compilerResult, actualMap)
.computeForLibrary(library, useFileUri: true);
.computeForLibrary(library);
}
@override
+1 -1
View File
@@ -353,7 +353,7 @@ enum ExtensionMemberKind { Field = 0, Method = 1, Getter = 2, Setter = 3, Operat
type ExtensionMemberDescriptor {
StringReference name;
ExtensionMemberKind kind;
Byte flags (isStatic, isExternal);
Byte flags (isStatic);
MemberReference member;
}
+1 -14
View File
@@ -1350,7 +1350,6 @@ enum ExtensionMemberKind {
/// Information about an member declaration in an extension.
class ExtensionMemberDescriptor {
static const int FlagStatic = 1 << 0; // Must match serialized bit positions.
static const int FlagExternal = 1 << 1;
/// The name of the extension member.
///
@@ -1387,28 +1386,16 @@ class ExtensionMemberDescriptor {
Reference member;
ExtensionMemberDescriptor(
{this.name,
this.kind,
bool isStatic: false,
bool isExternal: false,
this.member}) {
{this.name, this.kind, bool isStatic: false, this.member}) {
this.isStatic = isStatic;
this.isExternal = isExternal;
}
/// Return `true` if the extension method was declared as `static`.
bool get isStatic => flags & FlagStatic != 0;
/// Return `true` if the extension method was declared as `external`.
bool get isExternal => flags & FlagExternal != 0;
void set isStatic(bool value) {
flags = value ? (flags | FlagStatic) : (flags & ~FlagStatic);
}
void set isExternal(bool value) {
flags = value ? (flags | FlagExternal) : (flags & ~FlagExternal);
}
}
// ------------------------------------------------------------------------
-1
View File
@@ -1189,7 +1189,6 @@ class Printer extends Visitor<Null> {
++indentation;
node.members.forEach((ExtensionMemberDescriptor descriptor) {
writeIndentation();
writeModifier(descriptor.isExternal, 'external');
writeModifier(descriptor.isStatic, 'static');
switch (descriptor.kind) {
case ExtensionMemberKind.Method:
@@ -61,7 +61,7 @@ class IdTestingDataComputer extends DataComputer<String> {
KernelToElementMapImpl elementMap = frontendStrategy.elementMap;
ir.Library node = elementMap.getLibraryNode(library);
new IdTestingDataExtractor(compiler.reporter, actualMap, elementMap)
.computeForLibrary(node, useFileUri: true);
.computeForLibrary(node);
}
@override