mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:30:32 +00:00
[package:js] Add checks for external keyword
Checks to see if a JS interop member is correctly annotated with the `external` keyword. If it is not, it must be one of several exceptions to be allowed. This CL also changes static errors to first check for `JS` and `external` before processing the member as a JS interop member. This makes it clearer whether a member is a JS member. Change-Id: I412eeafbfe8773847bfb9c864e4fb9b65e2d632a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/158083 Commit-Queue: Srujan Gaddam <srujzs@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
f0d1fe173c
commit
c990450628
|
@ -5669,6 +5669,17 @@ const MessageCode messageJsInteropNonExternalConstructor = const MessageCode(
|
|||
r"""JS interop classes do not support non-external constructors.""",
|
||||
tip: r"""Try annotating with `external`.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeJsInteropNonExternalMember =
|
||||
messageJsInteropNonExternalMember;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageJsInteropNonExternalMember = const MessageCode(
|
||||
"JsInteropNonExternalMember",
|
||||
message:
|
||||
r"""This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.""",
|
||||
tip: r"""Try annotating the member with `external`.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Template<
|
||||
Message Function(String name)> templateLabelNotFound = const Template<
|
||||
|
|
|
@ -13,26 +13,57 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
|
|||
messageJsInteropEnclosingClassJSAnnotationContext,
|
||||
messageJsInteropIndexNotSupported,
|
||||
messageJsInteropNamedParameters,
|
||||
messageJsInteropNonExternalConstructor;
|
||||
messageJsInteropNonExternalConstructor,
|
||||
messageJsInteropNonExternalMember;
|
||||
|
||||
import 'src/js_interop.dart';
|
||||
|
||||
class JsInteropChecks extends RecursiveVisitor<void> {
|
||||
final DiagnosticReporter<Message, LocatedMessage> _diagnosticsReporter;
|
||||
bool _classHasJSAnnotation = false;
|
||||
bool _libraryHasJSAnnotation = false;
|
||||
|
||||
JsInteropChecks(this._diagnosticsReporter);
|
||||
|
||||
@override
|
||||
void defaultMember(Member member) {
|
||||
_checkMemberJSInteropAnnotation(member);
|
||||
_checkJSInteropAnnotation(member);
|
||||
// TODO(43530): Disallow having JS interop annotations on non-external
|
||||
// members (class members or otherwise). Currently, they're being ignored.
|
||||
super.defaultMember(member);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitProcedure(Procedure procedure) {
|
||||
_checkMemberJSInteropAnnotation(procedure);
|
||||
void visitClass(Class cls) {
|
||||
_classHasJSAnnotation = hasJSInteropAnnotation(cls);
|
||||
super.visitClass(cls);
|
||||
_classHasJSAnnotation = false;
|
||||
}
|
||||
|
||||
if (!procedure.isExternal || !isJSInteropMember(procedure)) return;
|
||||
@override
|
||||
void visitLibrary(Library lib) {
|
||||
_libraryHasJSAnnotation = hasJSInteropAnnotation(lib);
|
||||
super.visitLibrary(lib);
|
||||
_libraryHasJSAnnotation = false;
|
||||
}
|
||||
|
||||
@override
|
||||
void visitProcedure(Procedure procedure) {
|
||||
_checkJSInteropAnnotation(procedure);
|
||||
if (_classHasJSAnnotation && !procedure.isExternal) {
|
||||
// If not one of few exceptions, member is not allowed to exclude
|
||||
// `external` inside of a JS interop class.
|
||||
if (!(procedure.isAbstract ||
|
||||
procedure.isFactory ||
|
||||
procedure.isStatic)) {
|
||||
_diagnosticsReporter.report(
|
||||
messageJsInteropNonExternalMember,
|
||||
procedure.fileOffset,
|
||||
procedure.name.text.length,
|
||||
procedure.location.file);
|
||||
}
|
||||
}
|
||||
if (!_isJSInteropMember(procedure)) return;
|
||||
|
||||
if (!procedure.isStatic &&
|
||||
(procedure.name.text == '[]=' || procedure.name.text == '[]')) {
|
||||
|
@ -65,17 +96,18 @@ class JsInteropChecks extends RecursiveVisitor<void> {
|
|||
|
||||
@override
|
||||
void visitConstructor(Constructor constructor) {
|
||||
_checkMemberJSInteropAnnotation(constructor);
|
||||
|
||||
if (!isJSInteropMember(constructor)) return;
|
||||
|
||||
if (!constructor.isExternal && !constructor.isSynthetic) {
|
||||
_checkJSInteropAnnotation(constructor);
|
||||
if (_classHasJSAnnotation &&
|
||||
!constructor.isExternal &&
|
||||
!constructor.isSynthetic) {
|
||||
// Non-synthetic constructors must be annotated with `external`.
|
||||
_diagnosticsReporter.report(
|
||||
messageJsInteropNonExternalConstructor,
|
||||
constructor.fileOffset,
|
||||
constructor.name.text.length,
|
||||
constructor.location.file);
|
||||
}
|
||||
if (!_isJSInteropMember(constructor)) return;
|
||||
|
||||
_checkNoNamedParameters(constructor.function);
|
||||
}
|
||||
|
@ -92,14 +124,18 @@ class JsInteropChecks extends RecursiveVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reports an error if [m] has a JS interop annotation and is part of a class
|
||||
/// that does not.
|
||||
void _checkMemberJSInteropAnnotation(Member m) {
|
||||
if (!hasJSInteropAnnotation(m)) return;
|
||||
var enclosingClass = m.enclosingClass;
|
||||
if (enclosingClass != null && !hasJSInteropAnnotation(enclosingClass)) {
|
||||
/// Reports an error if [member] does not correctly use the JS interop
|
||||
/// annotation or the keyword `external`.
|
||||
void _checkJSInteropAnnotation(Member member) {
|
||||
var enclosingClass = member.enclosingClass;
|
||||
|
||||
if (!_classHasJSAnnotation &&
|
||||
enclosingClass != null &&
|
||||
hasJSInteropAnnotation(member)) {
|
||||
// If in a class that is not JS interop, this member is not allowed to be
|
||||
// JS interop.
|
||||
_diagnosticsReporter.report(messageJsInteropEnclosingClassJSAnnotation,
|
||||
m.fileOffset, m.name.text.length, m.location.file,
|
||||
member.fileOffset, member.name.text.length, member.location.file,
|
||||
context: <LocatedMessage>[
|
||||
messageJsInteropEnclosingClassJSAnnotationContext.withLocation(
|
||||
enclosingClass.location.file,
|
||||
|
@ -108,4 +144,15 @@ class JsInteropChecks extends RecursiveVisitor<void> {
|
|||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether [member] is considered to be a JS interop member.
|
||||
bool _isJSInteropMember(Member member) {
|
||||
if (!member.isExternal) return false;
|
||||
if (_classHasJSAnnotation) return true;
|
||||
if (!_classHasJSAnnotation && member.enclosingClass != null) return false;
|
||||
// In the case where the member does not belong to any class, a JS
|
||||
// annotation is not needed on the library to be considered JS interop as
|
||||
// long as the member has an annotation.
|
||||
return hasJSInteropAnnotation(member) || _libraryHasJSAnnotation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,17 +9,6 @@ import 'package:kernel/kernel.dart';
|
|||
bool hasJSInteropAnnotation(Annotatable a) =>
|
||||
a.annotations.any(_isPublicJSAnnotation);
|
||||
|
||||
/// Returns true if [m] belongs to a JS interop context. Checks if either the
|
||||
/// member or the surrounding context has a JS interop annotation.
|
||||
bool isJSInteropMember(Member m) {
|
||||
if (hasJSInteropAnnotation(m)) return true;
|
||||
var enclosingClass = m.enclosingClass;
|
||||
if (enclosingClass != null) return hasJSInteropAnnotation(enclosingClass);
|
||||
var enclosingLibrary = m.enclosingLibrary;
|
||||
if (enclosingLibrary != null) return hasJSInteropAnnotation(enclosingLibrary);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns true if [m] belongs to an anonymous class.
|
||||
bool isAnonymousClassMember(Member m) {
|
||||
var enclosingClass = m.enclosingClass;
|
||||
|
|
|
@ -74,7 +74,6 @@ enum MessageKind {
|
|||
INVALID_PACKAGE_URI,
|
||||
INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE,
|
||||
JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS,
|
||||
JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
|
||||
JS_INTEROP_FIELD_NOT_SUPPORTED,
|
||||
JS_INTEROP_NON_EXTERNAL_MEMBER,
|
||||
JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS,
|
||||
|
@ -200,25 +199,6 @@ class MessageTemplate {
|
|||
MessageKind.JS_INTEROP_NON_EXTERNAL_MEMBER,
|
||||
"Js-interop members must be 'external'."),
|
||||
|
||||
MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER: const MessageTemplate(
|
||||
MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
|
||||
"Member '#{member}' in js-interop class '#{cls}' is not external.",
|
||||
howToFix: "Try adding 'external' to '#{member}'.",
|
||||
examples: const [
|
||||
"""
|
||||
import 'package:js/js.dart';
|
||||
|
||||
@JS()
|
||||
class Foo {
|
||||
bar() {}
|
||||
}
|
||||
|
||||
main() {
|
||||
new Foo().bar();
|
||||
}
|
||||
"""
|
||||
]),
|
||||
|
||||
MessageKind.IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED:
|
||||
const MessageTemplate(
|
||||
MessageKind.IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED,
|
||||
|
|
|
@ -125,15 +125,6 @@ class KernelAnnotationProcessor implements AnnotationProcessor {
|
|||
_nativeBasicDataBuilder.markAsJsInteropMember(
|
||||
function, memberName);
|
||||
}
|
||||
|
||||
if (!function.isExternal &&
|
||||
!function.isAbstract &&
|
||||
!function.isStatic) {
|
||||
reporter.reportErrorMessage(
|
||||
function,
|
||||
MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
|
||||
{'cls': cls.name, 'member': member.name});
|
||||
}
|
||||
}
|
||||
});
|
||||
elementEnvironment.forEachConstructor(cls,
|
||||
|
|
|
@ -94,19 +94,6 @@ class A {
|
|||
|
||||
main() => new A();
|
||||
'''),
|
||||
const Test('Js-interop class with instance method.', '''
|
||||
@JS()
|
||||
library test;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
|
||||
@JS()
|
||||
class A {
|
||||
method() {}
|
||||
}
|
||||
|
||||
main() => new A();
|
||||
''', errors: const [MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER]),
|
||||
const Test(
|
||||
'Js-interop class with abstract getter.',
|
||||
'''
|
||||
|
|
|
@ -448,6 +448,8 @@ JsInteropNamedParameters/analyzerCode: Fail # Web compiler specific
|
|||
JsInteropNamedParameters/example: Fail # Web compiler specific
|
||||
JsInteropNonExternalConstructor/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropNonExternalConstructor/example: Fail # Web compiler specific
|
||||
JsInteropNonExternalMember/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropNonExternalMember/example: Fail # Web compiler specific
|
||||
LanguageVersionInvalidInDotPackages/analyzerCode: Fail
|
||||
LanguageVersionMismatchInPart/analyzerCode: Fail
|
||||
LanguageVersionMismatchInPart/part_wrapped_script: Fail # Part in (now) part.
|
||||
|
|
|
@ -4179,6 +4179,10 @@ JsInteropNonExternalConstructor:
|
|||
template: "JS interop classes do not support non-external constructors."
|
||||
tip: "Try annotating with `external`."
|
||||
|
||||
JsInteropNonExternalMember:
|
||||
template: "This JS interop member must be annotated with `external`. Only factories and static methods can be non-external."
|
||||
tip: "Try annotating the member with `external`."
|
||||
|
||||
DefaultListConstructorError:
|
||||
template: "Can't use the default List constructor."
|
||||
tip: "Try using List.filled instead."
|
||||
|
|
|
@ -21,16 +21,16 @@ set topLevelSetter(_) {}
|
|||
|
||||
topLevelFunction() {}
|
||||
|
||||
@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED //# 01: compile-time error
|
||||
@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED //# 01: compile-time error
|
||||
var topLevelJsInteropField; //# 01: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 02: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 02: compile-time error
|
||||
get topLevelJsInteropGetter => null; //# 02: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 03: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 03: compile-time error
|
||||
set topLevelJsInteropSetter(_) {} //# 03: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 04: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 04: compile-time error
|
||||
topLevelJsInteropFunction() {} //# 04: continued
|
||||
|
||||
external get externalTopLevelGetter;
|
||||
|
@ -58,7 +58,7 @@ class Class {
|
|||
// NON_NATIVE_EXTERNAL //# 09: compile-time error
|
||||
external factory Class.externalFact(); //# 09: continued
|
||||
|
||||
@JS('a') // GENERIC, GENERIC //# 10: compile-time error
|
||||
@JS('a') // GENERIC //# 10: compile-time error
|
||||
Class.jsInteropGenerative(); //# 10: continued
|
||||
|
||||
@JS('a') // GENERIC //# 11: compile-time error
|
||||
|
@ -95,7 +95,7 @@ class Class {
|
|||
@JS('a') // GENERIC //# 18: compile-time error
|
||||
static var staticJsInteropField; //# 18: continued
|
||||
|
||||
@JS('a') // GENERIC //# 19: compile-time error
|
||||
@JS('a') // GENERIC //# 19: compile-time error
|
||||
static get staticJsInteropGetter => null; //# 19: continued
|
||||
|
||||
@JS('a') // GENERIC //# 20: compile-time error
|
||||
|
@ -167,13 +167,13 @@ class JsInteropClass {
|
|||
// IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 38: compile-time error
|
||||
var instanceField; //# 38: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 39: compile-time error
|
||||
// GENERIC //# 39: compile-time error
|
||||
get instanceGetter => null; //# 39: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 40: compile-time error
|
||||
// GENERIC //# 40: compile-time error
|
||||
set instanceSetter(_) {} //# 40: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 41: compile-time error
|
||||
// GENERIC //# 41: compile-time error
|
||||
instanceMethod() {} //# 41: continued
|
||||
|
||||
// IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 42: compile-time error
|
||||
|
@ -188,16 +188,16 @@ class JsInteropClass {
|
|||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 45: compile-time error
|
||||
static staticMethod() {} //# 45: continued
|
||||
|
||||
@JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 46: compile-time error
|
||||
@JS('a') // GENERIC //# 46: compile-time error
|
||||
var instanceJsInteropField; //# 46: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 48: compile-time error
|
||||
@JS('a') // GENERIC //# 48: compile-time error
|
||||
get instanceJsInteropGetter => null; //# 48: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 49: compile-time error
|
||||
@JS('a') // GENERIC //# 49: compile-time error
|
||||
set instanceJsInteropSetter(_) {} //# 49: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 50: compile-time error
|
||||
@JS('a') // GENERIC //# 50: compile-time error
|
||||
instanceJsInteropMethod() {} //# 50: continued
|
||||
|
||||
@JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 51: compile-time error
|
||||
|
|
|
@ -20,16 +20,16 @@ set topLevelSetter(_) {}
|
|||
|
||||
topLevelFunction() {}
|
||||
|
||||
@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED //# 01: compile-time error
|
||||
@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED //# 01: compile-time error
|
||||
var topLevelJsInteropField; //# 01: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 02: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 02: compile-time error
|
||||
get topLevelJsInteropGetter => null; //# 02: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 03: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 03: compile-time error
|
||||
set topLevelJsInteropSetter(_) {} //# 03: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 04: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 04: compile-time error
|
||||
topLevelJsInteropFunction() {} //# 04: continued
|
||||
|
||||
// NON_NATIVE_EXTERNAL //# 05: compile-time error
|
||||
|
@ -60,9 +60,6 @@ class Class {
|
|||
// NON_NATIVE_EXTERNAL //# 09: compile-time error
|
||||
external factory Class.externalFact(); //# 09: continued
|
||||
|
||||
@JS('a') // GENERIC, GENERIC //# 10: compile-time error
|
||||
Class.jsInteropGenerative(); //# 10: continued
|
||||
|
||||
@JS('a') // GENERIC //# 11: compile-time error
|
||||
factory Class.jsInteropFact() => null; //# 11: continued
|
||||
|
||||
|
@ -169,13 +166,13 @@ class JsInteropClass {
|
|||
// IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 38: compile-time error
|
||||
var instanceField; //# 38: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 39: compile-time error
|
||||
// GENERIC //# 39: compile-time error
|
||||
get instanceGetter => null; //# 39: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 40: compile-time error
|
||||
// GENERIC //# 40: compile-time error
|
||||
set instanceSetter(_) {} //# 40: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 41: compile-time error
|
||||
// GENERIC //# 41: compile-time error
|
||||
instanceMethod() {} //# 41: continued
|
||||
|
||||
// IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 42: compile-time error
|
||||
|
@ -193,13 +190,13 @@ class JsInteropClass {
|
|||
@JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 46: compile-time error
|
||||
var instanceJsInteropField; //# 46: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 48: compile-time error
|
||||
@JS('a') // GENERIC //# 48: compile-time error
|
||||
get instanceJsInteropGetter => null; //# 48: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 49: compile-time error
|
||||
@JS('a') // GENERIC //# 49: compile-time error
|
||||
set instanceJsInteropSetter(_) {} //# 49: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 50: compile-time error
|
||||
@JS('a') // GENERIC //# 50: compile-time error
|
||||
instanceJsInteropMethod() {} //# 50: continued
|
||||
|
||||
@JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 51: compile-time error
|
||||
|
|
|
@ -23,16 +23,16 @@ set topLevelSetter(_) {}
|
|||
|
||||
topLevelFunction() {}
|
||||
|
||||
@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED //# 01: compile-time error
|
||||
@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED //# 01: compile-time error
|
||||
var topLevelJsInteropField; //# 01: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 02: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 02: compile-time error
|
||||
get topLevelJsInteropGetter => null; //# 02: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 03: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 03: compile-time error
|
||||
set topLevelJsInteropSetter(_) {} //# 03: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 04: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 04: compile-time error
|
||||
topLevelJsInteropFunction() {} //# 04: continued
|
||||
|
||||
external get externalTopLevelGetter;
|
||||
|
@ -52,7 +52,7 @@ external externalTopLevelJsInteropFunction();
|
|||
|
||||
class Class {
|
||||
Class.generative();
|
||||
factory Class.fact() => null;
|
||||
factory Class.fact() => null as dynamic;
|
||||
|
||||
// NON_NATIVE_EXTERNAL //# 08: compile-time error
|
||||
external Class.externalGenerative(); //# 08: continued
|
||||
|
@ -60,7 +60,7 @@ class Class {
|
|||
// NON_NATIVE_EXTERNAL //# 09: compile-time error
|
||||
external factory Class.externalFact(); //# 09: continued
|
||||
|
||||
@JS('a') // GENERIC, GENERIC //# 10: compile-time error
|
||||
@JS('a') // GENERIC //# 10: compile-time error
|
||||
Class.jsInteropGenerative(); //# 10: continued
|
||||
|
||||
@JS('a') // GENERIC //# 11: compile-time error
|
||||
|
@ -97,7 +97,7 @@ class Class {
|
|||
@JS('a') // GENERIC //# 18: compile-time error
|
||||
static var staticJsInteropField; //# 18: continued
|
||||
|
||||
@JS('a') // GENERIC //# 19: compile-time error
|
||||
@JS('a') // GENERIC //# 19: compile-time error
|
||||
static get staticJsInteropGetter => null; //# 19: continued
|
||||
|
||||
@JS('a') // GENERIC //# 20: compile-time error
|
||||
|
@ -169,13 +169,13 @@ class JsInteropClass {
|
|||
// IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 38: compile-time error
|
||||
var instanceField; //# 38: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 39: compile-time error
|
||||
// GENERIC //# 39: compile-time error
|
||||
get instanceGetter => null; //# 39: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 40: compile-time error
|
||||
// GENERIC //# 40: compile-time error
|
||||
set instanceSetter(_) {} //# 40: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 41: compile-time error
|
||||
// GENERIC //# 41: compile-time error
|
||||
instanceMethod() {} //# 41: continued
|
||||
|
||||
// IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 42: compile-time error
|
||||
|
@ -190,16 +190,16 @@ class JsInteropClass {
|
|||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 45: compile-time error
|
||||
static staticMethod() {} //# 45: continued
|
||||
|
||||
@JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 46: compile-time error
|
||||
@JS('a') // GENERIC //# 46: compile-time error
|
||||
var instanceJsInteropField; //# 46: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 48: compile-time error
|
||||
@JS('a') // GENERIC //# 48: compile-time error
|
||||
get instanceJsInteropGetter => null; //# 48: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 49: compile-time error
|
||||
@JS('a') // GENERIC //# 49: compile-time error
|
||||
set instanceJsInteropSetter(_) {} //# 49: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 50: compile-time error
|
||||
@JS('a') // GENERIC //# 50: compile-time error
|
||||
instanceJsInteropMethod() {} //# 50: continued
|
||||
|
||||
@JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 51: compile-time error
|
||||
|
|
|
@ -22,16 +22,16 @@ set topLevelSetter(_) {}
|
|||
|
||||
topLevelFunction() {}
|
||||
|
||||
@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED //# 01: compile-time error
|
||||
@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED //# 01: compile-time error
|
||||
var topLevelJsInteropField; //# 01: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 02: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 02: compile-time error
|
||||
get topLevelJsInteropGetter => null; //# 02: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 03: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 03: compile-time error
|
||||
set topLevelJsInteropSetter(_) {} //# 03: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 04: compile-time error
|
||||
@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER //# 04: compile-time error
|
||||
topLevelJsInteropFunction() {} //# 04: continued
|
||||
|
||||
// NON_NATIVE_EXTERNAL //# 05: compile-time error
|
||||
|
@ -54,7 +54,7 @@ external externalTopLevelJsInteropFunction();
|
|||
|
||||
class Class {
|
||||
Class.generative();
|
||||
factory Class.fact() => null;
|
||||
factory Class.fact() => null as dynamic;
|
||||
|
||||
// NON_NATIVE_EXTERNAL //# 08: compile-time error
|
||||
external Class.externalGenerative(); //# 08: continued
|
||||
|
@ -62,9 +62,6 @@ class Class {
|
|||
// NON_NATIVE_EXTERNAL //# 09: compile-time error
|
||||
external factory Class.externalFact(); //# 09: continued
|
||||
|
||||
@JS('a') // GENERIC, GENERIC //# 10: compile-time error
|
||||
Class.jsInteropGenerative(); //# 10: continued
|
||||
|
||||
@JS('a') // GENERIC //# 11: compile-time error
|
||||
factory Class.jsInteropFact() => null; //# 11: continued
|
||||
|
||||
|
@ -171,13 +168,13 @@ class JsInteropClass {
|
|||
// IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 38: compile-time error
|
||||
var instanceField; //# 38: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 39: compile-time error
|
||||
// GENERIC //# 39: compile-time error
|
||||
get instanceGetter => null; //# 39: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 40: compile-time error
|
||||
// GENERIC //# 40: compile-time error
|
||||
set instanceSetter(_) {} //# 40: continued
|
||||
|
||||
// JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 41: compile-time error
|
||||
// GENERIC //# 41: compile-time error
|
||||
instanceMethod() {} //# 41: continued
|
||||
|
||||
// IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 42: compile-time error
|
||||
|
@ -195,13 +192,13 @@ class JsInteropClass {
|
|||
@JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 46: compile-time error
|
||||
var instanceJsInteropField; //# 46: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 48: compile-time error
|
||||
@JS('a') // GENERIC //# 48: compile-time error
|
||||
get instanceJsInteropGetter => null; //# 48: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 49: compile-time error
|
||||
@JS('a') // GENERIC //# 49: compile-time error
|
||||
set instanceJsInteropSetter(_) {} //# 49: continued
|
||||
|
||||
@JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 50: compile-time error
|
||||
@JS('a') // GENERIC //# 50: compile-time error
|
||||
instanceJsInteropMethod() {} //# 50: continued
|
||||
|
||||
@JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 51: compile-time error
|
||||
|
|
196
tests/lib/js/external_member_static_test.dart
Normal file
196
tests/lib/js/external_member_static_test.dart
Normal file
|
@ -0,0 +1,196 @@
|
|||
// Copyright (c) 2020, 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.
|
||||
|
||||
// Tests static errors for JS interop members without an external keyword.
|
||||
|
||||
@JS()
|
||||
library external_member_static_test;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
|
||||
@JS()
|
||||
class JSClass {
|
||||
int? field;
|
||||
|
||||
@JS()
|
||||
int? fieldWithJS;
|
||||
|
||||
static int? staticField;
|
||||
|
||||
@JS()
|
||||
static int? staticFieldWithJS;
|
||||
|
||||
JSClass.constructor();
|
||||
//^
|
||||
// [web] JS interop classes do not support non-external constructors.
|
||||
@JS()
|
||||
JSClass.constructorWithJS();
|
||||
//^
|
||||
// [web] JS interop classes do not support non-external constructors.
|
||||
|
||||
// Dart factories of a JS interop class are allowed.
|
||||
factory JSClass.fact() => JSClass.constructor();
|
||||
|
||||
factory JSClass.redirectingFactory() = JSClass.constructor;
|
||||
|
||||
external factory JSClass.externalFactory();
|
||||
|
||||
@JS()
|
||||
factory JSClass.factoryWithJS() => JSClass.fact();
|
||||
|
||||
int get getSet => 0;
|
||||
// ^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
@JS()
|
||||
int get getSetWithJS => 0;
|
||||
// ^^^^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
set getSet(int val) {}
|
||||
// ^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
@JS()
|
||||
set getSetWithJS(int val) {}
|
||||
// ^^^^^^^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
int method() => 0;
|
||||
// ^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
@JS()
|
||||
int methodWithJS() => 0;
|
||||
// ^^^^^^^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
|
||||
// Static methods on JS interop classes are allowed.
|
||||
static int staticMethod() => 0;
|
||||
|
||||
@JS()
|
||||
static int staticMethodWithJS() => 0;
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class JSAnonymousClass {
|
||||
int? field;
|
||||
|
||||
@JS()
|
||||
int? fieldWithJS;
|
||||
|
||||
static int? staticField;
|
||||
|
||||
@JS()
|
||||
static int? staticFieldWithJS;
|
||||
|
||||
JSAnonymousClass.constructor();
|
||||
//^
|
||||
// [web] JS interop classes do not support non-external constructors.
|
||||
@JS()
|
||||
JSAnonymousClass.constructorWithJS();
|
||||
//^
|
||||
// [web] JS interop classes do not support non-external constructors.
|
||||
|
||||
factory JSAnonymousClass.fact() => JSAnonymousClass.constructor();
|
||||
|
||||
factory JSAnonymousClass.redirectingFactory() = JSAnonymousClass.fact;
|
||||
|
||||
external factory JSAnonymousClass.externalFactory();
|
||||
|
||||
@JS()
|
||||
factory JSAnonymousClass.factoryWithJS() => JSAnonymousClass.fact();
|
||||
|
||||
int get getSet => 0;
|
||||
// ^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
@JS()
|
||||
int get getSetWithJS => 0;
|
||||
// ^^^^^^^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
set getSet(int val) {}
|
||||
// ^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
@JS()
|
||||
set getSetWithJS(int val) {}
|
||||
// ^^^^^^^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
int method() => 0;
|
||||
// ^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
@JS()
|
||||
int methodWithJS() => 0;
|
||||
// ^^^^^^^^^^^^
|
||||
// [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
|
||||
|
||||
static int staticMethod() => 0;
|
||||
|
||||
@JS()
|
||||
static int staticMethodWithJS() => 0;
|
||||
}
|
||||
|
||||
@JS()
|
||||
abstract class JSAbstractClass {
|
||||
int? field;
|
||||
|
||||
@JS()
|
||||
int? fieldWithJS;
|
||||
|
||||
static int? staticField;
|
||||
|
||||
@JS()
|
||||
static int? staticFieldWithJS;
|
||||
|
||||
JSAbstractClass.constructor();
|
||||
//^
|
||||
// [web] JS interop classes do not support non-external constructors.
|
||||
@JS()
|
||||
JSAbstractClass.constructorWithJS();
|
||||
//^
|
||||
// [web] JS interop classes do not support non-external constructors.
|
||||
|
||||
factory JSAbstractClass.fact() => JSAbstractClass.factoryWithJS();
|
||||
|
||||
factory JSAbstractClass.redirectingFactory() = JSAbstractClass.fact;
|
||||
|
||||
external factory JSAbstractClass.externalFactory();
|
||||
|
||||
@JS()
|
||||
factory JSAbstractClass.factoryWithJS() => JSAbstractClass.fact();
|
||||
|
||||
// Members in an abstract class are allowed.
|
||||
int get getSet;
|
||||
|
||||
@JS()
|
||||
int get getSetWithJS;
|
||||
|
||||
set getSet(int val);
|
||||
|
||||
@JS()
|
||||
set getSetWithJS(int val);
|
||||
|
||||
int method();
|
||||
|
||||
@JS()
|
||||
int methodWithJS();
|
||||
|
||||
static int staticMethod() => 0;
|
||||
|
||||
@JS()
|
||||
static int staticMethodWithJS() => 0;
|
||||
}
|
||||
|
||||
@JS()
|
||||
class JSClassWithSyntheticConstructor {}
|
||||
|
||||
@JS()
|
||||
int? globalWithJS;
|
||||
@JS()
|
||||
int get getSetWithJS => 0;
|
||||
@JS()
|
||||
set getSetWithJS(int val) {}
|
||||
@JS()
|
||||
int methodWithJS() => 0;
|
||||
|
||||
external int get getSet;
|
||||
external set getSet(int val);
|
||||
external int method();
|
||||
|
||||
main() {}
|
Loading…
Reference in a new issue