[pkg:js] Disallow all operators in JS classes

Closes https://github.com/dart-lang/sdk/issues/48515

Expands existing checks for index operations to all operators. This
only affects instance members and not extension members.

Change-Id: I8cbb5b12a49539ea502e4396e1b469ffb0e17d5e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/235980
Reviewed-by: Riley Porter <rileyporter@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index a9ec81e..6035330 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -6569,17 +6569,6 @@
         r"""Try removing the 'external' keyword or adding a JS interop annotation.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeJsInteropIndexNotSupported =
-    messageJsInteropIndexNotSupported;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageJsInteropIndexNotSupported = const MessageCode(
-    "JsInteropIndexNotSupported",
-    problemMessage:
-        r"""JS interop classes do not support [] and []= operator methods.""",
-    correctionMessage: r"""Try replacing with a normal method.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         String name,
@@ -6685,6 +6674,16 @@
     correctionMessage: r"""Try annotating the member with `external`.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeJsInteropOperatorsNotSupported =
+    messageJsInteropOperatorsNotSupported;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageJsInteropOperatorsNotSupported = const MessageCode(
+    "JsInteropOperatorsNotSupported",
+    problemMessage: r"""JS interop classes do not support operator methods.""",
+    correctionMessage: r"""Try replacing this with a normal method.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(String name)>
     templateJsInteropStaticInteropWithInstanceMembers =
     const Template<Message Function(String name)>(
diff --git a/pkg/_js_interop_checks/lib/js_interop_checks.dart b/pkg/_js_interop_checks/lib/js_interop_checks.dart
index 6dab119..26d8396 100644
--- a/pkg/_js_interop_checks/lib/js_interop_checks.dart
+++ b/pkg/_js_interop_checks/lib/js_interop_checks.dart
@@ -14,10 +14,10 @@
         messageJsInteropEnclosingClassJSAnnotationContext,
         messageJsInteropExternalExtensionMemberOnTypeInvalid,
         messageJsInteropExternalMemberNotJSAnnotated,
-        messageJsInteropIndexNotSupported,
         messageJsInteropNamedParameters,
         messageJsInteropNonExternalConstructor,
         messageJsInteropNonExternalMember,
+        messageJsInteropOperatorsNotSupported,
         templateJsInteropDartClassExtendsJSClass,
         templateJsInteropStaticInteropWithInstanceMembers,
         templateJsInteropStaticInteropWithNonStaticSupertype,
@@ -220,10 +220,9 @@
       _checkDisallowedExternal(procedure);
     } else {
       // Check JS interop indexing.
-      if (!procedure.isStatic &&
-          (procedure.name.text == '[]=' || procedure.name.text == '[]')) {
+      if (!procedure.isStatic && procedure.kind == ProcedureKind.Operator) {
         _diagnosticsReporter.report(
-            messageJsInteropIndexNotSupported,
+            messageJsInteropOperatorsNotSupported,
             procedure.fileOffset,
             procedure.name.text.length,
             procedure.fileUri);
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 6563de2..a4710b5 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -546,8 +546,6 @@
 JsInteropExternalExtensionMemberOnTypeInvalid/example: Fail # Web compiler specific
 JsInteropExternalMemberNotJSAnnotated/analyzerCode: Fail # Web compiler specific
 JsInteropExternalMemberNotJSAnnotated/example: Fail # Web compiler specific
-JsInteropIndexNotSupported/analyzerCode: Fail # Web compiler specific
-JsInteropIndexNotSupported/example: Fail # Web compiler specific
 JsInteropJSClassExtendsDartClass/analyzerCode: Fail # Web compiler specific
 JsInteropJSClassExtendsDartClass/example: Fail # Web compiler specific
 JsInteropNamedParameters/analyzerCode: Fail # Web compiler specific
@@ -558,6 +556,8 @@
 JsInteropNonExternalConstructor/example: Fail # Web compiler specific
 JsInteropNonExternalMember/analyzerCode: Fail # Web compiler specific
 JsInteropNonExternalMember/example: Fail # Web compiler specific
+JsInteropOperatorsNotSupported/analyzerCode: Fail # Web compiler specific
+JsInteropOperatorsNotSupported/example: Fail # Web compiler specific
 JsInteropStaticInteropWithInstanceMembers/analyzerCode: Fail # Web compiler specific
 JsInteropStaticInteropWithInstanceMembers/example: Fail # Web compiler specific
 JsInteropStaticInteropWithNonStaticSupertype/analyzerCode: Fail # Web compiler specific
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index d165d4c..21e529c 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -5096,18 +5096,6 @@
   problemMessage: "Only JS interop members may be 'external'."
   correctionMessage: "Try removing the 'external' keyword or adding a JS interop annotation."
 
-JsInteropIndexNotSupported:
-  problemMessage: "JS interop classes do not support [] and []= operator methods."
-  correctionMessage: "Try replacing with a normal method."
-
-JsInteropStaticInteropWithInstanceMembers:
-  problemMessage: "JS interop class '#name' with `@staticInterop` annotation cannot declare instance members."
-  correctionMessage: "Try moving the instance member to a static extension."
-
-JsInteropStaticInteropWithNonStaticSupertype:
-  problemMessage: "JS interop class '#name' has an `@staticInterop` annotation, but has supertype '#name2', which is non-static."
-  correctionMessage: "Try marking the supertype as a static interop class using `@staticInterop`."
-
 JsInteropJSClassExtendsDartClass:
   problemMessage: "JS interop class '#name' cannot extend Dart class '#name2'."
   correctionMessage: "Try removing the JS interop annotation or adding it to the parent class."
@@ -5128,6 +5116,18 @@
   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`."
 
+JsInteropOperatorsNotSupported:
+  problemMessage: "JS interop classes do not support operator methods."
+  correctionMessage: "Try replacing this with a normal method."
+
+JsInteropStaticInteropWithInstanceMembers:
+  problemMessage: "JS interop class '#name' with `@staticInterop` annotation cannot declare instance members."
+  correctionMessage: "Try moving the instance member to a static extension."
+
+JsInteropStaticInteropWithNonStaticSupertype:
+  problemMessage: "JS interop class '#name' has an `@staticInterop` annotation, but has supertype '#name2', which is non-static."
+  correctionMessage: "Try marking the supertype as a static interop class using `@staticInterop`."
+
 DefaultListConstructorError:
   problemMessage: "Can't use the default List constructor."
   correctionMessage: "Try using List.filled instead."
diff --git a/tests/lib/js/operator_test.dart b/tests/lib/js/operator_test.dart
new file mode 100644
index 0000000..cd688cc
--- /dev/null
+++ b/tests/lib/js/operator_test.dart
@@ -0,0 +1,170 @@
+// Copyright (c) 2022, 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.
+
+@JS()
+library operator_test;
+
+import 'package:js/js.dart';
+
+@JS()
+class JSClass {
+  // https://dart.dev/guides/language/language-tour#_operators for the list of
+  // operators allowed by the language.
+  external void operator <(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator <=(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >=(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator -(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator +(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator /(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ~/(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator *(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator %(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator |(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ^(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator &(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator <<(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >>(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >>>(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator [](_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator []=(_, __);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ~();
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external bool operator ==(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+}
+
+@JS()
+@anonymous
+class AnonymousClass {
+  external void operator <(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator <=(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >=(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator -(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator +(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator /(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ~/(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator *(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator %(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator |(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ^(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator &(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator <<(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >>(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >>>(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator [](_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator []=(_, __);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ~();
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external bool operator ==(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+}
+
+@JS()
+class JSClassExtensions {}
+
+extension _ on JSClassExtensions {
+  // External operators in extensions are allowed for now, but don't work as
+  // intended. Specific operators will need to be allowlisted in the future.
+  // TODO(srujzs): Remove this test once we do that.
+  external void operator <(_);
+  external void operator >(_);
+  external void operator <=(_);
+  external void operator >=(_);
+  external void operator -(_);
+  external void operator +(_);
+  external void operator /(_);
+  external void operator ~/(_);
+  external void operator *(_);
+  external void operator %(_);
+  external void operator |(_);
+  external void operator ^(_);
+  external void operator &(_);
+  external void operator <<(_);
+  external void operator >>(_);
+  external void operator >>>(_);
+  external void operator [](_);
+  external void operator []=(_, __);
+  external void operator ~();
+  // No `==` as it's an `Object` method.
+}
+
+void main() {}
diff --git a/tests/lib_2/js/operator_test.dart b/tests/lib_2/js/operator_test.dart
new file mode 100644
index 0000000..cd688cc
--- /dev/null
+++ b/tests/lib_2/js/operator_test.dart
@@ -0,0 +1,170 @@
+// Copyright (c) 2022, 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.
+
+@JS()
+library operator_test;
+
+import 'package:js/js.dart';
+
+@JS()
+class JSClass {
+  // https://dart.dev/guides/language/language-tour#_operators for the list of
+  // operators allowed by the language.
+  external void operator <(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator <=(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >=(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator -(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator +(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator /(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ~/(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator *(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator %(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator |(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ^(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator &(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator <<(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >>(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >>>(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator [](_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator []=(_, __);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ~();
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external bool operator ==(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+}
+
+@JS()
+@anonymous
+class AnonymousClass {
+  external void operator <(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator <=(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >=(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator -(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator +(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator /(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ~/(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator *(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator %(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator |(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ^(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator &(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator <<(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >>(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator >>>(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator [](_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator []=(_, __);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external void operator ~();
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+  external bool operator ==(_);
+  //                     ^
+  // [web] JS interop classes do not support operator methods.
+}
+
+@JS()
+class JSClassExtensions {}
+
+extension _ on JSClassExtensions {
+  // External operators in extensions are allowed for now, but don't work as
+  // intended. Specific operators will need to be allowlisted in the future.
+  // TODO(srujzs): Remove this test once we do that.
+  external void operator <(_);
+  external void operator >(_);
+  external void operator <=(_);
+  external void operator >=(_);
+  external void operator -(_);
+  external void operator +(_);
+  external void operator /(_);
+  external void operator ~/(_);
+  external void operator *(_);
+  external void operator %(_);
+  external void operator |(_);
+  external void operator ^(_);
+  external void operator &(_);
+  external void operator <<(_);
+  external void operator >>(_);
+  external void operator >>>(_);
+  external void operator [](_);
+  external void operator []=(_, __);
+  external void operator ~();
+  // No `==` as it's an `Object` method.
+}
+
+void main() {}