blob: 9657bfa2ab9c46bd33711bcaabc6f6ecb53ecfc5 [file] [log] [blame]
// Copyright (c) 2012, 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.
import 'dart:async';
import "package:expect/expect.dart";
import "package:async_helper/async_helper.dart";
import "../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart";
import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart";
import "../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart";
import "../../../sdk/lib/_internal/compiler/implementation/util/util.dart";
import "mock_compiler.dart";
import "parser_helper.dart";
Future<Compiler> applyPatch(String script, String patch,
{bool analyzeAll: false, bool analyzeOnly: false}) {
String core = "$DEFAULT_CORELIB\n$script";
MockCompiler compiler = new MockCompiler(coreSource: core,
analyzeAll: analyzeAll,
analyzeOnly: analyzeOnly);
var uri = Uri.parse("core.dartp");
compiler.sourceFiles[uri.toString()] = new MockFile(patch);
var handler = new LibraryDependencyHandler(compiler);
return compiler.patchParser.patchLibrary(handler, uri, compiler.coreLibrary)
.then((_) {
handler.computeExports();
return compiler;
});
}
void expectHasBody(compiler, Element element) {
var node = element.parseNode(compiler);
Expect.isNotNull(node, "Element isn't parseable, when a body was expected");
Expect.isNotNull(node.body);
// If the element has a body it is either a Block or a Return statement,
// both with different begin and end tokens.
Expect.isTrue(node.body is Block || node.body is Return);
Expect.notEquals(node.body.getBeginToken(), node.body.getEndToken());
}
void expectHasNoBody(compiler, Element element) {
var node = element.parseNode(compiler);
Expect.isNotNull(node, "Element isn't parseable, when a body was expected");
Expect.isFalse(node.hasBody());
}
Element ensure(compiler,
String name,
Element lookup(name),
{bool expectIsPatched: false,
bool expectIsPatch: false,
bool checkHasBody: false,
bool expectIsGetter: false,
bool expectIsFound: true,
bool expectIsRegular: false}) {
var element = lookup(name);
if (!expectIsFound) {
Expect.isNull(element);
return element;
}
Expect.isNotNull(element);
if (expectIsGetter) {
Expect.isTrue(element is AbstractFieldElement);
Expect.isNotNull(element.getter);
element = element.getter;
}
Expect.equals(expectIsPatched, element.isPatched);
if (expectIsPatched) {
Expect.isNull(element.origin);
Expect.isNotNull(element.patch);
Expect.equals(element, element.declaration);
Expect.equals(element.patch, element.implementation);
if (checkHasBody) {
expectHasNoBody(compiler, element);
expectHasBody(compiler, element.patch);
}
} else {
Expect.isTrue(element.isImplementation);
}
Expect.equals(expectIsPatch, element.isPatch);
if (expectIsPatch) {
Expect.isNotNull(element.origin);
Expect.isNull(element.patch);
Expect.equals(element.origin, element.declaration);
Expect.equals(element, element.implementation);
if (checkHasBody) {
expectHasBody(compiler, element);
expectHasNoBody(compiler, element.origin);
}
} else {
Expect.isTrue(element.isDeclaration);
}
if (expectIsRegular) {
Expect.isNull(element.origin);
Expect.isNull(element.patch);
Expect.equals(element, element.declaration);
Expect.equals(element, element.implementation);
if (checkHasBody) {
expectHasBody(compiler, element);
}
}
Expect.isFalse(element.isPatched && element.isPatch);
return element;
}
testPatchFunction() {
asyncTest(() => applyPatch(
"external test();",
"patch test() { return 'string'; } ").then((compiler) {
ensure(compiler, "test", compiler.coreLibrary.find,
expectIsPatched: true, checkHasBody: true);
ensure(compiler, "test", compiler.coreLibrary.patch.find,
expectIsPatch: true, checkHasBody: true);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
Expect.isTrue(compiler.errors.isEmpty,
"Unexpected errors: ${compiler.errors}");
}));
}
testPatchConstructor() {
asyncTest(() => applyPatch(
"""
class Class {
external Class();
}
""",
"""
patch class Class {
patch Class();
}
""").then((compiler) {
var classOrigin = ensure(compiler, "Class", compiler.coreLibrary.find,
expectIsPatched: true);
classOrigin.ensureResolved(compiler);
var classPatch = ensure(compiler, "Class", compiler.coreLibrary.patch.find,
expectIsPatch: true);
Expect.equals(classPatch, classOrigin.patch);
Expect.equals(classOrigin, classPatch.origin);
var constructorOrigin = ensure(compiler, "",
(name) => classOrigin.localLookup(name),
expectIsPatched: true);
var constructorPatch = ensure(compiler, "",
(name) => classPatch.localLookup(name),
expectIsPatch: true);
Expect.equals(constructorPatch, constructorOrigin.patch);
Expect.equals(constructorOrigin, constructorPatch.origin);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
Expect.isTrue(compiler.errors.isEmpty,
"Unexpected errors: ${compiler.errors}");
}));
}
testPatchMember() {
asyncTest(() => applyPatch(
"""
class Class {
external String toString();
}
""",
"""
patch class Class {
patch String toString() => 'string';
}
""").then((compiler) {
var container = ensure(compiler, "Class", compiler.coreLibrary.find,
expectIsPatched: true);
container.parseNode(compiler);
ensure(compiler, "Class", compiler.coreLibrary.patch.find,
expectIsPatch: true);
ensure(compiler, "toString", container.lookupLocalMember,
expectIsPatched: true, checkHasBody: true);
ensure(compiler, "toString", container.patch.lookupLocalMember,
expectIsPatch: true, checkHasBody: true);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
Expect.isTrue(compiler.errors.isEmpty,
"Unexpected errors: ${compiler.errors}");
}));
}
testPatchGetter() {
asyncTest(() => applyPatch(
"""
class Class {
external int get field;
}
""",
"""
patch class Class {
patch int get field => 5;
}
""").then((compiler) {
var container = ensure(compiler, "Class", compiler.coreLibrary.find,
expectIsPatched: true);
container.parseNode(compiler);
ensure(compiler,
"field",
container.lookupLocalMember,
expectIsGetter: true,
expectIsPatched: true,
checkHasBody: true);
ensure(compiler,
"field",
container.patch.lookupLocalMember,
expectIsGetter: true,
expectIsPatch: true,
checkHasBody: true);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
Expect.isTrue(compiler.errors.isEmpty,
"Unexpected errors: ${compiler.errors}");
}));
}
testRegularMember() {
asyncTest(() => applyPatch(
"""
class Class {
void regular() {}
}
""",
"""
patch class Class {
}
""").then((compiler) {
var container = ensure(compiler, "Class", compiler.coreLibrary.find,
expectIsPatched: true);
container.parseNode(compiler);
ensure(compiler, "Class", compiler.coreLibrary.patch.find,
expectIsPatch: true);
ensure(compiler, "regular", container.lookupLocalMember,
checkHasBody: true, expectIsRegular: true);
ensure(compiler, "regular", container.patch.lookupLocalMember,
checkHasBody: true, expectIsRegular: true);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
Expect.isTrue(compiler.errors.isEmpty,
"Unexpected errors: ${compiler.errors}");
}));
}
testGhostMember() {
asyncTest(() => applyPatch(
"""
class Class {
}
""",
"""
patch class Class {
void ghost() {}
}
""").then((compiler) {
var container = ensure(compiler, "Class", compiler.coreLibrary.find,
expectIsPatched: true);
container.parseNode(compiler);
ensure(compiler, "Class", compiler.coreLibrary.patch.find,
expectIsPatch: true);
ensure(compiler, "ghost", container.lookupLocalMember,
expectIsFound: false);
ensure(compiler, "ghost", container.patch.lookupLocalMember,
checkHasBody: true, expectIsRegular: true);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
Expect.isTrue(compiler.errors.isEmpty,
"Unexpected errors: ${compiler.errors}");
}));
}
testInjectFunction() {
asyncTest(() => applyPatch(
"",
"int _function() => 5;").then((compiler) {
ensure(compiler,
"_function",
compiler.coreLibrary.find,
expectIsFound: false);
ensure(compiler,
"_function",
compiler.coreLibrary.patch.find,
checkHasBody: true, expectIsRegular: true);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
Expect.isTrue(compiler.errors.isEmpty,
"Unexpected errors: ${compiler.errors}");
}));
}
testPatchSignatureCheck() {
asyncTest(() => applyPatch(
"""
class Class {
external String method1();
external void method2(String str);
external void method3(String s1);
external void method4([String str]);
external void method5({String str});
external void method6({String str});
external void method7([String s1]);
external void method8({String s1});
external void method9(String str);
external void method10([String str]);
external void method11({String str});
}
""",
"""
patch class Class {
patch int method1() => 0;
patch void method2() {}
patch void method3(String s2) {}
patch void method4([String str, int i]) {}
patch void method5() {}
patch void method6([String str]) {}
patch void method7([String s2]) {}
patch void method8({String s2}) {}
patch void method9(int str) {}
patch void method10([int str]) {}
patch void method11({int str}) {}
}
""").then((compiler) {
var container = ensure(compiler, "Class", compiler.coreLibrary.find,
expectIsPatched: true);
container.ensureResolved(compiler);
container.parseNode(compiler);
void expect(String methodName, List infos, List errors) {
compiler.clearMessages();
compiler.resolver.resolveMethodElement(
ensure(compiler, methodName, container.lookupLocalMember,
expectIsPatched: true, checkHasBody: true));
Expect.equals(0, compiler.warnings.length);
Expect.equals(infos.length, compiler.infos.length,
"Unexpected infos: ${compiler.infos} on $methodName");
for (int i = 0 ; i < infos.length ; i++) {
Expect.equals(infos[i], compiler.infos[i].message.kind);
}
Expect.equals(errors.length, compiler.errors.length,
"Unexpected errors: ${compiler.errors} on $methodName");
for (int i = 0 ; i < errors.length ; i++) {
Expect.equals(errors[i], compiler.errors[i].message.kind);
}
}
expect("method1", [], [MessageKind.PATCH_RETURN_TYPE_MISMATCH]);
expect("method2", [],
[MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH]);
expect("method3", [MessageKind.PATCH_POINT_TO_PARAMETER],
[MessageKind.PATCH_PARAMETER_MISMATCH]);
expect("method4", [],
[MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]);
expect("method5", [],
[MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]);
expect("method6", [],
[MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH]);
expect("method7", [MessageKind.PATCH_POINT_TO_PARAMETER],
[MessageKind.PATCH_PARAMETER_MISMATCH]);
expect("method8", [MessageKind.PATCH_POINT_TO_PARAMETER],
[MessageKind.PATCH_PARAMETER_MISMATCH]);
expect("method9", [MessageKind.PATCH_POINT_TO_PARAMETER],
[MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
expect("method10", [MessageKind.PATCH_POINT_TO_PARAMETER],
[MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
expect("method11", [MessageKind.PATCH_POINT_TO_PARAMETER],
[MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
}));
}
testExternalWithoutImplementationTopLevel() {
asyncTest(() => applyPatch(
"""
external void foo();
""",
"""
// patch void foo() {}
""").then((compiler) {
var function = ensure(compiler, "foo", compiler.coreLibrary.find);
compiler.resolver.resolve(function);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
print('testExternalWithoutImplementationTopLevel:${compiler.errors}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind ==
MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION);
Expect.stringEquals('Error: External method without an implementation.',
compiler.errors[0].message.toString());
}));
}
testExternalWithoutImplementationMember() {
asyncTest(() => applyPatch(
"""
class Class {
external void foo();
}
""",
"""
patch class Class {
// patch void foo() {}
}
""").then((compiler) {
var container = ensure(compiler, "Class", compiler.coreLibrary.find,
expectIsPatched: true);
container.parseNode(compiler);
compiler.warnings.clear();
compiler.errors.clear();
compiler.resolver.resolveMethodElement(
ensure(compiler, "foo", container.lookupLocalMember));
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
print('testExternalWithoutImplementationMember:${compiler.errors}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind ==
MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION);
Expect.stringEquals('Error: External method without an implementation.',
compiler.errors[0].message.toString());
}));
}
testIsSubclass() {
asyncTest(() => applyPatch(
"""
class A {}
""",
"""
patch class A {}
""").then((compiler) {
ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find,
expectIsPatched: true);
ClassElement patch = cls.patch;
Expect.isTrue(cls != patch);
Expect.isTrue(cls.isSubclassOf(patch));
Expect.isTrue(patch.isSubclassOf(cls));
}));
}
testPatchNonExistingTopLevel() {
asyncTest(() => applyPatch(
"""
// class Class {}
""",
"""
patch class Class {}
""").then((compiler) {
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
print('testPatchNonExistingTopLevel:${compiler.errors}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING);
}));
}
testPatchNonExistingMember() {
asyncTest(() => applyPatch(
"""
class Class {}
""",
"""
patch class Class {
patch void foo() {}
}
""").then((compiler) {
var container = ensure(compiler, "Class", compiler.coreLibrary.find,
expectIsPatched: true);
container.parseNode(compiler);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
print('testPatchNonExistingMember:${compiler.errors}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING);
}));
}
testPatchNonPatchablePatch() {
asyncTest(() => applyPatch(
"""
external get foo;
""",
"""
patch var foo;
""").then((compiler) {
ensure(compiler, "foo", compiler.coreLibrary.find);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
print('testPatchNonPatchablePatch:${compiler.errors}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NONPATCHABLE);
}));
}
testPatchNonPatchableOrigin() {
asyncTest(() => applyPatch(
"""
external var foo;
""",
"""
patch get foo => 0;
""").then((compiler) {
ensure(compiler, "foo", compiler.coreLibrary.find);
Expect.isTrue(compiler.warnings.isEmpty,
"Unexpected warnings: ${compiler.warnings}");
print('testPatchNonPatchableOrigin:${compiler.errors}');
Expect.equals(2, compiler.errors.length);
Expect.equals(
MessageKind.EXTRANEOUS_MODIFIER, compiler.errors[0].message.kind);
Expect.equals(
// TODO(ahe): Eventually, this error should be removed as it will be
// handled by the regular parser.
MessageKind.PATCH_NONPATCHABLE, compiler.errors[1].message.kind);
}));
}
testPatchNonExternalTopLevel() {
asyncTest(() => applyPatch(
"""
void foo() {}
""",
"""
patch void foo() {}
""").then((compiler) {
print('testPatchNonExternalTopLevel.errors:${compiler.errors}');
print('testPatchNonExternalTopLevel.warnings:${compiler.warnings}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL);
Expect.equals(0, compiler.warnings.length);
Expect.equals(1, compiler.infos.length);
Expect.isTrue(compiler.infos[0].message.kind ==
MessageKind.PATCH_POINT_TO_FUNCTION);
}));
}
testPatchNonExternalMember() {
asyncTest(() => applyPatch(
"""
class Class {
void foo() {}
}
""",
"""
patch class Class {
patch void foo() {}
}
""").then((compiler) {
var container = ensure(compiler, "Class", compiler.coreLibrary.find,
expectIsPatched: true);
container.parseNode(compiler);
print('testPatchNonExternalMember.errors:${compiler.errors}');
print('testPatchNonExternalMember.warnings:${compiler.warnings}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL);
Expect.equals(0, compiler.warnings.length);
Expect.equals(1, compiler.infos.length);
Expect.isTrue(compiler.infos[0].message.kind ==
MessageKind.PATCH_POINT_TO_FUNCTION);
}));
}
testPatchNonClass() {
asyncTest(() => applyPatch(
"""
external void Class() {}
""",
"""
patch class Class {}
""").then((compiler) {
print('testPatchNonClass.errors:${compiler.errors}');
print('testPatchNonClass.warnings:${compiler.warnings}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NON_CLASS);
Expect.equals(0, compiler.warnings.length);
Expect.equals(1, compiler.infos.length);
Expect.isTrue(
compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_CLASS);
}));
}
testPatchNonGetter() {
asyncTest(() => applyPatch(
"""
external void foo() {}
""",
"""
patch get foo => 0;
""").then((compiler) {
print('testPatchNonClass.errors:${compiler.errors}');
print('testPatchNonClass.warnings:${compiler.warnings}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NON_GETTER);
Expect.equals(0, compiler.warnings.length);
Expect.equals(1, compiler.infos.length);
Expect.isTrue(
compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
}));
}
testPatchNoGetter() {
asyncTest(() => applyPatch(
"""
external set foo(var value) {}
""",
"""
patch get foo => 0;
""").then((compiler) {
print('testPatchNonClass.errors:${compiler.errors}');
print('testPatchNonClass.warnings:${compiler.warnings}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NO_GETTER);
Expect.equals(0, compiler.warnings.length);
Expect.equals(1, compiler.infos.length);
Expect.isTrue(
compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
}));
}
testPatchNonSetter() {
asyncTest(() => applyPatch(
"""
external void foo() {}
""",
"""
patch set foo(var value) {}
""").then((compiler) {
print('testPatchNonClass.errors:${compiler.errors}');
print('testPatchNonClass.warnings:${compiler.warnings}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NON_SETTER);
Expect.equals(0, compiler.warnings.length);
Expect.equals(1, compiler.infos.length);
Expect.isTrue(
compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
}));
}
testPatchNoSetter() {
asyncTest(() => applyPatch(
"""
external get foo;
""",
"""
patch set foo(var value) {}
""").then((compiler) {
print('testPatchNonClass.errors:${compiler.errors}');
print('testPatchNonClass.warnings:${compiler.warnings}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NO_SETTER);
Expect.equals(0, compiler.warnings.length);
Expect.equals(1, compiler.infos.length);
Expect.isTrue(
compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
}));
}
testPatchNonFunction() {
asyncTest(() => applyPatch(
"""
external get foo;
""",
"""
patch void foo() {}
""").then((compiler) {
print('testPatchNonClass.errors:${compiler.errors}');
print('testPatchNonClass.warnings:${compiler.warnings}');
Expect.equals(1, compiler.errors.length);
Expect.isTrue(
compiler.errors[0].message.kind == MessageKind.PATCH_NON_FUNCTION);
Expect.equals(0, compiler.warnings.length);
Expect.equals(1, compiler.infos.length);
Expect.isTrue(
compiler.infos[0].message.kind ==
MessageKind.PATCH_POINT_TO_FUNCTION);
}));
}
testPatchAndSelector() {
asyncTest(() => applyPatch(
"""
class A {
external void clear();
}
class B extends A {
}
""",
"""
patch class A {
int method() => 0;
patch void clear() {}
}
""").then((compiler) {
ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find,
expectIsPatched: true);
cls.ensureResolved(compiler);
ensure(compiler, "method", cls.patch.lookupLocalMember,
checkHasBody: true, expectIsRegular: true);
ensure(compiler, "clear", cls.lookupLocalMember,
checkHasBody: true, expectIsPatched: true);
compiler.phase = Compiler.PHASE_DONE_RESOLVING;
// Check that a method just in the patch class is a target for a
// typed selector.
var selector = new Selector.call('method', compiler.coreLibrary, 0);
var typedSelector = new TypedSelector.exact(cls, selector);
Element method = cls.implementation.lookupLocalMember('method');
Expect.isTrue(selector.applies(method, compiler));
Expect.isTrue(typedSelector.applies(method, compiler));
// Check that the declaration method in the declaration class is a target
// for a typed selector.
selector = new Selector.call('clear', compiler.coreLibrary, 0);
typedSelector = new TypedSelector.exact(cls, selector);
method = cls.lookupLocalMember('clear');
Expect.isTrue(selector.applies(method, compiler));
Expect.isTrue(typedSelector.applies(method, compiler));
// Check that the declaration method in the declaration class is a target
// for a typed selector on a subclass.
cls = ensure(compiler, "B", compiler.coreLibrary.find);
cls.ensureResolved(compiler);
typedSelector = new TypedSelector.exact(cls, selector);
Expect.isTrue(selector.applies(method, compiler));
Expect.isTrue(typedSelector.applies(method, compiler));
}));
}
void testAnalyzeAllInjectedMembers() {
void expect(String patchText, [expectedWarnings]) {
if (expectedWarnings == null) expectedWarnings = [];
if (expectedWarnings is! List) {
expectedWarnings = <MessageKind>[expectedWarnings];
}
asyncTest(() => applyPatch('', patchText, analyzeAll: true,
analyzeOnly: true).then((compiler) {
compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')];
return compiler.runCompiler(null).then((_) {
compareWarningKinds(patchText, expectedWarnings, compiler.warnings);
});
}));
}
expect('String s = 0;', MessageKind.NOT_ASSIGNABLE.warning);
expect('void method() { String s = 0; }', MessageKind.NOT_ASSIGNABLE.warning);
expect('''
class Class {
String s = 0;
}
''',
MessageKind.NOT_ASSIGNABLE.warning);
expect('''
class Class {
void method() {
String s = 0;
}
}
''',
MessageKind.NOT_ASSIGNABLE.warning);
}
void testTypecheckPatchedMembers() {
String originText = "external void method();";
String patchText = """
patch void method() {
String s = 0;
}
""";
asyncTest(() => applyPatch(originText, patchText,
analyzeAll: true, analyzeOnly: true).then((compiler) {
compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')];
return compiler.runCompiler(null).then((_) {
compareWarningKinds(patchText,
[MessageKind.NOT_ASSIGNABLE.warning], compiler.warnings);
});
}));
}
main() {
testPatchConstructor();
testPatchFunction();
testPatchMember();
testPatchGetter();
testRegularMember();
testGhostMember();
testInjectFunction();
testPatchSignatureCheck();
testExternalWithoutImplementationTopLevel();
testExternalWithoutImplementationMember();
testIsSubclass();
testPatchNonExistingTopLevel();
testPatchNonExistingMember();
testPatchNonPatchablePatch();
testPatchNonPatchableOrigin();
testPatchNonExternalTopLevel();
testPatchNonExternalMember();
testPatchNonClass();
testPatchNonGetter();
testPatchNoGetter();
testPatchNonSetter();
testPatchNoSetter();
testPatchNonFunction();
testPatchAndSelector();
testAnalyzeAllInjectedMembers();
testTypecheckPatchedMembers();
}