[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:
Srujan Gaddam 2020-09-25 23:30:34 +00:00 committed by commit-bot@chromium.org
parent f0d1fe173c
commit c990450628
13 changed files with 325 additions and 124 deletions

View file

@ -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<

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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,

View file

@ -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,

View file

@ -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.',
'''

View file

@ -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.

View file

@ -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."

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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() {}