diff --git a/crates/oxc_query/src/adapter.rs b/crates/oxc_query/src/adapter.rs index c72ff6e08..1033bef8f 100644 --- a/crates/oxc_query/src/adapter.rs +++ b/crates/oxc_query/src/adapter.rs @@ -281,6 +281,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> { resolve_info, ) } + "VariableDeclarationAST" | "VariableDeclaration" => { + super::properties::resolve_variable_declaration_property( + contexts, + property_name.as_ref(), + resolve_info, + ) + } "VarRefAST" | "VarRef" => super::properties::resolve_var_ref_property( contexts, property_name.as_ref(), @@ -393,6 +400,14 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> { self, ) } + "ElidedArrayElementAST" | "ElidedArrayElement" => { + super::edges::resolve_elided_array_element_edge( + contexts, + edge_name.as_ref(), + parameters, + resolve_info, + ) + } "Expression" => super::edges::resolve_expression_edge( contexts, edge_name.as_ref(), @@ -646,6 +661,14 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> { parameters, resolve_info, ), + "SpreadArrayElementAST" | "SpreadArrayElement" => { + super::edges::resolve_spread_array_element_edge( + contexts, + edge_name.as_ref(), + parameters, + resolve_info, + ) + } "SpreadIntoObjectAST" | "SpreadIntoObject" => { super::edges::resolve_spread_into_object_edge( contexts, diff --git a/crates/oxc_query/src/edges.rs b/crates/oxc_query/src/edges.rs index c9bfbfd99..8e4e9bcf5 100644 --- a/crates/oxc_query/src/edges.rs +++ b/crates/oxc_query/src/edges.rs @@ -15,7 +15,7 @@ pub(super) fn resolve_array_edge<'a, 'b: 'a>( ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { match edge_name { "span" => array::span(contexts, resolve_info), - "elements" => array::elements(contexts, resolve_info), + "element" => array::element(contexts, resolve_info), "strip_parens" => strip_parens(contexts, parameters), "ancestor" => ancestors(contexts, adapter), "parent" => parents(contexts, adapter), @@ -31,11 +31,11 @@ mod array { VertexIterator, }; - use crate::vertex::ArrayElementVertex; + use crate::vertex::{ArrayElementVertex, ElidedArrayElementVertex, SpreadArrayElementVertex}; use super::super::vertex::Vertex; - pub(super) fn elements<'a, 'b: 'a>( + pub(super) fn element<'a, 'b: 'a>( contexts: ContextIterator<'a, Vertex<'b>>, _resolve_info: &ResolveEdgeInfo, ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { @@ -48,11 +48,27 @@ mod array { .array_expression .elements .iter() - .map(|x| { - Vertex::ArrayElement( - ArrayElementVertex { array_expression_element: x, ast_node: None } + .map(|x| match x { + oxc_ast::ast::ArrayExpressionElement::SpreadElement(spread) => { + Vertex::SpreadArrayElement( + SpreadArrayElementVertex { + ast_node: None, + spread: &spread.argument, + } .into(), - ) + ) + } + oxc_ast::ast::ArrayExpressionElement::Elision(span) => { + Vertex::ElidedArrayElement( + ElidedArrayElementVertex { ast_node: None, span: *span }.into(), + ) + } + oxc_ast::ast::ArrayExpressionElement::Expression(_) => { + Vertex::ArrayElement( + ArrayElementVertex { array_expression_element: x, ast_node: None } + .into(), + ) + } }), ) }) @@ -802,6 +818,37 @@ mod dot_property { } } +pub(super) fn resolve_elided_array_element_edge<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + edge_name: &str, + _parameters: &EdgeParameters, + resolve_info: &ResolveEdgeInfo, +) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { + match edge_name { + "span" => elided_array_element::span(contexts, resolve_info), + _ => { + unreachable!( + "attempted to resolve unexpected edge '{edge_name}' on type 'ElidedArrayElement'" + ) + } + } +} + +mod elided_array_element { + use trustfall::provider::{ + ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo, VertexIterator, + }; + + use super::super::vertex::Vertex; + + pub(super) fn span<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + _resolve_info: &ResolveEdgeInfo, + ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { + super::get_span(contexts) + } +} + pub(super) fn resolve_expression_edge<'a, 'b: 'a>( contexts: ContextIterator<'a, Vertex<'b>>, edge_name: &str, @@ -3046,6 +3093,55 @@ mod specific_import { } } +pub(super) fn resolve_spread_array_element_edge<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + edge_name: &str, + _parameters: &EdgeParameters, + resolve_info: &ResolveEdgeInfo, +) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { + match edge_name { + "span" => spread_array_element::span(contexts, resolve_info), + "spread" => spread_array_element::spread(contexts, resolve_info), + _ => { + unreachable!( + "attempted to resolve unexpected edge '{edge_name}' on type 'SpreadArrayElement'" + ) + } + } +} + +mod spread_array_element { + use trustfall::provider::{ + resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo, + VertexIterator, + }; + + use super::{super::vertex::Vertex, get_span}; + + pub(super) fn spread<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + _resolve_info: &ResolveEdgeInfo, + ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { + resolve_neighbors_with(contexts, |v| { + Box::new(std::iter::once( + (v.as_spread_array_element() + .unwrap_or_else(|| { + panic!("expected to have a spreadarrayelement vertex, instead have: {v:#?}") + }) + .spread) + .into(), + )) + }) + } + + pub(super) fn span<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + _resolve_info: &ResolveEdgeInfo, + ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { + get_span(contexts) + } +} + pub(super) fn resolve_spread_into_object_edge<'a, 'b: 'a>( contexts: ContextIterator<'a, Vertex<'b>>, edge_name: &str, diff --git a/crates/oxc_query/src/properties.rs b/crates/oxc_query/src/properties.rs index ce83e33f8..aa49e9cbb 100644 --- a/crates/oxc_query/src/properties.rs +++ b/crates/oxc_query/src/properties.rs @@ -885,6 +885,34 @@ pub(super) fn resolve_unary_expression_property<'a, 'b: 'a>( } } +pub(super) fn resolve_variable_declaration_property<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + property_name: &str, + _resolve_info: &ResolveInfo, +) -> ContextOutcomeIterator<'a, Vertex<'b>, FieldValue> { + match property_name { + "kind" => resolve_property_with(contexts, |v| { + match v + .as_variable_declaration() + .unwrap_or_else(|| { + panic!("expected to have a variabledeclaration vertex, instead have: {v:#?}",) + }) + .variable_declaration + .kind + { + oxc_ast::ast::VariableDeclarationKind::Var => "var".into(), + oxc_ast::ast::VariableDeclarationKind::Const => "const".into(), + oxc_ast::ast::VariableDeclarationKind::Let => "let".into(), + } + }), + _ => { + unreachable!( + "attempted to read unexpected property '{property_name}' on type 'LogicalExpression'" + ) + } + } +} + pub(super) fn resolve_var_ref_property<'a, 'b: 'a>( contexts: ContextIterator<'a, Vertex<'b>>, property_name: &str, diff --git a/crates/oxc_query/src/schema.graphql b/crates/oxc_query/src/schema.graphql index 00dccf24d..a7cda8103 100644 --- a/crates/oxc_query/src/schema.graphql +++ b/crates/oxc_query/src/schema.graphql @@ -276,6 +276,36 @@ type JSXText { span: Span! } +interface SpreadArrayElement implements ArrayElement & HasSpan { + spread: Expression! + # HasSpan + span: Span! +} + +type SpreadArrayElementAST implements ArrayElement & HasSpan & SpreadArrayElement { + spread: Expression! + # HasSpan + span: Span! +} + +""" +The element in this array would be elided: [,] +The element in the middle of this array is elided: [1,,3] +""" +interface ElidedArrayElement implements ArrayElement & HasSpan { + # HasSpan + span: Span! +} + +""" +The element in this array would be elided: [,] +The element in the middle of this array is elided: [1,,3] +""" +type ElidedArrayElementAST implements ArrayElement & HasSpan & ElidedArrayElement { + # HasSpan + span: Span! +} + interface ArrayElement implements HasSpan { # HasSpan span: Span! @@ -290,7 +320,7 @@ type ArrayElementAST implements HasSpan & ASTNode { } interface Array implements HasSpan & Expression { - elements: [ArrayElement!] + element: [ArrayElement!] # Expression as_constant_string: String """ @@ -303,7 +333,7 @@ interface Array implements HasSpan & Expression { } type ArrayAST implements HasSpan & Expression & Array & ASTNode { - elements: [ArrayElement!] + element: [ArrayElement!] # ASTNode parent: ASTNode ancestor: [ASTNode!]! @@ -1217,6 +1247,10 @@ this will fire once per assignment. type VariableDeclarationAST implements VariableDeclaration & ASTNode & HasSpan { left: AssignmentType! right: Expression + """ + 'let' | 'var' | 'const' + """ + kind: String! # ASTNode parent: ASTNode ancestor: [ASTNode!]! diff --git a/crates/oxc_query/src/vertex.rs b/crates/oxc_query/src/vertex.rs index 1a69dd993..1f9541a23 100644 --- a/crates/oxc_query/src/vertex.rs +++ b/crates/oxc_query/src/vertex.rs @@ -79,6 +79,8 @@ pub enum Vertex<'a> { TemplateLiteral(Rc>), RegExpLiteral(Rc>), ParenthesizedExpression(Rc>), + ElidedArrayElement(Rc>), + SpreadArrayElement(Rc>), } impl<'a> Vertex<'a> { @@ -142,6 +144,8 @@ impl<'a> Vertex<'a> { Self::TemplateLiteral(data) => data.template.span, Self::RegExpLiteral(data) => data.regexp.span, Self::ParenthesizedExpression(data) => data.parenthesized_expression.span, + Self::ElidedArrayElement(data) => data.span, + Self::SpreadArrayElement(data) => data.spread.span(), Self::File | Self::Url(_) | Self::PathPart(_) @@ -197,6 +201,8 @@ impl<'a> Vertex<'a> { Vertex::TemplateLiteral(data) => data.ast_node.map(|x| x.id()), Vertex::RegExpLiteral(data) => data.ast_node.map(|x| x.id()), Vertex::ParenthesizedExpression(data) => data.ast_node.map(|x| x.id()), + Vertex::ElidedArrayElement(data) => data.ast_node.map(|x| x.id()), + Vertex::SpreadArrayElement(data) => data.ast_node.map(|x| x.id()), Vertex::DefaultImport(_) | Vertex::Statement(_) | Vertex::AssignmentType(_) @@ -309,6 +315,8 @@ impl<'a> Vertex<'a> { | Vertex::Array(..) => true, Vertex::ASTNode(..) | Vertex::AssignmentType(..) + | Vertex::ElidedArrayElement(..) + | Vertex::SpreadArrayElement(..) | Vertex::Class(..) | Vertex::ClassMethod(..) | Vertex::ClassProperty(..) @@ -419,6 +427,8 @@ impl Typename for Vertex<'_> { Vertex::TemplateLiteral(data) => data.typename(), Vertex::RegExpLiteral(data) => data.typename(), Vertex::ParenthesizedExpression(data) => data.typename(), + Vertex::ElidedArrayElement(data) => data.typename(), + Vertex::SpreadArrayElement(data) => data.typename(), } } } @@ -567,6 +577,9 @@ impl<'a> From> for Vertex<'a> { .into(), ) } + AstKind::Elision(span) => Vertex::ElidedArrayElement( + ElidedArrayElementVertex { span, ast_node: Some(ast_node) }.into(), + ), _ => Vertex::ASTNode(ast_node), } } @@ -1400,3 +1413,37 @@ impl<'a> Typename for ParenthesizedExpressionVertex<'a> { } } } + +#[non_exhaustive] +#[derive(Debug, Clone)] +pub struct ElidedArrayElementVertex<'a> { + pub ast_node: Option>, + pub span: Span, +} + +impl<'a> Typename for ElidedArrayElementVertex<'a> { + fn typename(&self) -> &'static str { + if self.ast_node.is_some() { + "ElidedArrayElementAST" + } else { + "ElidedArrayElement" + } + } +} + +#[non_exhaustive] +#[derive(Debug, Clone)] +pub struct SpreadArrayElementVertex<'a> { + pub ast_node: Option>, + pub spread: &'a Expression<'a>, +} + +impl<'a> Typename for SpreadArrayElementVertex<'a> { + fn typename(&self) -> &'static str { + if self.ast_node.is_some() { + "SpreadArrayElementAST" + } else { + "SpreadArrayElement" + } + } +}