diff --git a/crates/analysis/src/jobs/syntax_analysis/syntax_error_visitor.rs b/crates/analysis/src/jobs/syntax_analysis/syntax_error_visitor.rs index ce12abe..c7bf5e7 100644 --- a/crates/analysis/src/jobs/syntax_analysis/syntax_error_visitor.rs +++ b/crates/analysis/src/jobs/syntax_analysis/syntax_error_visitor.rs @@ -761,6 +761,7 @@ impl SyntaxNodeVisitor for SyntaxErrorVisitor<'_> { NewExpressionTraversalPolicy { traverse_lifetime_obj, + traverse_unnamed: any_error, traverse_errors: any_error } } @@ -833,6 +834,7 @@ impl SyntaxNodeVisitor for SyntaxErrorVisitor<'_> { TypeCastExpressionTraversalPolicy { traverse_value, + traverse_unnamed: any_error, traverse_errors: any_error } } diff --git a/crates/core/src/ast/expressions.rs b/crates/core/src/ast/expressions.rs index d5a1bba..178788d 100644 --- a/crates/core/src/ast/expressions.rs +++ b/crates/core/src/ast/expressions.rs @@ -356,14 +356,34 @@ impl<'script> FunctionCallArgumentsNode<'script> { } fn accept_with_policy(&self, visitor: &mut V, ctx: &mut TraversalContextStack, tp: FunctionCallExpressionTraversalPolicy) { - //FIXME missing unnamed traversal - for res in self.iter_result() { - match res { - Ok(arg) => { - arg.accept(visitor, ctx) - } + let mut previous_was_comma = true; + + for ch in self.children_detailed().must_be_named(false) { + match ch { + Ok((arg, _)) if arg.is_named() => { + let arg = FunctionCallArgument::Some(arg.unsafe_into()); + arg.accept(visitor, ctx); + + previous_was_comma = false; + }, + // comma is the only valid unnamed token in thi s context + Ok((comma, _)) if !comma.is_named() => { + if previous_was_comma { + let arg = FunctionCallArgument::Omitted(comma.range()); + arg.accept(visitor, ctx); + } + + previous_was_comma = true; + + if tp.traverse_unnamed { + let unnamed: UnnamedNode = comma.unsafe_into(); + unnamed.accept(visitor, ctx); + } + }, Err(e) if tp.traverse_errors => { - e.accept(visitor, ctx) + e.accept(visitor, ctx); + + previous_was_comma = false; }, _ => {} } @@ -394,6 +414,7 @@ impl<'script> TryFrom> for FunctionCallArgumentsNode<'script> { impl SyntaxNodeTraversal for FunctionCallArgumentsNode<'_> { fn accept(&self, visitor: &mut V, ctx: &mut TraversalContextStack) { + // UNUSED self.iter().for_each(|n| n.accept(visitor, ctx)) } } @@ -657,6 +678,10 @@ impl SyntaxNodeTraversal for NewExpressionNode<'_> { lifetime_obj.accept(visitor, ctx); ctx.pop(); }, + Ok((unnamed, _)) if !unnamed.is_named() && tp.traverse_unnamed => { + let unnamed: UnnamedNode = unnamed.unsafe_into(); + unnamed.accept(visitor, ctx); + } Err(e) if tp.traverse_errors => { e.accept(visitor, ctx); }, @@ -726,6 +751,10 @@ impl SyntaxNodeTraversal for TypeCastExpressionNode<'_> { value.accept(visitor, ctx); ctx.pop(); }, + Ok((unnamed, _)) if !unnamed.is_named() && tp.traverse_unnamed => { + let unnamed: UnnamedNode = unnamed.unsafe_into(); + unnamed.accept(visitor, ctx); + } Err(e) if tp.traverse_errors => { e.accept(visitor, ctx); }, diff --git a/crates/core/src/ast/functions.rs b/crates/core/src/ast/functions.rs index 013cb6d..7467ecf 100644 --- a/crates/core/src/ast/functions.rs +++ b/crates/core/src/ast/functions.rs @@ -71,7 +71,7 @@ impl SyntaxNodeTraversal for EventDeclarationNode<'_> { Ok((params, Some("params"))) if tp.traverse_params => { let params: FunctionParametersNode = params.unsafe_into(); - params.accept_with_policy(visitor, ctx, tp.traverse_errors); + params.accept_with_policy(visitor, ctx, tp.traverse_unnamed, tp.traverse_errors); }, Ok((rt, Some("return_type"))) if tp.traverse_return_type => { let rt: TypeAnnotationNode = rt.unsafe_into(); @@ -179,7 +179,7 @@ impl SyntaxNodeTraversal for FunctionDeclarationNode<'_> { Ok((params, Some("params"))) if tp.traverse_params => { let params: FunctionParametersNode = params.unsafe_into(); - params.accept_with_policy(visitor, ctx, tp.traverse_errors); + params.accept_with_policy(visitor, ctx, tp.traverse_unnamed, tp.traverse_errors); }, Ok((rt, Some("return_type"))) if tp.traverse_return_type => { let rt: TypeAnnotationNode = rt.unsafe_into(); @@ -375,15 +375,17 @@ impl<'script> FunctionParametersNode<'script> { } - fn accept_with_policy(&self, visitor: &mut V, ctx: &mut TraversalContextStack, traverse_errors: bool) { - //FIXME missing unnamed traversal + fn accept_with_policy(&self, visitor: &mut V, ctx: &mut TraversalContextStack, traverse_unnamed: bool, traverse_errors: bool) { for ch in self.children_detailed().must_be_named(true) { match ch { - Ok((param_group, _)) => { + Ok((param_group, _)) if param_group.is_named() => { let param_group: FunctionParameterGroupNode = param_group.unsafe_into(); - param_group.accept(visitor, ctx); }, + Ok((unnamed, _)) if !unnamed.is_named() && traverse_unnamed => { + let unnamed: UnnamedNode = unnamed.unsafe_into(); + unnamed.accept(visitor, ctx); + }, Err(e) if traverse_errors => { e.accept(visitor, ctx); }, diff --git a/crates/core/src/ast/traversal/policies.rs b/crates/core/src/ast/traversal/policies.rs index 9c05b46..348d454 100644 --- a/crates/core/src/ast/traversal/policies.rs +++ b/crates/core/src/ast/traversal/policies.rs @@ -77,11 +77,13 @@ traversal_policy!(MemberFieldExpressionTraversalPolicy, traversal_policy!(NewExpressionTraversalPolicy, traverse_lifetime_obj, + traverse_unnamed, traverse_errors ); traversal_policy!(TypeCastExpressionTraversalPolicy, traverse_value, + traverse_unnamed, traverse_errors );