[tint][resolver] Standardise attribute diagnostics

Use '@blah', instead of 'blah attribute'.
This is less verbose, and is closer to the user code.

Also change '@X must only be used with @Y' to '@X can only be used with @Y' in attribute diagnostics.
This is to avoid interpretation that only '@X' and '@Y' can exist on an AST node.

Change-Id: Ied96f5344f5ab6efeee15fd52b63bbf3965c9f7d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/159782
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
index 43ec16a..a82437d 100644
--- a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
@@ -744,7 +744,7 @@
         },
         TestParams{
             {AttributeKind::kInterpolate, AttributeKind::kBuiltinPosition},
-            R"(1:2 error: interpolate attribute must only be used with @location)",
+            R"(1:2 error: @interpolate can only be used with @location)",
         },
         TestParams{
             {AttributeKind::kInterpolate, AttributeKind::kLocation},
@@ -855,7 +855,7 @@
         },
         TestParams{
             {AttributeKind::kInvariant, AttributeKind::kLocation},
-            R"(1:2 error: invariant attribute must only be applied to a position builtin)",
+            R"(1:2 error: @invariant must be applied to a position builtin)",
         },
         TestParams{
             {AttributeKind::kInvariant, AttributeKind::kBuiltinPosition},
@@ -1038,7 +1038,7 @@
         },
         TestParams{
             {AttributeKind::kInvariant, AttributeKind::kLocation},
-            R"(1:2 error: invariant attribute must only be applied to a position builtin)",
+            R"(1:2 error: @invariant must be applied to a position builtin)",
         },
         TestParams{
             {AttributeKind::kLocation},
@@ -1130,7 +1130,7 @@
         },
         TestParams{
             {AttributeKind::kInterpolate},
-            R"(1:2 error: interpolate attribute must only be used with @location)",
+            R"(1:2 error: @interpolate can only be used with @location)",
         },
         TestParams{
             {AttributeKind::kInvariant},
@@ -1297,91 +1297,90 @@
 
     CHECK();
 }
-INSTANTIATE_TEST_SUITE_P(
-    ResolverAttributeValidationTest,
-    StructMemberAttributeTest,
-    testing::Values(
-        TestParams{
-            {AttributeKind::kAlign},
-            Pass,
-        },
-        TestParams{
-            {AttributeKind::kBinding},
-            R"(1:2 error: @binding is not valid for struct members)",
-        },
-        TestParams{
-            {AttributeKind::kBuiltinPosition},
-            Pass,
-        },
-        TestParams{
-            {AttributeKind::kDiagnostic},
-            R"(1:2 error: @diagnostic is not valid for struct members)",
-        },
-        TestParams{
-            {AttributeKind::kGroup},
-            R"(1:2 error: @group is not valid for struct members)",
-        },
-        TestParams{
-            {AttributeKind::kId},
-            R"(1:2 error: @id is not valid for struct members)",
-        },
-        TestParams{
-            {AttributeKind::kIndex},
-            R"(1:2 error: index attribute must only be used with @location)",
-        },
-        TestParams{
-            {AttributeKind::kInterpolate},
-            R"(1:2 error: interpolate attribute must only be used with @location)",
-        },
-        TestParams{
-            {AttributeKind::kInterpolate, AttributeKind::kLocation},
-            Pass,
-        },
-        TestParams{
-            {AttributeKind::kInvariant},
-            R"(1:2 error: invariant attribute must only be applied to a position builtin)",
-        },
-        TestParams{
-            {AttributeKind::kInvariant, AttributeKind::kBuiltinPosition},
-            Pass,
-        },
-        TestParams{
-            {AttributeKind::kLocation},
-            Pass,
-        },
-        TestParams{
-            {AttributeKind::kMustUse},
-            R"(1:2 error: @must_use is not valid for struct members)",
-        },
-        TestParams{
-            {AttributeKind::kOffset},
-            Pass,
-        },
-        TestParams{
-            {AttributeKind::kSize},
-            Pass,
-        },
-        TestParams{
-            {AttributeKind::kStageCompute},
-            R"(1:2 error: @stage is not valid for struct members)",
-        },
-        TestParams{
-            {AttributeKind::kStride},
-            R"(1:2 error: @stride is not valid for struct members)",
-        },
-        TestParams{
-            {AttributeKind::kWorkgroupSize},
-            R"(1:2 error: @workgroup_size is not valid for struct members)",
-        },
-        TestParams{
-            {AttributeKind::kBinding, AttributeKind::kGroup},
-            R"(1:2 error: @binding is not valid for struct members)",
-        },
-        TestParams{
-            {AttributeKind::kAlign, AttributeKind::kAlign},
-            R"(3:4 error: duplicate align attribute
+INSTANTIATE_TEST_SUITE_P(ResolverAttributeValidationTest,
+                         StructMemberAttributeTest,
+                         testing::Values(
+                             TestParams{
+                                 {AttributeKind::kAlign},
+                                 Pass,
+                             },
+                             TestParams{
+                                 {AttributeKind::kBinding},
+                                 R"(1:2 error: @binding is not valid for struct members)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kBuiltinPosition},
+                                 Pass,
+                             },
+                             TestParams{
+                                 {AttributeKind::kDiagnostic},
+                                 R"(1:2 error: @diagnostic is not valid for struct members)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kGroup},
+                                 R"(1:2 error: @group is not valid for struct members)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kId},
+                                 R"(1:2 error: @id is not valid for struct members)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kIndex},
+                                 R"(1:2 error: @index can only be used with @location)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kInterpolate},
+                                 R"(1:2 error: @interpolate can only be used with @location)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kInterpolate, AttributeKind::kLocation},
+                                 Pass,
+                             },
+                             TestParams{
+                                 {AttributeKind::kInvariant},
+                                 R"(1:2 error: @invariant must be applied to a position builtin)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kInvariant, AttributeKind::kBuiltinPosition},
+                                 Pass,
+                             },
+                             TestParams{
+                                 {AttributeKind::kLocation},
+                                 Pass,
+                             },
+                             TestParams{
+                                 {AttributeKind::kMustUse},
+                                 R"(1:2 error: @must_use is not valid for struct members)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kOffset},
+                                 Pass,
+                             },
+                             TestParams{
+                                 {AttributeKind::kSize},
+                                 Pass,
+                             },
+                             TestParams{
+                                 {AttributeKind::kStageCompute},
+                                 R"(1:2 error: @stage is not valid for struct members)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kStride},
+                                 R"(1:2 error: @stride is not valid for struct members)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kWorkgroupSize},
+                                 R"(1:2 error: @workgroup_size is not valid for struct members)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kBinding, AttributeKind::kGroup},
+                                 R"(1:2 error: @binding is not valid for struct members)",
+                             },
+                             TestParams{
+                                 {AttributeKind::kAlign, AttributeKind::kAlign},
+                                 R"(3:4 error: duplicate align attribute
 1:2 note: first attribute declared here)",
-        }));
+                             }));
 
 TEST_F(StructMemberAttributeTest, Align_Attribute_Const) {
     GlobalConst("val", ty.i32(), Expr(1_i));
diff --git a/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc b/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc
index cb4489f..6adfb36 100644
--- a/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc
+++ b/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc
@@ -122,7 +122,7 @@
                         });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: index attribute must only be used with @location");
