Skip to content

[naga] Comments parsing (naga + wgsl) #6364

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 32 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
198f862
wip simple '//' comment token for 'Struct'
Vrixyz Oct 3, 2024
4a0c0a6
expose comments in `Module`
Vrixyz Oct 4, 2024
9415d36
add comments in module only if struct comments is not empty
Vrixyz Oct 4, 2024
3530a13
add comments to functions, consts, and globalvariables
Vrixyz Oct 7, 2024
3f7d11c
add support for struct member comments
Vrixyz Oct 7, 2024
6a6e5d0
support for multi-line comments
Vrixyz Oct 8, 2024
a1028c9
fix comment parsing for long characters
Vrixyz Oct 9, 2024
4f69d08
support for module comment
Vrixyz Oct 10, 2024
ef9346a
avoid a Trivia token between comment lines.
Vrixyz Oct 11, 2024
b3c4592
module comments have specific syntax
Vrixyz Oct 11, 2024
60eeb63
few PR feedbacks ; thanks @jimblandy
Vrixyz Jan 8, 2025
e66a6b0
validate doc comments + split entrypoints and functions + fix emoji
Vrixyz Jan 8, 2025
b1cf5a4
do not add doc struct member if the comment is empty
Vrixyz Jan 8, 2025
ad07328
module comments now behind an option<box<>> + moved comments parser t…
Vrixyz Feb 24, 2025
d3c1fd0
update tests snapshots
Vrixyz Jan 9, 2025
eaa0901
add tests for module docs + fix start span
Vrixyz Jan 9, 2025
97cdaf2
compact: adjust handles in comments
Vrixyz Jan 10, 2025
46c0861
remove unused function
Vrixyz Jan 10, 2025
45689da
update test snapshots
Vrixyz Jan 10, 2025
9436232
remove hack from error fixed by compact handle adjusting
Vrixyz Jan 10, 2025
24d7c5d
fix wrong parameter naming
Vrixyz Jan 10, 2025
7f36ed3
adjust types for struct members
Vrixyz Jan 10, 2025
2526753
update snapshots
jimblandy Feb 20, 2025
8324eb6
simplify comments compacting logic (PR feedback)
Vrixyz Feb 21, 2025
1bacb02
add an option struct to opt in comments parsing for wgsl
Vrixyz Feb 21, 2025
d1ff1a1
add line in changelog
Vrixyz Feb 21, 2025
bc56502
moved Module implementation to front/mod.rs
Vrixyz Feb 21, 2025
768d7b6
update snapshots ; not sure if we should add 1 or 2 snapshot tests wi…
Vrixyz Feb 21, 2025
5de3752
fix clippy from my changes
Vrixyz Feb 21, 2025
46f81af
rename ParserOptions to Options
Vrixyz Feb 21, 2025
9cb6d53
use rust-style doc comments ; ignore others
Vrixyz Feb 25, 2025
6791409
pr feedback: simpler accumulate doc comments
Vrixyz Apr 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ By @cwfitzgerald in [#7030](https://github.com/gfx-rs/wgpu/pull/7030).
- Support @must_use attribute on function declarations. By @turbocrime in [#6801](https://github.com/gfx-rs/wgpu/pull/6801).
- Support for generating the candidate intersections from AABB geometry, and confirming the hits. By @kvark in [#7047](https://github.com/gfx-rs/wgpu/pull/7047).
- Make naga::back::spv::Function::to_words write the OpFunctionEnd instruction in itself, instead of making another call after it. By @junjunjd in [#7156](https://github.com/gfx-rs/wgpu/pull/7156).
- Support comments parsing for wgsl through `naga::front::glsl::Frontend::new_with_options`. By @Vrixyz in [#6364](https://github.com/gfx-rs/wgpu/pull/6364).

### Changes

Expand Down
42 changes: 42 additions & 0 deletions naga/src/compact/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,48 @@ pub fn compact(module: &mut crate::Module) {
module_map.global_expressions.adjust(init);
}
}
// Adjust comments
if let Some(ref mut comments) = module.comments {
let crate::Comments {
module: _,
types: ref mut comment_types,
struct_members: ref mut comment_struct_members,
entry_points: _,
functions: _,
constants: ref mut comment_constants,
global_variables: _,
} = **comments;
log::trace!("adjusting comments for types");
for (mut comment_type_handle, comment) in std::mem::take(comment_types) {
if !module_map.types.used(comment_type_handle) {
continue;
}
module_map.types.adjust(&mut comment_type_handle);
comment_types.insert(comment_type_handle, comment);
}
log::trace!("adjusting comments for struct members");
for (mut comment_struct_member_handle, comment) in std::mem::take(comment_struct_members) {
if !module_map.types.used(comment_struct_member_handle.0) {
continue;
}
module_map.types.adjust(&mut comment_struct_member_handle.0);
comment_struct_members.insert(
(
comment_struct_member_handle.0,
comment_struct_member_handle.1,
),
comment,
);
}
log::trace!("adjusting comments for constants");
for (mut comment_constant_handle, comment) in std::mem::take(comment_constants) {
if !module_map.constants.used(comment_constant_handle) {
continue;
}
module_map.constants.adjust(&mut comment_constant_handle);
comment_constants.insert(comment_constant_handle, comment);
}
}

// Temporary storage to help us reuse allocations of existing
// named expression tables.
Expand Down
11 changes: 10 additions & 1 deletion naga/src/front/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*!
Frontend parsers that consume binary and text shaders and load them into [`Module`](super::Module)s.
Frontend parsers that consume binary and text shaders and load them into [`Module`]s.
*/

mod interpolator;
Expand Down Expand Up @@ -328,3 +328,12 @@ impl<Name: fmt::Debug, Var: fmt::Debug> fmt::Debug for SymbolTable<Name, Var> {
.finish()
}
}

use crate::{Comments, Module};

impl Module {
pub fn get_comments_or_insert_default(&mut self) -> &mut Box<Comments> {
self.comments
.get_or_insert_with(|| Box::new(Comments::default()))
}
}
2 changes: 2 additions & 0 deletions naga/src/front/wgsl/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,8 @@ impl<'a> Error<'a> {
Token::Arrow => "->".to_string(),
Token::Unknown(c) => format!("unknown (`{c}`)"),
Token::Trivia => "trivia".to_string(),
Token::CommentDoc(s) => format!("documentation ('{s}')"),
Token::CommentDocModule(s) => format!("module documentation ('{s}')"),
Token::End => "end".to_string(),
},
ExpectedToken::Identifier => "identifier".to_string(),
Expand Down
68 changes: 64 additions & 4 deletions naga/src/front/wgsl/lower/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ enum LoweredGlobalDecl {
Const(Handle<crate::Constant>),
Override(Handle<crate::Override>),
Type(Handle<crate::Type>),
EntryPoint,
EntryPoint(usize),
}

enum Texture {
Expand Down Expand Up @@ -1057,6 +1057,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
layouter: &mut Layouter::default(),
global_expression_kind_tracker: &mut crate::proc::ExpressionKindTracker::new(),
};
if !tu.comments.is_empty() {
ctx.module.get_comments_or_insert_default().module =
tu.comments.iter().map(|s| s.to_string()).collect();
}

for decl_handle in self.index.visit_ordered() {
let span = tu.decls.get_span(decl_handle);
Expand All @@ -1065,6 +1069,29 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
match decl.kind {
ast::GlobalDeclKind::Fn(ref f) => {
let lowered_decl = self.function(f, span, &mut ctx)?;
if !f.comments.is_empty() {
match lowered_decl {
LoweredGlobalDecl::Function { handle, .. } => {
ctx.module
.get_comments_or_insert_default()
.functions
.insert(
handle,
f.comments.iter().map(|s| s.to_string()).collect(),
);
}
LoweredGlobalDecl::EntryPoint(index) => {
ctx.module
.get_comments_or_insert_default()
.entry_points
.insert(
index,
f.comments.iter().map(|s| s.to_string()).collect(),
);
}
_ => {}
}
}
ctx.globals.insert(f.name.name, lowered_decl);
}
ast::GlobalDeclKind::Var(ref v) => {
Expand Down Expand Up @@ -1095,6 +1122,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
span,
);

if !v.comments.is_empty() {
ctx.module
.get_comments_or_insert_default()
.global_variables
.insert(handle, v.comments.iter().map(|s| s.to_string()).collect());
}
ctx.globals
.insert(v.name.name, LoweredGlobalDecl::Var(handle));
}
Expand All @@ -1120,6 +1153,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {

ctx.globals
.insert(c.name.name, LoweredGlobalDecl::Const(handle));
if !c.comments.is_empty() {
ctx.module
.get_comments_or_insert_default()
.constants
.insert(handle, c.comments.iter().map(|s| s.to_string()).collect());
}
}
ast::GlobalDeclKind::Override(ref o) => {
let explicit_ty =
Expand Down Expand Up @@ -1160,6 +1199,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let handle = self.r#struct(s, span, &mut ctx)?;
ctx.globals
.insert(s.name.name, LoweredGlobalDecl::Type(handle));
if !s.comments.is_empty() {
ctx.module
.get_comments_or_insert_default()
.types
.insert(handle, s.comments.iter().map(|s| s.to_string()).collect());
}
}
ast::GlobalDeclKind::Type(ref alias) => {
let ty = self.resolve_named_ast_type(
Expand Down Expand Up @@ -1375,7 +1420,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
workgroup_size_overrides,
function,
});
Ok(LoweredGlobalDecl::EntryPoint)
Ok(LoweredGlobalDecl::EntryPoint(
ctx.module.entry_points.len() - 1,
))
} else {
let handle = ctx.module.functions.append(function, span);
Ok(LoweredGlobalDecl::Function {
Expand Down Expand Up @@ -1933,7 +1980,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
}
LoweredGlobalDecl::Function { .. }
| LoweredGlobalDecl::Type(_)
| LoweredGlobalDecl::EntryPoint => {
| LoweredGlobalDecl::EntryPoint(_) => {
return Err(Error::Unexpected(span, ExpectedToken::Variable));
}
};
Expand Down Expand Up @@ -2193,7 +2240,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
| &LoweredGlobalDecl::Override(_)
| &LoweredGlobalDecl::Var(_),
) => Err(Error::Unexpected(function_span, ExpectedToken::Function)),
Some(&LoweredGlobalDecl::EntryPoint) => Err(Error::CalledEntryPoint(function_span)),
Some(&LoweredGlobalDecl::EntryPoint(_)) => Err(Error::CalledEntryPoint(function_span)),
Some(&LoweredGlobalDecl::Function {
handle: function,
must_use,
Expand Down Expand Up @@ -3058,6 +3105,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let mut struct_alignment = Alignment::ONE;
let mut members = Vec::with_capacity(s.members.len());

let mut comments: Vec<Option<Vec<String>>> = Vec::new();

for member in s.members.iter() {
let ty = self.resolve_ast_type(member.ty, &mut ctx.as_const())?;

Expand Down Expand Up @@ -3097,6 +3146,11 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
offset = member_alignment.round_up(offset);
struct_alignment = struct_alignment.max(member_alignment);

if !member.comments.is_empty() {
comments.push(Some(
member.comments.iter().map(|s| s.to_string()).collect(),
));
}
members.push(crate::StructMember {
name: Some(member.name.name.to_owned()),
ty,
Expand All @@ -3120,6 +3174,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
},
span,
);
for (i, c) in comments.drain(..).enumerate() {
if let Some(comment) = c {
let comments = ctx.module.get_comments_or_insert_default();
comments.struct_members.insert((handle, i), comment);
}
}
Ok(handle)
}

Expand Down
11 changes: 10 additions & 1 deletion naga/src/front/wgsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,28 @@ use thiserror::Error;
pub use crate::front::wgsl::error::ParseError;
use crate::front::wgsl::lower::Lowerer;
use crate::Scalar;
pub use parse::Options;

pub use crate::front::wgsl::parse::directive::language_extension::{
ImplementedLanguageExtension, LanguageExtension, UnimplementedLanguageExtension,
};

pub struct Frontend {
parser: Parser,
options: Options,
}

impl Frontend {
pub const fn new() -> Self {
Self {
parser: Parser::new(),
options: Options::new(),
}
}
pub const fn new_with_options(options: Options) -> Self {
Self {
parser: Parser::new(),
options,
}
}

Expand All @@ -40,7 +49,7 @@ impl Frontend {
}

fn inner<'a>(&mut self, source: &'a str) -> Result<crate::Module, Error<'a>> {
let tu = self.parser.parse(source)?;
let tu = self.parser.parse(source, &self.options)?;
let index = index::Index::generate(&tu)?;
let module = Lowerer::new(&index).lower(&tu)?;

Expand Down
10 changes: 10 additions & 0 deletions naga/src/front/wgsl/parse/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ pub struct TranslationUnit<'a> {
/// See [`DiagnosticFilterNode`] for details on how the tree is represented and used in
/// validation.
pub diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,

/// Comments appearing first in the file.
/// This serves as documentation for the whole TranslationUnit.
pub comments: Vec<&'a str>,
}

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -135,6 +139,7 @@ pub struct Function<'a> {
pub result: Option<FunctionResult<'a>>,
pub body: Block<'a>,
pub diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,
pub comments: Vec<&'a str>,
}

#[derive(Debug)]
Expand All @@ -161,6 +166,7 @@ pub struct GlobalVariable<'a> {
pub binding: Option<ResourceBinding<'a>>,
pub ty: Option<Handle<Type<'a>>>,
pub init: Option<Handle<Expression<'a>>>,
pub comments: Vec<&'a str>,
}

#[derive(Debug)]
Expand All @@ -170,12 +176,15 @@ pub struct StructMember<'a> {
pub binding: Option<Binding<'a>>,
pub align: Option<Handle<Expression<'a>>>,
pub size: Option<Handle<Expression<'a>>>,
pub comments: Vec<&'a str>,
}

#[derive(Debug)]
pub struct Struct<'a> {
pub name: Ident<'a>,
pub members: Vec<StructMember<'a>>,
// TODO: Make it optional ? Store Span ? Add it to other elements
pub comments: Vec<&'a str>,
}

#[derive(Debug)]
Expand All @@ -189,6 +198,7 @@ pub struct Const<'a> {
pub name: Ident<'a>,
pub ty: Option<Handle<Type<'a>>>,
pub init: Handle<Expression<'a>>,
pub comments: Vec<&'a str>,
}

#[derive(Debug)]
Expand Down
Loading