[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>
diff --git a/pkg/front_end/lib/src/api_prototype/memory_file_system.dart b/pkg/front_end/lib/src/api_prototype/memory_file_system.dart
index fd091bb..3618c93 100644
--- a/pkg/front_end/lib/src/api_prototype/memory_file_system.dart
+++ b/pkg/front_end/lib/src/api_prototype/memory_file_system.dart
@@ -26,7 +26,9 @@
Uri currentDirectory;
MemoryFileSystem(Uri currentDirectory)
- : currentDirectory = _addTrailingSlash(currentDirectory);
+ : currentDirectory = _addTrailingSlash(currentDirectory) {
+ _directories.add(currentDirectory);
+ }
@override
MemoryFileSystemEntity entityForUri(Uri uri) {
diff --git a/pkg/front_end/lib/src/base/common.dart b/pkg/front_end/lib/src/base/common.dart
new file mode 100644
index 0000000..e511a04
--- /dev/null
+++ b/pkg/front_end/lib/src/base/common.dart
@@ -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;
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index c4a1632..1ccb68b 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -53,6 +53,8 @@
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 @@
ClassBuilder actualOrigin;
+ ClassBuilder patchForTesting;
+
ClassBuilder(
List<MetadataBuilder> metadata,
int modifiers,
@@ -1523,6 +1527,9 @@
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];
diff --git a/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart b/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart
index 6357975..592ecf2 100644
--- a/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart
@@ -74,5 +74,6 @@
return buffer..write(name ?? fullNameForErrors);
}
- String toString() => "$debugName(${printOn(new StringBuffer())})";
+ String toString() =>
+ "${isPatch ? 'patch ' : ''}$debugName(${printOn(new StringBuffer())})";
}
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index d818e4d..0335f23 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -11,6 +11,8 @@
import 'package:kernel/type_algebra.dart';
+import '../../base/common.dart';
+
import 'builder.dart'
show
Builder,
@@ -459,6 +461,7 @@
final Procedure _procedure;
final int charOpenParenOffset;
final ProcedureKind kind;
+ ProcedureBuilder patchForTesting;
AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
@@ -553,8 +556,8 @@
_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 @@
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 @@
Statement closureBody = new ReturnStatement(
new StaticInvocation(
- procedure,
+ _procedure,
new Arguments(closurePositionalArguments,
types: typeArguments, named: closureNamedArguments))
..fileOffset = fileOffset)
@@ -709,10 +712,10 @@
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 @@
if (patch is ProcedureBuilder) {
if (checkPatch(patch)) {
patch.actualOrigin = this;
+ if (retainDataForTesting) {
+ patchForTesting = patch;
+ }
}
} else {
reportPatchMismatch(patch);
@@ -807,6 +813,8 @@
@override
ConstructorBuilder actualOrigin;
+ ConstructorBuilder patchForTesting;
+
Constructor get actualConstructor => _constructor;
ConstructorBuilder(
@@ -998,6 +1006,9 @@
if (patch is ConstructorBuilder) {
if (checkPatch(patch)) {
patch.actualOrigin = this;
+ if (retainDataForTesting) {
+ patchForTesting = patch;
+ }
}
} else {
reportPatchMismatch(patch);
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart
index b46cd36..d45a8c7 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart
@@ -26,7 +26,7 @@
bool get isStatic => _descriptor.isStatic;
@override
- bool get isExternal => _descriptor.isExternal;
+ bool get isExternal => member.isExternal;
@override
Procedure get procedure {
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index f2753bd..9e548fb 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -3444,7 +3444,7 @@
beforeInitializers?.next, token);
break;
case DeclarationKind.Extension:
- if (optional(';', bodyStart)) {
+ if (optional(';', bodyStart) && externalToken == null) {
reportRecoverableError(isOperator ? name.next : name,
fasta.messageExtensionDeclaresAbstractMember);
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index fd7df17..ea3c839 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -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/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 @@
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 @@
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 @@
}
} 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 @@
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 @@
name: new Name(declaration.name, libraryBuilder.library),
member: tearOff.reference,
isStatic: false,
- isExternal: false,
kind: ExtensionMemberKind.TearOff));
}
}
@@ -157,4 +164,46 @@
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;
+ }
}
diff --git a/pkg/front_end/lib/src/testing/id_extractor.dart b/pkg/front_end/lib/src/testing/id_extractor.dart
index 0afbb82..a7be604 100644
--- a/pkg/front_end/lib/src/testing/id_extractor.dart
+++ b/pkg/front_end/lib/src/testing/id_extractor.dart
@@ -61,9 +61,8 @@
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);
}
diff --git a/pkg/front_end/lib/src/testing/id_testing.dart b/pkg/front_end/lib/src/testing/id_testing.dart
index 6aba9fb..3c49ea0 100644
--- a/pkg/front_end/lib/src/testing/id_testing.dart
+++ b/pkg/front_end/lib/src/testing/id_testing.dart
@@ -214,6 +214,8 @@
entry;
}
}
+ assert(
+ mainTestFile != null, "No 'main.dart' test file found for $testFile.");
}
String annotatedCode = new File.fromUri(mainTestFile.uri).readAsStringSync();
diff --git a/pkg/front_end/lib/src/testing/id_testing_helper.dart b/pkg/front_end/lib/src/testing/id_testing_helper.dart
index ec92375..68aa64d 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.dart
@@ -8,6 +8,7 @@
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 @@
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 @@
/// 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 @@
};
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,
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index d32d8f5..0c98653 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -62,7 +62,7 @@
(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 @@
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 @@
/// 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 ');
}
diff --git a/pkg/front_end/test/extensions/data/as_show/lib.dart b/pkg/front_end/test/extensions/data/as_show/lib.dart
new file mode 100644
index 0000000..e89ef0c
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/as_show/lib.dart
@@ -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]*/
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/extensions/data/as_show/libraries.json b/pkg/front_end/test/extensions/data/as_show/libraries.json
new file mode 100644
index 0000000..7a584cb
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/as_show/libraries.json
@@ -0,0 +1,9 @@
+{
+ "none": {
+ "libraries": {
+ "test": {
+ "uri": "origin.dart"
+ }
+ }
+ }
+}
diff --git a/pkg/front_end/test/extensions/data/as_show/main.dart b/pkg/front_end/test/extensions/data/as_show/main.dart
new file mode 100644
index 0000000..2a7d2d1
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/as_show/main.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();
+}
diff --git a/pkg/front_end/test/extensions/data/as_show/origin.dart b/pkg/front_end/test/extensions/data/as_show/origin.dart
new file mode 100644
index 0000000..1b36bb9
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/as_show/origin.dart
@@ -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]*/
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/extensions/data/patching/libraries.json b/pkg/front_end/test/extensions/data/patching/libraries.json
new file mode 100644
index 0000000..a697508
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/patching/libraries.json
@@ -0,0 +1,12 @@
+{
+ "none": {
+ "libraries": {
+ "test": {
+ "patches": [
+ "patch.dart"
+ ],
+ "uri": "origin.dart"
+ }
+ }
+ }
+}
diff --git a/pkg/front_end/test/extensions/data/patching/main.dart b/pkg/front_end/test/extensions/data/patching/main.dart
new file mode 100644
index 0000000..9599059
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/patching/main.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;
+}
diff --git a/pkg/front_end/test/extensions/data/patching/origin.dart b/pkg/front_end/test/extensions/data/patching/origin.dart
new file mode 100644
index 0000000..1a5b69e
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/patching/origin.dart
@@ -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);
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/extensions/data/patching/patch.dart b/pkg/front_end/test/extensions/data/patching/patch.dart
new file mode 100644
index 0000000..32edfc4
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/patching/patch.dart
@@ -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) {}
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/extensions/extensions_test.dart b/pkg/front_end/test/extensions/extensions_test.dart
index 33e8fb4..880d249 100644
--- a/pkg/front_end/test/extensions/extensions_test.dart
+++ b/pkg/front_end/test/extensions/extensions_test.dart
@@ -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 @@
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> {
diff --git a/pkg/front_end/test/id_testing/id_testing_test.dart b/pkg/front_end/test/id_testing/id_testing_test.dart
index 07d99ba..92a4fb5 100644
--- a/pkg/front_end/test/id_testing/id_testing_test.dart
+++ b/pkg/front_end/test/id_testing/id_testing_test.dart
@@ -58,7 +58,7 @@
Library library, Map<Id, ActualData<String>> actualMap,
{bool verbose}) {
new IdTestingDataExtractor(compilerResult, actualMap)
- .computeForLibrary(library, useFileUri: true);
+ .computeForLibrary(library);
}
@override
diff --git a/pkg/front_end/test/language_versioning/language_versioning_test.dart b/pkg/front_end/test/language_versioning/language_versioning_test.dart
index 691df94..a387f9a 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_test.dart
@@ -52,7 +52,7 @@
Library library, Map<Id, ActualData<String>> actualMap,
{bool verbose}) {
new LanguageVersioningDataExtractor(compilerResult, actualMap)
- .computeForLibrary(library, useFileUri: true);
+ .computeForLibrary(library);
}
@override
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index d8a353e..333a741e 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -353,7 +353,7 @@
type ExtensionMemberDescriptor {
StringReference name;
ExtensionMemberKind kind;
- Byte flags (isStatic, isExternal);
+ Byte flags (isStatic);
MemberReference member;
}
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index cd777e3..6fb554d 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -1350,7 +1350,6 @@
/// 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 @@
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);
- }
}
// ------------------------------------------------------------------------
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 707b3a1..d3a9b1a 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1189,7 +1189,6 @@
++indentation;
node.members.forEach((ExtensionMemberDescriptor descriptor) {
writeIndentation();
- writeModifier(descriptor.isExternal, 'external');
writeModifier(descriptor.isStatic, 'static');
switch (descriptor.kind) {
case ExtensionMemberKind.Method:
diff --git a/tests/compiler/dart2js/equivalence/id_testing_test.dart b/tests/compiler/dart2js/equivalence/id_testing_test.dart
index a24168a..c40ff6f 100644
--- a/tests/compiler/dart2js/equivalence/id_testing_test.dart
+++ b/tests/compiler/dart2js/equivalence/id_testing_test.dart
@@ -61,7 +61,7 @@
KernelToElementMapImpl elementMap = frontendStrategy.elementMap;
ir.Library node = elementMap.getLibraryNode(library);
new IdTestingDataExtractor(compiler.reporter, actualMap, elementMap)
- .computeForLibrary(node, useFileUri: true);
+ .computeForLibrary(node);
}
@override