Import Tint changes from Dawn
Changes:
- 95cd216962b6d70e233b725f70f2a1bac8d112c1 [tint][wgsl] Polish struct address space diagnostic messa... by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: 95cd216962b6d70e233b725f70f2a1bac8d112c1
Change-Id: I92b345d6503bb39e8a5fc07613ec1ecde5f49619
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/182080
Commit-Queue: dan sinclair <dsinclair@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/src/tint/cmd/info/main.cc b/src/tint/cmd/info/main.cc
index a68a46b..26f6df2 100644
--- a/src/tint/cmd/info/main.cc
+++ b/src/tint/cmd/info/main.cc
@@ -28,6 +28,8 @@
#include <iostream>
+#include "src/tint/utils/text/styled_text_printer.h"
+
#if TINT_BUILD_SPV_READER
#include "spirv-tools/libspirv.hpp"
#endif // TINT_BUILD_SPV_READER
@@ -293,6 +295,7 @@
}
void EmitText(const tint::Program& program) {
+ auto printer = tint::StyledTextPrinter::Create(stdout);
tint::inspector::Inspector inspector(program);
if (!inspector.GetUsedExtensionNames().empty()) {
std::cout << "Extensions:" << std::endl;
@@ -320,7 +323,7 @@
continue;
}
const auto* s = ty->As<tint::core::type::Struct>();
- std::cout << s->Layout() << std::endl << std::endl;
+ printer->Print(s->Layout() << "\n\n");
}
}
}
diff --git a/src/tint/lang/core/type/struct.cc b/src/tint/lang/core/type/struct.cc
index b26042a..f403c1e 100644
--- a/src/tint/lang/core/type/struct.cc
+++ b/src/tint/lang/core/type/struct.cc
@@ -30,12 +30,15 @@
#include <cmath>
#include <iomanip>
#include <string>
+#include <string_view>
#include <utility>
#include "src/tint/lang/core/type/manager.h"
#include "src/tint/utils/math/hash.h"
#include "src/tint/utils/symbol/symbol_table.h"
#include "src/tint/utils/text/string_stream.h"
+#include "src/tint/utils/text/styled_text.h"
+#include "src/tint/utils/text/text_style.h"
TINT_INSTANTIATE_TYPEINFO(tint::core::type::Struct);
TINT_INSTANTIATE_TYPEINFO(tint::core::type::StructMember);
@@ -115,8 +118,15 @@
return name_.Name();
}
-std::string Struct::Layout() const {
- StringStream ss;
+StyledText Struct::Layout() const {
+ static constexpr auto Code = style::CodeNoQuote;
+ static constexpr auto Comment = style::Comment + style::CodeNoQuote;
+ static constexpr auto Keyword = style::Keyword + style::CodeNoQuote;
+ static constexpr auto Type = style::Type + style::CodeNoQuote;
+ static constexpr auto Variable = style::Variable + style::CodeNoQuote;
+ static constexpr auto Plain = style::Plain;
+
+ StyledText out;
auto member_name_of = [&](const StructMember* sm) { return sm->Name().Name(); };
@@ -131,20 +141,23 @@
const auto size_w = static_cast<int>(::log10(Size())) + 1;
const auto align_w = static_cast<int>(::log10(Align())) + 1;
+ auto pad = [](int n) { return std::string(static_cast<size_t>(n), ' '); };
+
auto print_struct_begin_line = [&](size_t align, size_t size, std::string struct_name) {
- ss << "/* " << std::setw(offset_w) << " "
- << "align(" << std::setw(align_w) << align << ") size(" << std::setw(size_w) << size
- << ") */ struct " << struct_name << " {\n";
+ out << Comment("/* ", pad(offset_w), "align(", std::setw(align_w), align,
+ ") size(", std::setw(size_w), size, ") */")
+ << Keyword(" struct ") << Type(struct_name) << Code(" {") << Plain("\n");
};
auto print_struct_end_line = [&] {
- ss << "/* " << std::setw(offset_w + size_w + align_w) << " "
- << "*/ };";
+ out << Comment("/* ", pad(offset_w + size_w + align_w), "*/")
+ << Code(" };");
};
- auto print_member_line = [&](size_t offset, size_t align, size_t size, std::string s) {
- ss << "/* offset(" << std::setw(offset_w) << offset << ") align(" << std::setw(align_w)
- << align << ") size(" << std::setw(size_w) << size << ") */ " << s << ";\n";
+ auto print_member_line = [&](size_t offset, size_t align, size_t size, StyledText s) {
+ out << Comment("/* offset(", std::setw(offset_w), offset, ") align(", std::setw(align_w),
+ align, ") size(", std::setw(size_w), size, ") */ ")
+ << s << Plain("\n");
};
print_struct_begin_line(Align(), Size(), UnwrapRef()->FriendlyName());
@@ -159,26 +172,31 @@
if (padding > 0) {
size_t padding_offset = m->Offset() - padding;
print_member_line(padding_offset, 1, padding,
- "// -- implicit field alignment padding --");
+ StyledText{}
+ << Code(" ")
+ << Comment("// -- implicit field alignment padding --"));
}
}
// Output member
std::string member_name = member_name_of(m);
print_member_line(m->Offset(), m->Align(), m->Size(),
- member_name + " : " + m->Type()->UnwrapRef()->FriendlyName());
+ StyledText{} << Code(" ") << Variable(member_name) << Code(" : ")
+ << Type(m->Type()->UnwrapRef()->FriendlyName())
+ << Code(","));
}
// Output struct size padding, if any
uint32_t struct_padding = Size() - last_member_struct_padding_offset;
if (struct_padding > 0) {
- print_member_line(last_member_struct_padding_offset, 1, struct_padding,
- "// -- implicit struct size padding --");
+ print_member_line(
+ last_member_struct_padding_offset, 1, struct_padding,
+ StyledText{} << Code(" ") << Comment("// -- implicit struct size padding --"));
}
print_struct_end_line();
- return ss.str();
+ return out;
}
TypeAndCount Struct::Elements(const Type* type_if_invalid /* = nullptr */,
diff --git a/src/tint/lang/core/type/struct.h b/src/tint/lang/core/type/struct.h
index 1ea2b0b..d95c084 100644
--- a/src/tint/lang/core/type/struct.h
+++ b/src/tint/lang/core/type/struct.h
@@ -41,6 +41,7 @@
#include "src/tint/utils/containers/hashset.h"
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/symbol/symbol.h"
+#include "src/tint/utils/text/styled_text.h"
// Forward declarations
namespace tint::core::type {
@@ -169,7 +170,7 @@
/// @returns a multiline string that describes the layout of this struct,
/// including size and alignment information.
- std::string Layout() const;
+ StyledText Layout() const;
/// @param concrete the conversion-rank ordered concrete versions of this abstract structure.
void SetConcreteTypes(VectorRef<const Struct*> concrete) { concrete_types_ = concrete; }
diff --git a/src/tint/lang/core/type/struct_test.cc b/src/tint/lang/core/type/struct_test.cc
index b545645..e47ab66 100644
--- a/src/tint/lang/core/type/struct_test.cc
+++ b/src/tint/lang/core/type/struct_test.cc
@@ -83,22 +83,22 @@
auto* sem_inner_st = p.Sem().Get(inner_st);
auto* sem_outer_st = p.Sem().Get(outer_st);
- EXPECT_EQ(sem_inner_st->Layout(),
+ EXPECT_EQ(sem_inner_st->Layout().Plain(),
R"(/* align(16) size(64) */ struct Inner {
-/* offset( 0) align( 4) size( 4) */ a : i32;
-/* offset( 4) align( 4) size( 4) */ b : u32;
-/* offset( 8) align( 4) size( 4) */ c : f32;
-/* offset(12) align( 1) size( 4) */ // -- implicit field alignment padding --;
-/* offset(16) align(16) size(12) */ d : vec3<f32>;
-/* offset(28) align( 1) size( 4) */ // -- implicit field alignment padding --;
-/* offset(32) align( 8) size(32) */ e : mat4x2<f32>;
+/* offset( 0) align( 4) size( 4) */ a : i32,
+/* offset( 4) align( 4) size( 4) */ b : u32,
+/* offset( 8) align( 4) size( 4) */ c : f32,
+/* offset(12) align( 1) size( 4) */ // -- implicit field alignment padding --
+/* offset(16) align(16) size(12) */ d : vec3<f32>,
+/* offset(28) align( 1) size( 4) */ // -- implicit field alignment padding --
+/* offset(32) align( 8) size(32) */ e : mat4x2<f32>,
/* */ };)");
- EXPECT_EQ(sem_outer_st->Layout(),
+ EXPECT_EQ(sem_outer_st->Layout().Plain(),
R"(/* align(16) size(80) */ struct Outer {
-/* offset( 0) align(16) size(64) */ inner : Inner;
-/* offset(64) align( 4) size( 4) */ a : i32;
-/* offset(68) align( 1) size(12) */ // -- implicit struct size padding --;
+/* offset( 0) align(16) size(64) */ inner : Inner,
+/* offset(64) align( 4) size( 4) */ a : i32,
+/* offset(68) align( 1) size(12) */ // -- implicit struct size padding --
/* */ };)");
}
diff --git a/src/tint/lang/wgsl/resolver/address_space_layout_validation_test.cc b/src/tint/lang/wgsl/resolver/address_space_layout_validation_test.cc
index 4fe832a..96b1340 100644
--- a/src/tint/lang/wgsl/resolver/address_space_layout_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/address_space_layout_validation_test.cc
@@ -47,7 +47,7 @@
// @group(0) @binding(0)
// var<storage> a : S;
- Structure(Source{{12, 34}}, "S",
+ Structure(Ident(Source{{12, 34}}, "S"),
Vector{
Member("a", ty.f32(), Vector{MemberSize(5_a)}),
Member(Source{{34, 56}}, "b", ty.f32(), Vector{MemberAlign(1_i)}),
@@ -62,9 +62,9 @@
R"(34:56 error: the offset of a struct member of type 'f32' in address space 'storage' must be a multiple of 4 bytes, but 'b' is currently at offset 5. Consider setting '@align(4)' on this member
12:34 note: see layout of struct:
/* align(4) size(12) */ struct S {
-/* offset(0) align(4) size( 5) */ a : f32;
-/* offset(5) align(1) size( 4) */ b : f32;
-/* offset(9) align(1) size( 3) */ // -- implicit struct size padding --;
+/* offset(0) align(4) size( 5) */ a : f32,
+/* offset(5) align(1) size( 4) */ b : f32,
+/* offset(9) align(1) size( 3) */ // -- implicit struct size padding --
/* */ };
78:90 note: 'S' used in address space 'storage' here)");
}
@@ -77,14 +77,12 @@
// @group(0) @binding(0)
// var<storage> a : S;
- Structure(Source{{12, 34}}, "S",
- Vector{
- Member("a", ty.f32(), Vector{MemberSize(5_a)}),
- Member(Source{{34, 56}}, "b", ty.f32(), Vector{MemberAlign(4_i)}),
- });
+ Structure("S", Vector{
+ Member("a", ty.f32(), Vector{MemberSize(5_a)}),
+ Member("b", ty.f32(), Vector{MemberAlign(4_i)}),
+ });
- GlobalVar(Source{{78, 90}}, "a", ty("S"), core::AddressSpace::kStorage, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("S"), core::AddressSpace::kStorage, Group(0_a), Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -103,16 +101,14 @@
// @group(0) @binding(0)
// var<uniform> a : Outer;
- Structure(Source{{12, 34}}, "Inner",
- Vector{
- Member("scalar", ty.i32()),
- });
+ Structure(Ident(Source{{12, 34}}, "Inner"), Vector{
+ Member("scalar", ty.i32()),
+ });
- Structure(Source{{34, 56}}, "Outer",
- Vector{
- Member("scalar", ty.f32()),
- Member(Source{{56, 78}}, "inner", ty("Inner")),
- });
+ Structure(Ident(Source{{34, 56}}, "Outer"), Vector{
+ Member("scalar", ty.f32()),
+ Member(Source{{56, 78}}, "inner", ty("Inner")),
+ });
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
@@ -123,12 +119,12 @@
R"(56:78 error: the offset of a struct member of type 'Inner' in address space 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting '@align(16)' on this member
34:56 note: see layout of struct:
/* align(4) size(8) */ struct Outer {
-/* offset(0) align(4) size(4) */ scalar : f32;
-/* offset(4) align(4) size(4) */ inner : Inner;
+/* offset(0) align(4) size(4) */ scalar : f32,
+/* offset(4) align(4) size(4) */ inner : Inner,
/* */ };
12:34 note: and layout of struct member:
/* align(4) size(4) */ struct Inner {
-/* offset(0) align(4) size(4) */ scalar : i32;
+/* offset(0) align(4) size(4) */ scalar : i32,
/* */ };
78:90 note: 'Outer' used in address space 'uniform' here)");
}
@@ -147,19 +143,16 @@
// @group(0) @binding(0)
// var<uniform> a : Outer;
- Structure(Source{{12, 34}}, "Inner",
- Vector{
- Member("scalar", ty.i32()),
- });
+ Structure("Inner", Vector{
+ Member("scalar", ty.i32()),
+ });
- Structure(Source{{34, 56}}, "Outer",
- Vector{
- Member("scalar", ty.f32()),
- Member(Source{{56, 78}}, "inner", ty("Inner"), Vector{MemberAlign(16_i)}),
- });
+ Structure("Outer", Vector{
+ Member("scalar", ty.f32()),
+ Member("inner", ty("Inner"), Vector{MemberAlign(16_i)}),
+ });
- GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -177,11 +170,10 @@
// var<uniform> a : Outer;
Alias("Inner", ty.array<f32, 10>(Vector{Stride(16)}));
- Structure(Source{{12, 34}}, "Outer",
- Vector{
- Member("scalar", ty.f32()),
- Member(Source{{56, 78}}, "inner", ty("Inner")),
- });
+ Structure(Ident(Source{{12, 34}}, "Outer"), Vector{
+ Member("scalar", ty.f32()),
+ Member(Source{{56, 78}}, "inner", ty("Inner")),
+ });
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
@@ -192,8 +184,8 @@
R"(56:78 error: the offset of a struct member of type '@stride(16) array<f32, 10>' in address space 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting '@align(16)' on this member
12:34 note: see layout of struct:
/* align(4) size(164) */ struct Outer {
-/* offset( 0) align(4) size( 4) */ scalar : f32;
-/* offset( 4) align(4) size(160) */ inner : @stride(16) array<f32, 10>;
+/* offset( 0) align(4) size( 4) */ scalar : f32,
+/* offset( 4) align(4) size(160) */ inner : @stride(16) array<f32, 10>,
/* */ };
78:90 note: 'Outer' used in address space 'uniform' here)");
}
@@ -210,14 +202,12 @@
// var<uniform> a : Outer;
Alias("Inner", ty.array<f32, 10>(Vector{Stride(16)}));
- Structure(Source{{12, 34}}, "Outer",
- Vector{
- Member("scalar", ty.f32()),
- Member(Source{{34, 56}}, "inner", ty("Inner"), Vector{MemberAlign(16_i)}),
- });
+ Structure("Outer", Vector{
+ Member("scalar", ty.f32()),
+ Member("inner", ty("Inner"), Vector{MemberAlign(16_i)}),
+ });
- GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -237,7 +227,7 @@
// @group(0) @binding(0)
// var<uniform> a : Outer;
- Structure(Source{{12, 34}}, "Inner",
+ Structure(Ident(Source{{12, 34}}, "Inner"),
Vector{
Member("scalar", ty.i32(), Vector{MemberAlign(1_i), MemberSize(5_a)}),
});
@@ -255,15 +245,15 @@
EXPECT_EQ(
r()->error(),
R"(78:90 error: 'uniform' storage requires that the number of bytes between the start of the previous member of type struct and the current member be a multiple of 16 bytes, but there are currently 8 bytes between 'inner' and 'scalar'. Consider setting '@align(16)' on this member
-34:56 note: see layout of struct:
+note: see layout of struct:
/* align(4) size(12) */ struct Outer {
-/* offset( 0) align(1) size( 5) */ inner : Inner;
-/* offset( 5) align(1) size( 3) */ // -- implicit field alignment padding --;
-/* offset( 8) align(4) size( 4) */ scalar : i32;
+/* offset( 0) align(1) size( 5) */ inner : Inner,
+/* offset( 5) align(1) size( 3) */ // -- implicit field alignment padding --
+/* offset( 8) align(4) size( 4) */ scalar : i32,
/* */ };
12:34 note: and layout of previous member struct:
/* align(1) size(5) */ struct Inner {
-/* offset(0) align(1) size(5) */ scalar : i32;
+/* offset(0) align(1) size(5) */ scalar : i32,
/* */ };
22:24 note: 'Outer' used in address space 'uniform' here)");
}
@@ -286,7 +276,7 @@
// @group(0) @binding(0)
// var<uniform> a : Outer;
- Structure(Source{{12, 34}}, "Inner",
+ Structure(Ident(Source{{12, 34}}, "Inner"),
Vector{
Member("a", ty.i32()),
Member("b", ty.i32()),
@@ -307,18 +297,18 @@
EXPECT_EQ(
r()->error(),
R"(78:90 error: 'uniform' storage requires that the number of bytes between the start of the previous member of type struct and the current member be a multiple of 16 bytes, but there are currently 20 bytes between 'inner' and 'scalar'. Consider setting '@align(16)' on this member
-34:56 note: see layout of struct:
+note: see layout of struct:
/* align(4) size(24) */ struct Outer {
-/* offset( 0) align(4) size(20) */ inner : Inner;
-/* offset(20) align(4) size( 4) */ scalar : i32;
+/* offset( 0) align(4) size(20) */ inner : Inner,
+/* offset(20) align(4) size( 4) */ scalar : i32,
/* */ };
12:34 note: and layout of previous member struct:
/* align(4) size(20) */ struct Inner {
-/* offset( 0) align(4) size( 4) */ a : i32;
-/* offset( 4) align(4) size( 4) */ b : i32;
-/* offset( 8) align(4) size( 4) */ c : i32;
-/* offset(12) align(1) size( 5) */ scalar : i32;
-/* offset(17) align(1) size( 3) */ // -- implicit struct size padding --;
+/* offset( 0) align(4) size( 4) */ a : i32,
+/* offset( 4) align(4) size( 4) */ b : i32,
+/* offset( 8) align(4) size( 4) */ c : i32,
+/* offset(12) align(1) size( 5) */ scalar : i32,
+/* offset(17) align(1) size( 3) */ // -- implicit struct size padding --
/* */ };
22:24 note: 'Outer' used in address space 'uniform' here)");
}
@@ -337,19 +327,16 @@
// @group(0) @binding(0)
// var<uniform> a : Outer;
- Structure(Source{{12, 34}}, "Inner",
- Vector{
- Member("scalar", ty.i32(), Vector{MemberAlign(1_i), MemberSize(5_a)}),
- });
+ Structure("Inner", Vector{
+ Member("scalar", ty.i32(), Vector{MemberAlign(1_i), MemberSize(5_a)}),
+ });
- Structure(Source{{34, 56}}, "Outer",
- Vector{
- Member(Source{{56, 78}}, "inner", ty("Inner")),
- Member(Source{{78, 90}}, "scalar", ty.i32(), Vector{MemberAlign(16_i)}),
- });
+ Structure("Outer", Vector{
+ Member("inner", ty("Inner")),
+ Member("scalar", ty.i32(), Vector{MemberAlign(16_i)}),
+ });
- GlobalVar(Source{{22, 34}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -369,8 +356,8 @@
Member("s", ty.f32()),
});
- GlobalVar(Source{{78, 90}}, "a", ty("ScalarPackedAtEndOfVec3"), core::AddressSpace::kUniform,
- Group(0_a), Binding(0_a));
+ GlobalVar("a", ty("ScalarPackedAtEndOfVec3"), core::AddressSpace::kUniform, Group(0_a),
+ Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -392,8 +379,8 @@
Member("s", ty.f16()),
});
- GlobalVar(Source{{78, 90}}, "a", ty("ScalarPackedAtEndOfVec3"), core::AddressSpace::kUniform,
- Group(0_a), Binding(0_a));
+ GlobalVar("a", ty("ScalarPackedAtEndOfVec3"), core::AddressSpace::kUniform, Group(0_a),
+ Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -412,11 +399,10 @@
Alias("Inner", ty.array<f32, 10>());
- Structure(Source{{12, 34}}, "Outer",
- Vector{
- Member("inner", ty(Source{{34, 56}}, "Inner")),
- Member("scalar", ty.i32()),
- });
+ Structure(Ident(Source{{12, 34}}, "Outer"), Vector{
+ Member("inner", ty(Source{{34, 56}}, "Inner")),
+ Member("scalar", ty.i32()),
+ });
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
@@ -427,8 +413,8 @@
R"(34:56 error: 'uniform' storage requires that array elements are aligned to 16 bytes, but array element of type 'f32' has a stride of 4 bytes. Consider using a vector or struct as the element type instead.
12:34 note: see layout of struct:
/* align(4) size(44) */ struct Outer {
-/* offset( 0) align(4) size(40) */ inner : array<f32, 10>;
-/* offset(40) align(4) size( 4) */ scalar : i32;
+/* offset( 0) align(4) size(40) */ inner : array<f32, 10>,
+/* offset(40) align(4) size( 4) */ scalar : i32,
/* */ };
78:90 note: 'Outer' used in address space 'uniform' here)");
}
@@ -446,11 +432,10 @@
Alias("Inner", ty.array<vec2<f32>, 10>());
- Structure(Source{{12, 34}}, "Outer",
- Vector{
- Member("inner", ty(Source{{34, 56}}, "Inner")),
- Member("scalar", ty.i32()),
- });
+ Structure(Ident(Source{{12, 34}}, "Outer"), Vector{
+ Member("inner", ty(Source{{34, 56}}, "Inner")),
+ Member("scalar", ty.i32()),
+ });
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
@@ -461,9 +446,9 @@
R"(34:56 error: 'uniform' storage requires that array elements are aligned to 16 bytes, but array element of type 'vec2<f32>' has a stride of 8 bytes. Consider using a vec4 instead.
12:34 note: see layout of struct:
/* align(8) size(88) */ struct Outer {
-/* offset( 0) align(8) size(80) */ inner : array<vec2<f32>, 10>;
-/* offset(80) align(4) size( 4) */ scalar : i32;
-/* offset(84) align(1) size( 4) */ // -- implicit struct size padding --;
+/* offset( 0) align(8) size(80) */ inner : array<vec2<f32>, 10>,
+/* offset(80) align(4) size( 4) */ scalar : i32,
+/* offset(84) align(1) size( 4) */ // -- implicit struct size padding --
/* */ };
78:90 note: 'Outer' used in address space 'uniform' here)");
}
@@ -489,11 +474,10 @@
});
Alias("Inner", ty.array(ty.Of(array_elem), 10_u));
- Structure(Source{{12, 34}}, "Outer",
- Vector{
- Member("inner", ty(Source{{34, 56}}, "Inner")),
- Member("scalar", ty.i32()),
- });
+ Structure(Ident(Source{{12, 34}}, "Outer"), Vector{
+ Member("inner", ty(Source{{34, 56}}, "Inner")),
+ Member("scalar", ty.i32()),
+ });
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
@@ -504,8 +488,8 @@
R"(34:56 error: 'uniform' storage requires that array elements are aligned to 16 bytes, but array element of type 'ArrayElem' has a stride of 8 bytes. Consider using the '@size' attribute on the last struct member.
12:34 note: see layout of struct:
/* align(4) size(84) */ struct Outer {
-/* offset( 0) align(4) size(80) */ inner : array<ArrayElem, 10>;
-/* offset(80) align(4) size( 4) */ scalar : i32;
+/* offset( 0) align(4) size(80) */ inner : array<ArrayElem, 10>,
+/* offset(80) align(4) size( 4) */ scalar : i32,
/* */ };
78:90 note: 'Outer' used in address space 'uniform' here)");
}
@@ -513,13 +497,12 @@
TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_TopLevelArray) {
// @group(0) @binding(0)
// var<uniform> a : array<f32, 4u>;
- GlobalVar(Source{{78, 90}}, "a", ty.array(Source{{34, 56}}, ty.f32(), 4_u),
- core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
+ GlobalVar("a", ty.array(ty.f32(), 4_u), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
- R"(78:90 error: 'uniform' storage requires that array elements are aligned to 16 bytes, but array element of type 'f32' has a stride of 4 bytes. Consider using a vector or struct as the element type instead.)");
+ R"(error: 'uniform' storage requires that array elements are aligned to 16 bytes, but array element of type 'f32' has a stride of 4 bytes. Consider using a vector or struct as the element type instead.)");
}
TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_NestedArray) {
@@ -530,7 +513,7 @@
// @group(0) @binding(0)
// var<uniform> a : array<Outer, 4u>;
- Structure(Source{{12, 34}}, "Outer",
+ Structure(Ident(Source{{12, 34}}, "Outer"),
Vector{
Member("inner", ty.array(Source{{34, 56}}, ty.array<f32, 4>(), 4_u)),
});
@@ -544,7 +527,7 @@
R"(34:56 error: 'uniform' storage requires that array elements are aligned to 16 bytes, but array element of type 'f32' has a stride of 4 bytes. Consider using a vector or struct as the element type instead.
12:34 note: see layout of struct:
/* align(4) size(64) */ struct Outer {
-/* offset( 0) align(4) size(64) */ inner : array<array<f32, 4>, 4>;
+/* offset( 0) align(4) size(64) */ inner : array<array<f32, 4>, 4>,
/* */ };
78:90 note: 'Outer' used in address space 'uniform' here)");
}
@@ -562,14 +545,12 @@
Alias("Inner", ty.array<f32, 10>(Vector{Stride(16)}));
- Structure(Source{{12, 34}}, "Outer",
- Vector{
- Member("inner", ty(Source{{34, 56}}, "Inner")),
- Member("scalar", ty.i32()),
- });
+ Structure("Outer", Vector{
+ Member("inner", ty("Inner")),
+ Member("scalar", ty.i32()),
+ });
- GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
@@ -583,7 +564,7 @@
// };
// var<push_constant> a : S;
Enable(wgsl::Extension::kChromiumExperimentalPushConstant);
- Structure(Source{{12, 34}}, "S",
+ Structure(Ident(Source{{12, 34}}, "S"),
Vector{Member("a", ty.f32(), Vector{MemberSize(5_a)}),
Member(Source{{34, 56}}, "b", ty.f32(), Vector{MemberAlign(1_i)})});
GlobalVar(Source{{78, 90}}, "a", ty("S"), core::AddressSpace::kPushConstant);
@@ -594,9 +575,9 @@
R"(34:56 error: the offset of a struct member of type 'f32' in address space 'push_constant' must be a multiple of 4 bytes, but 'b' is currently at offset 5. Consider setting '@align(4)' on this member
12:34 note: see layout of struct:
/* align(4) size(12) */ struct S {
-/* offset(0) align(4) size( 5) */ a : f32;
-/* offset(5) align(1) size( 4) */ b : f32;
-/* offset(9) align(1) size( 3) */ // -- implicit struct size padding --;
+/* offset(0) align(4) size( 5) */ a : f32,
+/* offset(5) align(1) size( 4) */ b : f32,
+/* offset(9) align(1) size( 3) */ // -- implicit struct size padding --
/* */ };
78:90 note: 'S' used in address space 'push_constant' here)");
}
@@ -633,19 +614,16 @@
Enable(wgsl::Extension::kChromiumInternalRelaxedUniformLayout);
- Structure(Source{{12, 34}}, "Inner",
- Vector{
- Member("scalar", ty.i32()),
- });
+ Structure("Inner", Vector{
+ Member("scalar", ty.i32()),
+ });
- Structure(Source{{34, 56}}, "Outer",
- Vector{
- Member("scalar", ty.f32()),
- Member(Source{{56, 78}}, "inner", ty("Inner")),
- });
+ Structure("Outer", Vector{
+ Member("scalar", ty.f32()),
+ Member("inner", ty("Inner")),
+ });
- GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
@@ -667,14 +645,12 @@
Alias("Inner", ty.array<f32, 10>(Vector{Stride(16)}));
- Structure(Source{{12, 34}}, "Outer",
- Vector{
- Member("scalar", ty.f32()),
- Member(Source{{56, 78}}, "inner", ty("Inner")),
- });
+ Structure("Outer", Vector{
+ Member("scalar", ty.f32()),
+ Member("inner", ty("Inner")),
+ });
- GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
@@ -696,19 +672,16 @@
Enable(wgsl::Extension::kChromiumInternalRelaxedUniformLayout);
- Structure(Source{{12, 34}}, "Inner",
- Vector{
- Member("scalar", ty.i32(), Vector{MemberAlign(1_i), MemberSize(5_a)}),
- });
+ Structure("Inner", Vector{
+ Member("scalar", ty.i32(), Vector{MemberAlign(1_i), MemberSize(5_a)}),
+ });
- Structure(Source{{34, 56}}, "Outer",
- Vector{
- Member(Source{{56, 78}}, "inner", ty("Inner")),
- Member(Source{{78, 90}}, "scalar", ty.i32()),
- });
+ Structure("Outer", Vector{
+ Member("inner", ty("Inner")),
+ Member("scalar", ty.i32()),
+ });
- GlobalVar(Source{{22, 24}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
@@ -725,13 +698,11 @@
Enable(wgsl::Extension::kChromiumInternalRelaxedUniformLayout);
- Structure(Source{{12, 34}}, "Outer",
- Vector{
- Member("arr", ty.array<f32, 10>()),
- });
+ Structure("Outer", Vector{
+ Member("arr", ty.array<f32, 10>()),
+ });
- GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
@@ -750,13 +721,11 @@
Enable(wgsl::Extension::kF16);
Enable(wgsl::Extension::kChromiumInternalRelaxedUniformLayout);
- Structure(Source{{12, 34}}, "Outer",
- Vector{
- Member("arr", ty.array<vec3<f16>, 10>()),
- });
+ Structure("Outer", Vector{
+ Member("arr", ty.array<vec3<f16>, 10>()),
+ });
- GlobalVar(Source{{78, 90}}, "a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a),
- Binding(0_a));
+ GlobalVar("a", ty("Outer"), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
diff --git a/src/tint/lang/wgsl/resolver/address_space_validation_test.cc b/src/tint/lang/wgsl/resolver/address_space_validation_test.cc
index aacf005..185bbdb 100644
--- a/src/tint/lang/wgsl/resolver/address_space_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/address_space_validation_test.cc
@@ -560,7 +560,7 @@
R"(12:34 error: 'uniform' storage requires that array elements are aligned to 16 bytes, but array element of type 'i32' has a stride of 4 bytes. Consider using a vector or struct as the element type instead.
note: see layout of struct:
/* align(4) size(4) */ struct S {
-/* offset(0) align(4) size(4) */ m : array<i32>;
+/* offset(0) align(4) size(4) */ m : array<i32>,
/* */ };
90:12 note: 'S' used in address space 'uniform' here)");
}
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index adc0134..a7a42ec 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -509,13 +509,14 @@
}
if (auto* str = store_ty->As<sem::Struct>()) {
+ auto& str_source = str->Declaration()->name->source;
for (size_t i = 0; i < str->Members().Length(); ++i) {
auto* const m = str->Members()[i];
uint32_t required_align = required_alignment_of(m->Type());
// Recurse into the member type.
if (!AddressSpaceLayout(m->Type(), address_space, m->Declaration()->type->source)) {
- AddNote(str->Declaration()->source) << "see layout of struct:\n" << str->Layout();
+ AddNote(str_source) << "see layout of struct:\n" << str->Layout();
note_usage();
return false;
}
@@ -533,11 +534,12 @@
<< style::Attribute("@align") << style::Code("(", required_align, ")")
<< " on this member";
- AddNote(str->Declaration()->source) << "see layout of struct:\n" << str->Layout();
+ AddNote(str_source) << "see layout of struct:\n" << str->Layout();
if (auto* member_str = m->Type()->As<sem::Struct>()) {
- AddNote(member_str->Declaration()->source) << "and layout of struct member:\n"
- << member_str->Layout();
+ AddNote(member_str->Declaration()->name->source)
+ << "and layout of struct member:\n"
+ << member_str->Layout();
}
note_usage();
@@ -562,11 +564,10 @@
<< style::Variable(member_name_of(m)) << ". Consider setting "
<< style::Attribute("@align") << style::Code("(16)") << " on this member";
- AddNote(str->Declaration()->source) << "see layout of struct:\n"
- << str->Layout();
+ AddNote(str_source) << "see layout of struct:\n" << str->Layout();
auto* prev_member_str = prev_member->Type()->As<sem::Struct>();
- AddNote(prev_member_str->Declaration()->source)
+ AddNote(prev_member_str->Declaration()->name->source)
<< "and layout of previous member struct:\n"
<< prev_member_str->Layout();
note_usage();
@@ -2220,7 +2221,7 @@
bool Validator::Structure(const sem::Struct* str, ast::PipelineStage stage) const {
if (str->Members().IsEmpty()) {
- AddError(str->Declaration()->source) << "structures must have at least one member";
+ AddError(str->Declaration()->name->source) << "structures must have at least one member";
return false;
}
diff --git a/src/tint/utils/text/styled_text.cc b/src/tint/utils/text/styled_text.cc
index 76d33cf..e9290ae 100644
--- a/src/tint/utils/text/styled_text.cc
+++ b/src/tint/utils/text/styled_text.cc
@@ -72,16 +72,16 @@
std::string StyledText::Plain() const {
StringStream ss;
- bool is_code = false;
+ bool is_code_no_quote = false;
Walk([&](std::string_view text, TextStyle style) {
- if (is_code != style.IsCode()) {
+ if (is_code_no_quote != (style.IsCode() && !style.IsCodeNoQuote())) {
ss << "'";
}
- is_code = style.IsCode();
+ is_code_no_quote = style.IsCode() && !style.IsCodeNoQuote();
ss << text;
});
- if (is_code) {
+ if (is_code_no_quote) {
ss << "'";
}
return ss.str();
diff --git a/src/tint/utils/text/styled_text_theme.cc b/src/tint/utils/text/styled_text_theme.cc
index e243cd5..0785c47 100644
--- a/src/tint/utils/text/styled_text_theme.cc
+++ b/src/tint/utils/text/styled_text_theme.cc
@@ -128,6 +128,13 @@
/* bold */ std::nullopt,
/* underlined */ std::nullopt,
},
+ /* kind_comment */
+ StyledTextTheme::Attributes{
+ /* foreground */ Color{106, 153, 85},
+ /* background */ std::nullopt,
+ /* bold */ std::nullopt,
+ /* underlined */ std::nullopt,
+ },
/* kind_squiggle */
StyledTextTheme::Attributes{
/* foreground */ Color{0, 200, 255},
@@ -235,6 +242,13 @@
/* bold */ std::nullopt,
/* underlined */ std::nullopt,
},
+ /* kind_comment */
+ StyledTextTheme::Attributes{
+ /* foreground */ Color{0, 128, 0},
+ /* background */ std::nullopt,
+ /* bold */ std::nullopt,
+ /* underlined */ std::nullopt,
+ },
/* kind_squiggle */
StyledTextTheme::Attributes{
/* foreground */ Color{0, 200, 255},
@@ -294,6 +308,8 @@
apply(kind_literal);
} else if (text_style.IsAttribute()) {
apply(kind_attribute);
+ } else if (text_style.IsComment()) {
+ apply(kind_comment);
}
}
if (text_style.IsSquiggle()) {
diff --git a/src/tint/utils/text/styled_text_theme.h b/src/tint/utils/text/styled_text_theme.h
index c083dd1..bff0de7 100644
--- a/src/tint/utils/text/styled_text_theme.h
+++ b/src/tint/utils/text/styled_text_theme.h
@@ -103,6 +103,8 @@
Attributes kind_literal;
/// The theme's attributes for a attribute token. This is applied on top #kind_code.
Attributes kind_attribute;
+ /// The theme's attributes for a comment token. This is applied on top #kind_code.
+ Attributes kind_comment;
/// The theme's attributes for a squiggle-highlight.
Attributes kind_squiggle;
diff --git a/src/tint/utils/text/text_style.h b/src/tint/utils/text/text_style.h
index a9ce9e1..c337a5a 100644
--- a/src/tint/utils/text/text_style.h
+++ b/src/tint/utils/text/text_style.h
@@ -53,68 +53,72 @@
/// Bit patterns
- static constexpr Bits kStyleMask /* */ = 0b0000'0000'0000'0011;
- static constexpr Bits kStyleUnderlined /* */ = 0b0000'0000'0000'0001;
- static constexpr Bits kStyleBold /* */ = 0b0000'0000'0000'0010;
+ static constexpr Bits kStyleMask /* */ = 0b00'000000'0000'00'11;
+ static constexpr Bits kStyleUnderlined /* */ = 0b00'000000'0000'00'01;
+ static constexpr Bits kStyleBold /* */ = 0b00'000000'0000'00'10;
- static constexpr Bits kCompareMask /* */ = 0b0000'0000'0000'1100;
- static constexpr Bits kCompareMatch /* */ = 0b0000'0000'0000'0100;
- static constexpr Bits kCompareMismatch /* */ = 0b0000'0000'0000'1000;
+ static constexpr Bits kCompareMask /* */ = 0b00'000000'0000'11'00;
+ static constexpr Bits kCompareMatch /* */ = 0b00'000000'0000'01'00;
+ static constexpr Bits kCompareMismatch /* */ = 0b00'000000'0000'10'00;
- static constexpr Bits kSeverityMask /* */ = 0b0000'0000'1111'0000;
- static constexpr Bits kSeverityDefault /* */ = 0b0000'0000'0000'0000;
- static constexpr Bits kSeveritySuccess /* */ = 0b0000'0000'0001'0000;
- static constexpr Bits kSeverityWarning /* */ = 0b0000'0000'0010'0000;
- static constexpr Bits kSeverityError /* */ = 0b0000'0000'0011'0000;
- static constexpr Bits kSeverityFatal /* */ = 0b0000'0000'0100'0000;
+ static constexpr Bits kSeverityMask /* */ = 0b00'000000'1111'00'00;
+ static constexpr Bits kSeverityDefault /* */ = 0b00'000000'0000'00'00;
+ static constexpr Bits kSeveritySuccess /* */ = 0b00'000000'0001'00'00;
+ static constexpr Bits kSeverityWarning /* */ = 0b00'000000'0010'00'00;
+ static constexpr Bits kSeverityError /* */ = 0b00'000000'0011'00'00;
+ static constexpr Bits kSeverityFatal /* */ = 0b00'000000'0100'00'00;
- static constexpr Bits kKindMask /* */ = 0b0000'1111'0000'0000;
- static constexpr Bits kKindCode /* */ = 0b0000'0001'0000'0000;
- static constexpr Bits kKindKeyword /* */ = 0b0000'0011'0000'0000;
- static constexpr Bits kKindVariable /* */ = 0b0000'0101'0000'0000;
- static constexpr Bits kKindType /* */ = 0b0000'0111'0000'0000;
- static constexpr Bits kKindFunction /* */ = 0b0000'1001'0000'0000;
- static constexpr Bits kKindEnum /* */ = 0b0000'1011'0000'0000;
- static constexpr Bits kKindLiteral /* */ = 0b0000'1101'0000'0000;
- static constexpr Bits kKindAttribute /* */ = 0b0000'1111'0000'0000;
- static constexpr Bits kKindSquiggle /* */ = 0b0000'0010'0000'0000;
+ static constexpr Bits kKindMask /* */ = 0b00'111111'0000'00'00;
+ static constexpr Bits kKindCode /* */ = 0b00'000001'0000'00'00;
+ static constexpr Bits kKindCodeNoQuote /* */ = 0b00'000011'0000'00'00; // includes kKindCode
+ static constexpr Bits kKindKeyword /* */ = 0b00'000101'0000'00'00; // includes kKindCode
+ static constexpr Bits kKindVariable /* */ = 0b00'001001'0000'00'00; // includes kKindCode
+ static constexpr Bits kKindType /* */ = 0b00'001101'0000'00'00; // includes kKindCode
+ static constexpr Bits kKindFunction /* */ = 0b00'010001'0000'00'00; // includes kKindCode
+ static constexpr Bits kKindEnum /* */ = 0b00'010101'0000'00'00; // includes kKindCode
+ static constexpr Bits kKindLiteral /* */ = 0b00'011001'0000'00'00; // includes kKindCode
+ static constexpr Bits kKindAttribute /* */ = 0b00'011101'0000'00'00; // includes kKindCode
+ static constexpr Bits kKindComment /* */ = 0b00'100001'0000'00'00; // includes kKindCode
+ static constexpr Bits kKindSquiggle /* */ = 0b00'000100'0000'00'00;
/// Getters
- bool IsBold() const { return (bits & kStyleBold) != 0; }
- bool IsUnderlined() const { return (bits & kStyleUnderlined) != 0; }
+ constexpr bool IsBold() const { return (bits & kStyleBold) != 0; }
+ constexpr bool IsUnderlined() const { return (bits & kStyleUnderlined) == kStyleUnderlined; }
- bool HasCompare() const { return (bits & kCompareMask) != 0; }
- bool IsMatch() const { return (bits & kCompareMask) == kCompareMatch; }
- bool IsMismatch() const { return (bits & kCompareMask) == kCompareMismatch; }
+ constexpr bool HasCompare() const { return (bits & kCompareMask) != 0; }
+ constexpr bool IsMatch() const { return (bits & kCompareMask) == kCompareMatch; }
+ constexpr bool IsMismatch() const { return (bits & kCompareMask) == kCompareMismatch; }
- bool HasSeverity() const { return (bits & kSeverityMask) != 0; }
- bool IsSuccess() const { return (bits & kSeverityMask) == kSeveritySuccess; }
- bool IsWarning() const { return (bits & kSeverityMask) == kSeverityWarning; }
- bool IsError() const { return (bits & kSeverityMask) == kSeverityError; }
- bool IsFatal() const { return (bits & kSeverityMask) == kSeverityFatal; }
+ constexpr bool HasSeverity() const { return (bits & kSeverityMask) != 0; }
+ constexpr bool IsSuccess() const { return (bits & kSeverityMask) == kSeveritySuccess; }
+ constexpr bool IsWarning() const { return (bits & kSeverityMask) == kSeverityWarning; }
+ constexpr bool IsError() const { return (bits & kSeverityMask) == kSeverityError; }
+ constexpr bool IsFatal() const { return (bits & kSeverityMask) == kSeverityFatal; }
- bool HasKind() const { return (bits & kKindMask) != 0; }
- bool IsCode() const { return (bits & kKindCode) != 0; }
- bool IsKeyword() const { return (bits & kKindMask) == kKindKeyword; }
- bool IsVariable() const { return (bits & kKindMask) == kKindVariable; }
- bool IsType() const { return (bits & kKindMask) == kKindType; }
- bool IsFunction() const { return (bits & kKindMask) == kKindFunction; }
- bool IsEnum() const { return (bits & kKindMask) == kKindEnum; }
- bool IsLiteral() const { return (bits & kKindMask) == kKindLiteral; }
- bool IsAttribute() const { return (bits & kKindMask) == kKindAttribute; }
- bool IsSquiggle() const { return (bits & kKindMask) == kKindSquiggle; }
+ constexpr bool HasKind() const { return (bits & kKindMask) != 0; }
+ constexpr bool IsCode() const { return (bits & kKindCode) == kKindCode; }
+ constexpr bool IsCodeNoQuote() const { return (bits & kKindCodeNoQuote) == kKindCodeNoQuote; }
+ constexpr bool IsKeyword() const { return (bits & kKindMask) == kKindKeyword; }
+ constexpr bool IsVariable() const { return (bits & kKindMask) == kKindVariable; }
+ constexpr bool IsType() const { return (bits & kKindMask) == kKindType; }
+ constexpr bool IsFunction() const { return (bits & kKindMask) == kKindFunction; }
+ constexpr bool IsEnum() const { return (bits & kKindMask) == kKindEnum; }
+ constexpr bool IsLiteral() const { return (bits & kKindMask) == kKindLiteral; }
+ constexpr bool IsAttribute() const { return (bits & kKindMask) == kKindAttribute; }
+ constexpr bool IsComment() const { return (bits & kKindMask) == kKindComment; }
+ constexpr bool IsSquiggle() const { return (bits & kKindMask) == kKindSquiggle; }
/// Equality operator
- bool operator==(TextStyle other) const { return bits == other.bits; }
+ constexpr bool operator==(TextStyle other) const { return bits == other.bits; }
/// Inequality operator
- bool operator!=(TextStyle other) const { return bits != other.bits; }
+ constexpr bool operator!=(TextStyle other) const { return bits != other.bits; }
/// @returns the combination of this TextStyle and @p other.
/// If both this TextStyle and @p other have a compare style, severity style or kind style, then
/// the style collision will resolve by using the style of @p other.
- TextStyle operator+(TextStyle other) const {
+ constexpr TextStyle operator+(TextStyle other) const {
Bits out = other.bits;
out |= bits & kStyleMask;
if (HasCompare() && !other.HasCompare()) {
@@ -184,6 +188,9 @@
static constexpr TextStyle Fatal = TextStyle{TextStyle::kSeverityFatal};
/// Code renders text with a 'code' style
static constexpr TextStyle Code = TextStyle{TextStyle::kKindCode};
+/// Code renders text with a 'code' style, but does not use a single quote when printed as plain
+/// text.
+static constexpr TextStyle CodeNoQuote = TextStyle{TextStyle::kKindCodeNoQuote};
/// Keyword renders text with a 'code' style that represents a 'keyword' token
static constexpr TextStyle Keyword = TextStyle{TextStyle::kKindKeyword};
/// Variable renders text with a 'code' style that represents a 'variable' token
@@ -198,6 +205,8 @@
static constexpr TextStyle Literal = TextStyle{TextStyle::kKindLiteral};
/// Attribute renders text with a 'code' style that represents an 'attribute' token
static constexpr TextStyle Attribute = TextStyle{TextStyle::kKindAttribute};
+/// Comment renders text with a 'code' style that represents an 'comment' token
+static constexpr TextStyle Comment = TextStyle{TextStyle::kKindComment};
/// Squiggle renders text with a squiggle-highlight style (`^^^^^`)
static constexpr TextStyle Squiggle = TextStyle{TextStyle::kKindSquiggle};