[dart:js_interop] Apply param errors to inline classes

Object literal constructors can't have positional parameters and
inline class members can't have named parameters. Adds tests and
rewords existing errors relating to parameters.

Change-Id: I9a25118b26b6b51857c2a455432ac84d96573e14
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/292241
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
This commit is contained in:
Srujan Gaddam 2023-05-22 21:50:51 +00:00 committed by Commit Queue
parent 9998ad2561
commit 383520d6ed
7 changed files with 123 additions and 52 deletions

View file

@ -7706,18 +7706,6 @@ Message _withArgumentsJointPatternVariablesMismatch(String name) {
arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeJsInteropAnonymousFactoryPositionalParameters =
messageJsInteropAnonymousFactoryPositionalParameters;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageJsInteropAnonymousFactoryPositionalParameters =
const MessageCode("JsInteropAnonymousFactoryPositionalParameters",
problemMessage:
r"""Factory constructors for @anonymous JS interop classes should not contain any positional parameters.""",
correctionMessage:
r"""Try replacing them with named parameters instead.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
@ -8023,7 +8011,7 @@ const Code<Null> codeJsInteropNamedParameters = messageJsInteropNamedParameters;
const MessageCode messageJsInteropNamedParameters = const MessageCode(
"JsInteropNamedParameters",
problemMessage:
r"""Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.""",
r"""Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.""",
correctionMessage:
r"""Try replacing them with normal or optional parameters.""");
@ -8118,6 +8106,36 @@ Message _withArgumentsJsInteropNonStaticWithStaticInteropSupertype(
arguments: {'name': name, 'name2': name2});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String string)>
templateJsInteropObjectLiteralConstructorPositionalParameters =
const Template<Message Function(String string)>(
problemMessageTemplate:
r"""#string should not contain any positional parameters.""",
correctionMessageTemplate:
r"""Try replacing them with named parameters instead.""",
withArguments:
_withArgumentsJsInteropObjectLiteralConstructorPositionalParameters);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String string)>
codeJsInteropObjectLiteralConstructorPositionalParameters =
const Code<Message Function(String string)>(
"JsInteropObjectLiteralConstructorPositionalParameters",
);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsJsInteropObjectLiteralConstructorPositionalParameters(
String string) {
if (string.isEmpty) throw 'No string provided';
return new Message(codeJsInteropObjectLiteralConstructorPositionalParameters,
problemMessage:
"""${string} should not contain any positional parameters.""",
correctionMessage:
"""Try replacing them with named parameters instead.""",
arguments: {'string': string});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeJsInteropOperatorsNotSupported =
messageJsInteropOperatorsNotSupported;

View file

@ -8,7 +8,6 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
show
Message,
LocatedMessage,
messageJsInteropAnonymousFactoryPositionalParameters,
messageJsInteropDartJsInteropAnnotationForStaticInteropOnly,
messageJsInteropEnclosingClassJSAnnotation,
messageJsInteropEnclosingClassJSAnnotationContext,
@ -24,11 +23,12 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
messageJsInteropStaticInteropGenerativeConstructor,
messageJsInteropStaticInteropSyntheticConstructor,
templateJsInteropDartClassExtendsJSClass,
templateJsInteropJSClassExtendsDartClass,
templateJsInteropNonStaticWithStaticInteropSupertype,
templateJsInteropStaticInteropNoJSAnnotation,
templateJsInteropStaticInteropWithInstanceMembers,
templateJsInteropStaticInteropWithNonStaticSupertype,
templateJsInteropJSClassExtendsDartClass,
templateJsInteropObjectLiteralConstructorPositionalParameters,
templateJsInteropNativeClassInAnnotation,
templateJsInteropStaticInteropTearOffsDisallowed,
templateJsInteropStaticInteropTrustTypesUsageNotAllowed,
@ -435,18 +435,18 @@ class JsInteropChecks extends RecursiveVisitor {
}
// Check JS Interop positional and named parameters.
final isObjectLiteralFactory =
_classHasAnonymousAnnotation && node.isFactory ||
node.isInlineClassMember && hasObjectLiteralAnnotation(node);
if (isObjectLiteralFactory) {
final isObjectLiteralConstructor =
node.isInlineClassMember && hasObjectLiteralAnnotation(node);
final isAnonymousFactory = _classHasAnonymousAnnotation && node.isFactory;
if (isObjectLiteralConstructor || isAnonymousFactory) {
var positionalParams = node.function.positionalParameters;
if (node.isInlineClassMember) {
positionalParams = positionalParams.skip(1).toList();
}
if (node.function.positionalParameters.isNotEmpty) {
if (positionalParams.isNotEmpty) {
final firstPositionalParam = positionalParams[0];
_diagnosticsReporter.report(
messageJsInteropAnonymousFactoryPositionalParameters,
templateJsInteropObjectLiteralConstructorPositionalParameters
.withArguments(isObjectLiteralConstructor
? 'Object literal constructors'
: '@anonymous factories'),
firstPositionalParam.fileOffset,
firstPositionalParam.name!.length,
firstPositionalParam.location!.file);

View file

@ -566,8 +566,6 @@ InvalidVoid/part_wrapped_script2: Fail
InvalidVoid/script1: Fail
InvalidVoid/script2: Fail
JointPatternVariablesMismatch/analyzerCode: Fail
JsInteropAnonymousFactoryPositionalParameters/analyzerCode: Fail # Web compiler specific
JsInteropAnonymousFactoryPositionalParameters/example: Fail # Web compiler specific
JsInteropDartClassExtendsJSClass/analyzerCode: Fail # Web compiler specific
JsInteropDartClassExtendsJSClass/example: Fail # Web compiler specific
JsInteropDartJsInteropAnnotationForStaticInteropOnly/analyzerCode: Fail # Web compiler specific
@ -610,6 +608,8 @@ JsInteropNonStaticWithStaticInteropSupertype/analyzerCode: Fail # Web compiler s
JsInteropNonStaticWithStaticInteropSupertype/example: Fail # Web compiler specific
JsInteropOperatorsNotSupported/analyzerCode: Fail # Web compiler specific
JsInteropOperatorsNotSupported/example: Fail # Web compiler specific
JsInteropObjectLiteralConstructorPositionalParameters/analyzerCode: Fail # Web compiler specific
JsInteropObjectLiteralConstructorPositionalParameters/example: Fail # Web compiler specific
JsInteropStaticInteropExternalExtensionMembersWithTypeParameters/analyzerCode: Fail # Web compiler specific
JsInteropStaticInteropExternalExtensionMembersWithTypeParameters/example: Fail # Web compiler specific
JsInteropStaticInteropGenerativeConstructor/analyzerCode: Fail # Web compiler specific

View file

@ -5439,10 +5439,6 @@ NullableInterfaceError:
NullableMixinError:
problemMessage: "Can't mix '#name' in because it's marked with '?'."
JsInteropAnonymousFactoryPositionalParameters:
problemMessage: "Factory constructors for @anonymous JS interop classes should not contain any positional parameters."
correctionMessage: "Try replacing them with named parameters instead."
JsInteropDartClassExtendsJSClass:
problemMessage: "Dart class '#name' cannot extend JS interop class '#name2'."
correctionMessage: "Try adding the JS interop annotation or removing it from the parent class."
@ -5508,7 +5504,7 @@ JsInteropJSClassExtendsDartClass:
correctionMessage: "Try removing the JS interop annotation or adding it to the parent class."
JsInteropNamedParameters:
problemMessage: "Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class."
problemMessage: "Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories."
correctionMessage: "Try replacing them with normal or optional parameters."
JsInteropNativeClassInAnnotation:
@ -5523,6 +5519,10 @@ JsInteropNonExternalMember:
problemMessage: "This JS interop member must be annotated with `external`. Only factories and static methods can be non-external."
correctionMessage: "Try annotating the member with `external`."
JsInteropObjectLiteralConstructorPositionalParameters:
problemMessage: "#string should not contain any positional parameters."
correctionMessage: "Try replacing them with named parameters instead."
JsInteropOperatorsNotSupported:
problemMessage: "JS interop classes do not support operator methods."
correctionMessage: "Try replacing this with a normal method."

View file

@ -15,10 +15,10 @@ import 'package:expect/expect.dart';
class Foo {
external Foo({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external factory Foo.fooFactory({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
}
@JS()
@ -26,21 +26,21 @@ class Foo {
class Bar {
external Bar({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
// Factories of an anonymous class can only contain named parameters.
external factory Bar.barFactoryPositional(int? a);
// ^
// [web] Factory constructors for @anonymous JS interop classes should not contain any positional parameters.
// [web] @anonymous factories should not contain any positional parameters.
external factory Bar.barFactoryOptional([int? a]);
// ^
// [web] Factory constructors for @anonymous JS interop classes should not contain any positional parameters.
// [web] @anonymous factories should not contain any positional parameters.
external factory Bar.barFactoryMixedOptional(int? a, [int? b]);
// ^
// [web] Factory constructors for @anonymous JS interop classes should not contain any positional parameters.
// [web] @anonymous factories should not contain any positional parameters.
external factory Bar.barFactoryMixedNamed(int? a, {int? b});
// ^
// [web] Factory constructors for @anonymous JS interop classes should not contain any positional parameters.
// [web] @anonymous factories should not contain any positional parameters.
// Named parameters are okay only for factories of an anonymous class.
external factory Bar.barFactoryNamed({int? a});
@ -50,10 +50,10 @@ class Bar {
abstract class Baz {
external Baz({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external factory Baz.bazFactory({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
}
main() {}

View file

@ -14,57 +14,57 @@ import 'package:expect/expect.dart';
class Foo {
external int singleNamedArg({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external int mixedNamedArgs(int a, {int? b});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
}
@JS()
class Bar {
external static int singleNamedArg({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external static int mixedNamedArgs(int a, {int? b});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
}
external int singleNamedArg({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external int mixedNamedArgs(int a, {int? b});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
@JS()
@anonymous
class Baz {
external int singleNamedArg({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external int mixedNamedArgs(int a, {int? b});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
}
@JS()
abstract class Qux {
external int singleNamedArg({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external int mixedNamedArgs(int a, {int? b});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
}
extension ExtensionFoo on Foo {
external int singleNamedArg({int? a});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external int mixedNamedArgs(int a, {int? b});
// ^
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
}
main() {}

View file

@ -0,0 +1,53 @@
// Copyright (c) 2023, 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.
// SharedOptions=--enable-experiment=inline-class
import 'dart:js_interop';
@JS()
external void topLevel({JSNumber named});
// ^
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
@JS()
inline class Inline {
external Inline({JSNumber named});
// ^
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external Inline.positionalNamed(JSNumber positional, {JSNumber named});
// ^
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external static void staticMethod({JSNumber named});
// ^
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
external void method({JSNumber named});
// ^
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
@ObjectLiteral()
external Inline.positionalLiteral(JSNumber positional);
// ^
// [web] Object literal constructors should not contain any positional parameters.
@ObjectLiteral()
external Inline.optionalLiteral([JSNumber optional]);
// ^
// [web] Object literal constructors should not contain any positional parameters.
@ObjectLiteral()
external Inline.positionalOptionalLiteral(JSNumber positional,
// ^
// [web] Object literal constructors should not contain any positional parameters.
[JSNumber optional]);
@ObjectLiteral()
external Inline.positionalNamedLiteral(JSNumber positional, {JSNumber named});
// ^
// [web] Object literal constructors should not contain any positional parameters.
}
extension on Inline {
external void extensionMethod({JSNumber named});
// ^
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
}
void main() {}