From 5dc69ea4ecedeb710b8a0b6a37dc2bf1e79d78e6 Mon Sep 17 00:00:00 2001 From: u9g Date: Tue, 15 Aug 2023 03:30:59 -0400 Subject: [PATCH] feat(query): Add many types (#742) --- crates/oxc_query/src/adapter.rs | 36 ++++- crates/oxc_query/src/edges.rs | 199 +++++++++++++++++++++++++--- crates/oxc_query/src/properties.rs | 24 ++++ crates/oxc_query/src/schema.graphql | 88 +++++++++++- crates/oxc_query/src/vertex.rs | 135 ++++++++++++++++--- 5 files changed, 443 insertions(+), 39 deletions(-) diff --git a/crates/oxc_query/src/adapter.rs b/crates/oxc_query/src/adapter.rs index 9cf080d1d..1d3b32b7f 100644 --- a/crates/oxc_query/src/adapter.rs +++ b/crates/oxc_query/src/adapter.rs @@ -106,6 +106,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> { property_name.as_ref(), resolve_info, ), + "FnDeclarationAST" | "FnDeclaration" => { + super::properties::resolve_fn_declaration_property( + contexts, + property_name.as_ref(), + resolve_info, + ) + } "FnCallAST" | "FnCall" => super::properties::resolve_fn_call_property( contexts, property_name.as_ref(), @@ -207,6 +214,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> { resolve_info: &ResolveEdgeInfo, ) -> ContextOutcomeIterator<'a, Self::Vertex, VertexIterator<'a, Self::Vertex>> { match type_name.as_ref() { + "ArrowFunctionAST" | "ArrowFunction" => super::edges::resolve_arrow_function_edge( + contexts, + edge_name.as_ref(), + parameters, + resolve_info, + self, + ), "ASTNode" => super::edges::resolve_astnode_edge( contexts, edge_name.as_ref(), @@ -264,6 +278,20 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> { parameters, resolve_info, ), + "FunctionBodyAST" | "FunctionBody" => super::edges::resolve_function_body_edge( + contexts, + edge_name.as_ref(), + parameters, + resolve_info, + self, + ), + "FnDeclarationAST" | "FnDeclaration" => super::edges::resolve_fn_declaration_edge( + contexts, + edge_name.as_ref(), + parameters, + resolve_info, + self, + ), "File" => super::edges::resolve_file_edge( contexts, edge_name.as_ref(), @@ -417,7 +445,7 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> { resolve_info, self, ), - "ReturnStatementAST" => super::edges::resolve_return_statement_ast_edge( + "ReturnAST" | "ReturnStatement" => super::edges::resolve_return_edge( contexts, edge_name.as_ref(), parameters, @@ -445,6 +473,12 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> { self, ) } + "Statement" => super::edges::resolve_statement_edge( + contexts, + edge_name.as_ref(), + parameters, + resolve_info, + ), "TypeAnnotation" | "TypeAnnotationAST" => super::edges::resolve_type_annotation_edge( contexts, edge_name.as_ref(), diff --git a/crates/oxc_query/src/edges.rs b/crates/oxc_query/src/edges.rs index 89b8ed9be..a67242fa2 100644 --- a/crates/oxc_query/src/edges.rs +++ b/crates/oxc_query/src/edges.rs @@ -1,3 +1,4 @@ +use oxc_ast::ast::Expression; use trustfall::provider::{ ContextIterator, ContextOutcomeIterator, EdgeParameters, ResolveEdgeInfo, VertexIterator, }; @@ -5,6 +6,39 @@ use trustfall::provider::{ use super::vertex::Vertex; use crate::Adapter; +pub(super) fn resolve_arrow_function_edge<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + edge_name: &str, + _parameters: &EdgeParameters, + resolve_info: &ResolveEdgeInfo, + adapter: &'a Adapter<'b>, +) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { + match edge_name { + "span" => arrow_function::span(contexts, resolve_info), + "ancestor" => ancestors(contexts, adapter), + "parent" => parents(contexts, adapter), + _ => { + unreachable!( + "attempted to resolve unexpected edge '{edge_name}' on type 'ArrowFunction'" + ) + } + } +} + +mod arrow_function { + 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_argument_edge<'a, 'b: 'a>( contexts: ContextIterator<'a, Vertex<'b>>, edge_name: &str, @@ -86,6 +120,17 @@ fn parents<'a, 'b: 'a>( }) } +fn strip_parens<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, +) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { + trustfall::provider::resolve_neighbors_with(contexts, |v| { + Box::new(std::iter::once(match v { + Vertex::Expression(Expression::ParenthesizedExpression(e)) => (&e.expression).into(), + _ => v.clone(), + })) + }) +} + fn get_span<'a, 'b: 'a>( contexts: ContextIterator<'a, Vertex<'b>>, ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { @@ -429,10 +474,11 @@ pub(super) fn resolve_dot_property_edge<'a, 'b: 'a>( ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { match edge_name { "span" => dot_property::span(contexts, resolve_info), - "ancestor" => ancestors(contexts, adapter), - "parent" => parents(contexts, adapter), "called_on" => dot_property::called_on(contexts, resolve_info), "accessed_property" => dot_property::accessed_property(contexts, resolve_info), + "ancestor" => ancestors(contexts, adapter), + "parent" => parents(contexts, adapter), + "strip_parens" => strip_parens(contexts), _ => { unreachable!( "attempted to resolve unexpected edge '{edge_name}' on type 'ClassProperty'" @@ -505,6 +551,7 @@ pub(super) fn resolve_expression_edge<'a, 'b: 'a>( ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { match edge_name { "span" => expression::span(contexts, resolve_info), + "strip_parens" => strip_parens(contexts), _ => { unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'Expression'") } @@ -526,6 +573,94 @@ mod expression { } } +pub(super) fn resolve_function_body_edge<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + edge_name: &str, + _parameters: &EdgeParameters, + resolve_info: &ResolveEdgeInfo, + adapter: &'a Adapter<'b>, +) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { + match edge_name { + "span" => function_body::span(contexts, resolve_info), + "statement" => function_body::statement(contexts, resolve_info), + "ancestor" => ancestors(contexts, adapter), + "parent" => parents(contexts, adapter), + _ => { + unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'FnBody'") + } + } +} + +mod function_body { + use std::convert::Into; + + use trustfall::provider::{ + resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo, + VertexIterator, + }; + + use super::super::vertex::Vertex; + + pub(super) fn statement<'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( + v.as_function_body() + .unwrap_or_else(|| { + panic!("expected to have a fnbody vertex, instead have: {v:#?}") + }) + .function_body + .statements + .iter() + .map(Into::into), + ) + }) + } + + 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_fn_declaration_edge<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + edge_name: &str, + _parameters: &EdgeParameters, + resolve_info: &ResolveEdgeInfo, + adapter: &'a Adapter<'b>, +) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { + match edge_name { + "span" => fn_declaration::span(contexts, resolve_info), + "ancestor" => ancestors(contexts, adapter), + "parent" => parents(contexts, adapter), + _ => { + unreachable!( + "attempted to resolve unexpected edge '{edge_name}' on type 'FnDeclaration'" + ) + } + } +} + +mod fn_declaration { + 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_file_edge<'a, 'b: 'a>( contexts: ContextIterator<'a, Vertex<'b>>, edge_name: &str, @@ -678,10 +813,11 @@ pub(super) fn resolve_fn_call_edge<'a, 'b: 'a>( ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { match edge_name { "span" => fn_call::span(contexts, resolve_info), - "ancestor" => ancestors(contexts, adapter), - "parent" => parents(contexts, adapter), "callee" => fn_call::callee(contexts, resolve_info), "arguments" => fn_call::arguments(contexts, resolve_info), + "ancestor" => ancestors(contexts, adapter), + "parent" => parents(contexts, adapter), + "strip_parens" => strip_parens(contexts), _ => { unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'FnCall'") } @@ -1133,6 +1269,7 @@ pub(super) fn resolve_jsxelement_edge<'a, 'b: 'a>( "span" => jsxelement::span(contexts, resolve_info), "ancestor" => ancestors(contexts, adapter), "parent" => parents(contexts, adapter), + "strip_parens" => strip_parens(contexts), _ => { unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'JSXElement'") } @@ -1556,6 +1693,7 @@ pub(super) fn resolve_number_literal_edge<'a, 'b: 'a>( "span" => number_literal::span(contexts, resolve_info), "ancestor" => ancestors(contexts, adapter), "parent" => parents(contexts, adapter), + "strip_parens" => strip_parens(contexts), _ => { unreachable!( "attempted to resolve unexpected edge '{edge_name}' on type 'NumberLiteral'" @@ -1676,6 +1814,7 @@ pub(super) fn resolve_object_literal_edge<'a, 'b: 'a>( "entry" => object_literal::entry(contexts, parameters, resolve_info), "ancestor" => ancestors(contexts, adapter), "parent" => parents(contexts, adapter), + "strip_parens" => strip_parens(contexts), _ => { unreachable!( "attempted to resolve unexpected edge '{edge_name}' on type 'ObjectLiteral'" @@ -1859,11 +1998,12 @@ pub(super) fn resolve_reassignment_edge<'a, 'b: 'a>( adapter: &'a Adapter<'b>, ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { match edge_name { - "parent" => parents(contexts, adapter), - "ancestor" => ancestors(contexts, adapter), "span" => reassignment::span(contexts, resolve_info), "left_as_expression" => reassignment::left_as_expression(contexts, resolve_info), "right" => reassignment::right(contexts, resolve_info), + "parent" => parents(contexts, adapter), + "ancestor" => ancestors(contexts, adapter), + "strip_parens" => strip_parens(contexts), _ => { unreachable!( "attempted to resolve unexpected edge '{edge_name}' on type 'Reassignment'" @@ -1950,7 +2090,7 @@ mod reassignment { } } -pub(super) fn resolve_return_statement_ast_edge<'a, 'b: 'a>( +pub(super) fn resolve_return_edge<'a, 'b: 'a>( contexts: ContextIterator<'a, Vertex<'b>>, edge_name: &str, _parameters: &EdgeParameters, @@ -1958,19 +2098,17 @@ pub(super) fn resolve_return_statement_ast_edge<'a, 'b: 'a>( adapter: &'a Adapter<'b>, ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { match edge_name { - "ancestor" => return_statement_ast::ancestor(contexts, resolve_info, adapter), - "expression" => return_statement_ast::expression(contexts, resolve_info), - "parent" => return_statement_ast::parent(contexts, resolve_info, adapter), - "span" => return_statement_ast::span(contexts, resolve_info), + "ancestor" => return_::ancestor(contexts, resolve_info, adapter), + "expression" => return_::expression(contexts, resolve_info), + "parent" => return_::parent(contexts, resolve_info, adapter), + "span" => return_::span(contexts, resolve_info), _ => { - unreachable!( - "attempted to resolve unexpected edge '{edge_name}' on type 'ReturnStatementAST'" - ) + unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'Return'") } } } -mod return_statement_ast { +mod return_ { use std::convert::Into; use trustfall::provider::{ @@ -1995,7 +2133,7 @@ mod return_statement_ast { ) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> { resolve_neighbors_with(contexts, |v| { let neighbors = v - .as_return_statement_ast() + .as_return() .unwrap() .return_statement .argument @@ -2189,6 +2327,35 @@ mod type_annotation { } } +pub(super) fn resolve_statement_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" => statement::span(contexts, resolve_info), + _ => { + unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'Statement'") + } + } +} + +mod statement { + use trustfall::provider::{ + ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo, VertexIterator, + }; + + use super::{super::vertex::Vertex, get_span}; + + 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_type_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 9b7210ef4..bc43d4fe0 100644 --- a/crates/oxc_query/src/properties.rs +++ b/crates/oxc_query/src/properties.rs @@ -189,6 +189,30 @@ pub(super) fn resolve_expression_property<'a, 'b: 'a>( } } +pub(super) fn resolve_fn_declaration_property<'a, 'b: 'a>( + contexts: ContextIterator<'a, Vertex<'b>>, + property_name: &str, + _resolve_info: &ResolveInfo, +) -> ContextOutcomeIterator<'a, Vertex<'b>, FieldValue> { + match property_name { + "name" => resolve_property_with(contexts, |v| { + v.as_fn_declaration() + .unwrap_or_else(|| { + panic!("expected to have a fndeclaration vertex, instead have: {v:#?}") + }) + .function + .id + .as_ref() + .map_or_else(|| FieldValue::Null, |f| f.name.to_string().into()) + }), + _ => { + unreachable!( + "attempted to read unexpected property '{property_name}' on type 'FnDeclaration'" + ) + } + } +} + pub(super) fn resolve_fn_call_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 c571b7e9c..d2632a8d6 100644 --- a/crates/oxc_query/src/schema.graphql +++ b/crates/oxc_query/src/schema.graphql @@ -285,6 +285,7 @@ interface NumberLiteral implements HasSpan & Expression { # Expression as_constant_string: String + strip_parens: Expression! } type NumberLiteralAST implements HasSpan & ASTNode & Expression & NumberLiteral { @@ -298,6 +299,7 @@ type NumberLiteralAST implements HasSpan & ASTNode & Expression & NumberLiteral ancestor: [ASTNode!]! # Expression as_constant_string: String + strip_parens: Expression! } # Expression @@ -316,6 +318,7 @@ interface JSXElement implements Expression & HasSpan { child_count: Int! # Expression as_constant_string: String + strip_parens: Expression! # HasSpan span: Span! } @@ -369,6 +372,7 @@ interface ObjectLiteral implements Expression & HasSpan { # Expression as_constant_string: String + strip_parens: Expression! # HasSpan span: Span! } @@ -379,6 +383,7 @@ type ObjectLiteralAST implements ObjectLiteral & Expression & HasSpan & ASTNode # Expression as_constant_string: String + strip_parens: Expression! # ASTNode parent: ASTNode ancestor: [ASTNode!]! @@ -396,6 +401,7 @@ interface FnCall implements Expression & HasSpan { # Expression as_constant_string: String + strip_parens: Expression! # HasSpan span: Span! } @@ -406,6 +412,7 @@ type FnCallAST implements FnCall & Expression & HasSpan & ASTNode { # Expression as_constant_string: String + strip_parens: Expression! # ASTNode parent: ASTNode ancestor: [ASTNode!]! @@ -426,6 +433,7 @@ interface Reassignment implements HasSpan & Expression { right: Expression! # Expression as_constant_string: String + strip_parens: Expression! # HasSpan span: Span! } @@ -443,6 +451,7 @@ type ReassignmentAST implements HasSpan & ASTNode & Reassignment & Expression { right: Expression! # Expression as_constant_string: String + strip_parens: Expression! # HasSpan span: Span! # ASTNode @@ -450,6 +459,68 @@ type ReassignmentAST implements HasSpan & ASTNode & Reassignment & Expression { ancestor: [ASTNode!]! } +interface Statement implements HasSpan { + # HasSpan + span: Span! +} + +interface FunctionBody implements HasSpan { + statement: [Statement!]! + + # HasSpan + span: Span! +} + +type FunctionBodyAST implements HasSpan & ASTNode & FunctionBody { + statement: [Statement!]! + + # HasSpan + span: Span! + # ASTNode + parent: ASTNode + ancestor: [ASTNode!]! +} + +interface ArrowFunction implements HasSpan { + # HasSpan + span: Span! +} + +type ArrowFunctionAST implements HasSpan & ArrowFunction & ASTNode { + # HasSpan + span: Span! + # ASTNode + parent: ASTNode + ancestor: [ASTNode!]! +} + +""" +A function defined in the sourcecode. +""" +interface FnDeclaration implements HasSpan { + """ + If this function is used an an expression, the name can be omitted. + ie: "const a = function() {};" + """ + name: String + + # HasSpan + span: Span! +} + +""" +A function defined in the sourcecode. +""" +type FnDeclarationAST implements ASTNode & FnDeclaration & HasSpan { + name: String + + # ASTNode + parent: ASTNode + ancestor: [ASTNode!]! + # HasSpan + span: Span! +} + interface Name implements HasSpan { name: String! # HasSpan @@ -476,6 +547,7 @@ interface DotProperty implements HasSpan & Expression { accessed_property: Name! # Expression as_constant_string: String + strip_parens: Expression! # HasSpan span: Span! } @@ -494,6 +566,7 @@ type DotPropertyAST implements DotProperty & ASTNode & HasSpan & Expression { ancestor: [ASTNode!]! # Expression as_constant_string: String + strip_parens: Expression! # HasSpan span: Span! } @@ -504,6 +577,7 @@ interface Expression implements HasSpan { ie: const a = "apple"; const b = `blueberry` """ as_constant_string: String + strip_parens: Expression! # HasSpan span: Span! @@ -579,6 +653,7 @@ type JSXElementAST implements JSXElement & Expression & ASTNode & HasSpan { child_count: Int! # Expression as_constant_string: String + strip_parens: Expression! # ASTNode parent: ASTNode ancestor: [ASTNode!]! @@ -626,7 +701,18 @@ type IfStatementAST implements ASTNode & HasSpan { span: Span! } -type ReturnStatementAST implements ASTNode & HasSpan { +type ReturnStatement implements Statement & HasSpan { + expression: Expression + + # ASTNode + parent: ASTNode + ancestor: [ASTNode!]! + + # HasSpan + span: Span! +} + +type ReturnAST implements ASTNode & HasSpan { expression: Expression # ASTNode diff --git a/crates/oxc_query/src/vertex.rs b/crates/oxc_query/src/vertex.rs index b15678f71..ca942f7a7 100644 --- a/crates/oxc_query/src/vertex.rs +++ b/crates/oxc_query/src/vertex.rs @@ -1,18 +1,8 @@ use std::rc::Rc; use enum_as_inner::EnumAsInner; -use oxc_ast::{ - ast::{ - AssignmentExpression, BindingPatternKind, CallExpression, Class, Expression, - IdentifierName, IdentifierReference, IfStatement, ImportDeclaration, - ImportDefaultSpecifier, ImportSpecifier, JSXAttribute, JSXElement, JSXExpressionContainer, - JSXFragment, JSXOpeningElement, JSXSpreadAttribute, JSXSpreadChild, JSXText, - MemberExpression, MethodDefinition, ModuleDeclaration, NumberLiteral, ObjectExpression, - ObjectProperty, PropertyDefinition, ReturnStatement, SpreadElement, StaticMemberExpression, - TSInterfaceDeclaration, TSType, TSTypeAnnotation, VariableDeclarator, - }, - AstKind, -}; +#[allow(clippy::wildcard_imports)] +use oxc_ast::{ast::*, AstKind}; use oxc_semantic::{AstNode, AstNodeId}; use oxc_span::{GetSpan, Span}; use trustfall::provider::Typename; @@ -53,14 +43,18 @@ pub enum Vertex<'a> { Type(&'a TSType<'a>), Url(Rc), VariableDeclaration(Rc>), - ReturnStatementAST(Rc>), + Return(Rc>), IfStatementAST(Rc>), SpreadIntoObject(Rc>), ObjectEntry(Rc>), DotProperty(Rc>), Reassignment(Rc>), FnCall(Rc>), + FnDeclaration(Rc>), + ArrowFunction(Rc>), Argument(Span), + FunctionBody(Rc>), + Statement(&'a Statement<'a>), } impl<'a> Vertex<'a> { @@ -95,13 +89,17 @@ impl<'a> Vertex<'a> { Self::TypeAnnotation(data) => data.type_annotation.span, Self::Type(data) => data.span(), Self::VariableDeclaration(data) => data.variable_declaration.span, - Self::ReturnStatementAST(data) => data.return_statement.span, + Self::Return(data) => data.return_statement.span, Self::IfStatementAST(data) => data.return_statement.span, Self::NumberLiteral(data) => data.number_literal.span, Self::Reassignment(data) => data.assignment_expression.span, Self::Name(data) => data.name.span, Self::FnCall(data) => data.call_expression.span, Self::Argument(data) => *data, + Self::FnDeclaration(data) => data.function.span, + Self::ArrowFunction(data) => data.arrow_expression.span, + Self::FunctionBody(data) => data.function_body.span, + Self::Statement(data) => data.span(), Self::File | Self::Url(_) | Self::PathPart(_) @@ -122,7 +120,7 @@ impl<'a> Vertex<'a> { Vertex::TypeAnnotation(data) => data.ast_node.map(|x| x.id()), Vertex::VariableDeclaration(data) => data.ast_node.map(|x| x.id()), Vertex::ObjectLiteral(data) => data.ast_node.map(|x| x.id()), - Vertex::ReturnStatementAST(data) => data.ast_node.map(|x| x.id()), + Vertex::Return(data) => data.ast_node.map(|x| x.id()), Vertex::IfStatementAST(data) => data.ast_node.map(|x| x.id()), Vertex::JSXOpeningElement(data) => data.ast_node.map(|x| x.id()), Vertex::NumberLiteral(data) => data.ast_node.map(|x| x.id()), @@ -132,7 +130,11 @@ impl<'a> Vertex<'a> { Vertex::DotProperty(data) => data.ast_node.map(|x| x.id()), Vertex::Reassignment(data) => data.ast_node.map(|x| x.id()), Vertex::FnCall(data) => data.ast_node.map(|x| x.id()), + Vertex::FnDeclaration(data) => data.ast_node.map(|x| x.id()), + Vertex::ArrowFunction(data) => data.ast_node.map(|x| x.id()), + Vertex::FunctionBody(data) => data.ast_node.map(|x| x.id()), Vertex::DefaultImport(_) + | Vertex::Statement(_) | Vertex::AssignmentType(_) | Vertex::ClassMethod(_) | Vertex::Expression(_) @@ -227,13 +229,17 @@ impl Typename for Vertex<'_> { Vertex::Url(_) => "URL", Vertex::VariableDeclaration(vd) => vd.typename(), Vertex::Name(name) => name.typename(), - Vertex::ReturnStatementAST(_) => "ReturnStatementAST", + Vertex::Return(ret) => ret.typename(), Vertex::IfStatementAST(_) => "IfStatementAST", Vertex::SpreadIntoObject(obj) => obj.typename(), Vertex::ObjectEntry(entry) => entry.typename(), Vertex::FnCall(fncall) => fncall.typename(), Vertex::Reassignment(reassignment) => reassignment.typename(), Vertex::Argument(_) => "Argument", + Vertex::FnDeclaration(fndecl) => fndecl.typename(), + Vertex::ArrowFunction(arrow_fn) => arrow_fn.typename(), + Vertex::FunctionBody(fn_body) => fn_body.typename(), + Vertex::Statement(_) => "Statement", } } } @@ -241,9 +247,9 @@ impl Typename for Vertex<'_> { impl<'a> From> for Vertex<'a> { fn from(ast_node: AstNode<'a>) -> Self { match ast_node.kind() { - AstKind::ReturnStatement(return_statement) => Self::ReturnStatementAST( - ReturnStatementVertex { ast_node: Some(ast_node), return_statement }.into(), - ), + AstKind::ReturnStatement(return_statement) => { + Self::Return(ReturnVertex { ast_node: Some(ast_node), return_statement }.into()) + } AstKind::IfStatement(if_statement) => Self::IfStatementAST( IfStatementVertex { ast_node: Some(ast_node), return_statement: if_statement } .into(), @@ -304,17 +310,37 @@ impl<'a> From> for Vertex<'a> { AstKind::CallExpression(call_expression) => { Vertex::FnCall(FnCallVertex { ast_node: Some(ast_node), call_expression }.into()) } + AstKind::Function(function) => Vertex::FnDeclaration( + FnDeclarationVertex { ast_node: Some(ast_node), function }.into(), + ), + AstKind::ArrowExpression(arrow_expression) => Vertex::ArrowFunction( + ArrowFunctionVertex { ast_node: Some(ast_node), arrow_expression }.into(), + ), + AstKind::FunctionBody(function_body) => Vertex::FunctionBody( + FunctionBodyVertex { ast_node: Some(ast_node), function_body }.into(), + ), _ => Vertex::ASTNode(ast_node), } } } +impl<'a> From<&'a Statement<'a>> for Vertex<'a> { + fn from(stmt: &'a Statement<'a>) -> Self { + match &stmt { + Statement::ReturnStatement(return_statement) => { + Vertex::Return(ReturnVertex { ast_node: None, return_statement }.into()) + } + _ => Vertex::Statement(stmt), + } + } +} + impl<'a> From<&'a Expression<'a>> for Vertex<'a> { fn from(expr: &'a Expression<'a>) -> Self { // FIXME: We just get rid of all parentheses here, but we shouldn't do that... // NOTE: When string literal / template literal is added, add to as_constant_string - match &expr.get_inner_expression() { + match &expr { Expression::ObjectExpression(object_expression) => Vertex::ObjectLiteral( ObjectLiteralVertex { ast_node: None, object_expression }.into(), ), @@ -335,6 +361,12 @@ impl<'a> From<&'a Expression<'a>> for Vertex<'a> { Expression::CallExpression(call_expression) => { Vertex::FnCall(FnCallVertex { ast_node: None, call_expression }.into()) } + Expression::FunctionExpression(fn_expression) => Vertex::FnDeclaration( + FnDeclarationVertex { ast_node: None, function: fn_expression }.into(), + ), + Expression::ArrowExpression(arrow_expression) => Vertex::ArrowFunction( + ArrowFunctionVertex { ast_node: None, arrow_expression }.into(), + ), _ => Vertex::Expression(expr), } } @@ -452,11 +484,21 @@ pub struct IfStatementVertex<'a> { #[non_exhaustive] #[derive(Debug, Clone)] -pub struct ReturnStatementVertex<'a> { +pub struct ReturnVertex<'a> { ast_node: Option>, pub return_statement: &'a ReturnStatement<'a>, } +impl<'a> Typename for ReturnVertex<'a> { + fn typename(&self) -> &'static str { + if self.ast_node.is_some() { + "ReturnAST" + } else { + "ReturnStatement" + } + } +} + #[non_exhaustive] #[derive(Debug, Clone)] pub struct TypeAnnotationVertex<'a> { @@ -650,3 +692,54 @@ impl<'a> Typename for FnCallVertex<'a> { } } } + +#[non_exhaustive] +#[derive(Debug, Clone)] +pub struct FnDeclarationVertex<'a> { + ast_node: Option>, + pub function: &'a Function<'a>, +} + +impl<'a> Typename for FnDeclarationVertex<'a> { + fn typename(&self) -> &'static str { + if self.ast_node.is_some() { + "FnDeclarationAST" + } else { + "FnDeclaration" + } + } +} + +#[non_exhaustive] +#[derive(Debug, Clone)] +pub struct ArrowFunctionVertex<'a> { + ast_node: Option>, + pub arrow_expression: &'a ArrowExpression<'a>, +} + +impl<'a> Typename for ArrowFunctionVertex<'a> { + fn typename(&self) -> &'static str { + if self.ast_node.is_some() { + "ArrowFunctionAST" + } else { + "ArrowFunction" + } + } +} + +#[non_exhaustive] +#[derive(Debug, Clone)] +pub struct FunctionBodyVertex<'a> { + ast_node: Option>, + pub function_body: &'a FunctionBody<'a>, +} + +impl<'a> Typename for FunctionBodyVertex<'a> { + fn typename(&self) -> &'static str { + if self.ast_node.is_some() { + "FunctionBodyAST" + } else { + "FunctionBody" + } + } +}