+    EXPECT_EQ(r()->error(), "12:34 error: @index can only be used with @location");
 }
 
 // Using an index attribute on a struct member should pass.
@@ -155,7 +155,7 @@
               });
 
     EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), "12:34 error: index attribute must only be used with @location(0)");
+    EXPECT_EQ(r()->error(), "12:34 error: @index can only be used with @location(0)");
 }
 
 class DualSourceBlendingExtensionTestWithParams : public ResolverTestWithParam<int> {
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index c05eca2..4df0d80 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -1235,8 +1235,7 @@
 
             if (index_attribute) {
                 if (Is<ast::LocationAttribute>(pipeline_io_attribute)) {
-                    AddError("index attribute must only be used with @location",
-                             index_attribute->source);
+                    AddError("@index can only be used with @location", index_attribute->source);
                     return false;
                 }
 
@@ -1244,8 +1243,7 @@
                 // should restrict targets with index attributes to location 0 for easy translation
                 // in the backend writers.
                 if (location.value() != 0) {
-                    AddError("index attribute must only be used with @location(0)",
-                             index_attribute->source);
+                    AddError("@index can only be used with @location(0)", index_attribute->source);
                     return false;
                 }
             }
@@ -1273,7 +1271,7 @@
             if (interpolate_attribute) {
                 if (!pipeline_io_attribute ||
                     !pipeline_io_attribute->Is<ast::LocationAttribute>()) {
-                    AddError("interpolate attribute must only be used with @location",
+                    AddError("@interpolate can only be used with @location",
                              interpolate_attribute->source);
                     return false;
                 }
@@ -1288,7 +1286,7 @@
                     }
                 }
                 if (!has_position) {
-                    AddError("invariant attribute must only be applied to a position builtin",
+                    AddError("@invariant must be applied to a position builtin",
                              invariant_attribute->source);
                     return false;
                 }
@@ -2230,15 +2228,14 @@
         }
 
         if (invariant_attribute && !has_position) {
-            AddError("invariant attribute must only be applied to a position builtin",
+            AddError("@invariant must be applied to a position builtin",
                      invariant_attribute->source);
             return false;
         }
 
         if (index_attribute) {
             if (!location_attribute) {
-                AddError("index attribute must only be used with @location",
-                         index_attribute->source);
+                AddError("@index can only be used with @location", index_attribute->source);
                 return false;
             }
 
@@ -2246,15 +2243,13 @@
             // restrict targets with index attributes to location 0 for easy translation in the
             // backend writers.
             if (member->Attributes().location.value() != 0) {
-                AddError("index attribute must only be used with @location(0)",
-                         index_attribute->source);
+                AddError("@index can only be used with @location(0)", index_attribute->source);
                 return false;
             }
         }
 
         if (interpolate_attribute && !location_attribute) {
-            AddError("interpolate attribute must only be used with @location",
-                     interpolate_attribute->source);
+            AddError("@interpolate can only be used with @location", interpolate_attribute->source);
             return false;
         }