feat(query): New types and new fields for existing types (#746)

```diff
+ Argument.value
+ Argument implements HasSpan
+ ArgumentAST

- FnCall.arguments
+ FnCall.argument
- FnCallAST.arguments
+ FnCallAST.argument

+ interface Function
+ Function.is_async
+ Function.is_generator
+ Function.parameter
+ Function implements Expression
+ Function implements HasSpan

+ Parameter
+ Parameter.is_readonly
+ Parameter.assignment
+ Parameter.type_annotation
+ Parameter implements HasSpan
+ ParameterAST

+ ArrowFunction implements Function
+ ArrowFunction implements Expression
+ ArrowFunctionAST implements Function
+ ArrowFunctionAST implements Expression


+ FnDeclaration implements Function
+ FnDeclaration implements Expression
+ FnDeclarationAST implements Function
+ FnDeclarationAST implements Expression
```
This commit is contained in:
u9g 2023-08-16 00:56:43 -04:00 committed by GitHub
parent f4d16c2166
commit b346a9ad6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 487 additions and 26 deletions

View file

@ -71,6 +71,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
return resolve_property_with(contexts, |v| v.typename().into());
}
match type_name.as_ref() {
"ArrowFunctionAST" | "ArrowFunction" => {
super::properties::resolve_arrow_function_property(
contexts,
property_name.as_ref(),
resolve_info,
)
}
"AssignmentType" => super::properties::resolve_assignment_type_property(
contexts,
property_name.as_ref(),
@ -118,6 +125,11 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
property_name.as_ref(),
resolve_info,
),
"Function" => super::properties::resolve_function_property(
contexts,
property_name.as_ref(),
resolve_info,
),
"ImportAST" | "Import" => super::properties::resolve_import_property(
contexts,
property_name.as_ref(),
@ -169,6 +181,11 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
resolve_info,
)
}
"ParameterAST" | "Parameter" => super::properties::resolve_parameter_property(
contexts,
property_name.as_ref(),
resolve_info,
),
"PathPart" => super::properties::resolve_path_part_property(
contexts,
property_name.as_ref(),
@ -228,11 +245,12 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
resolve_info,
self,
),
"Argument" => super::edges::resolve_argument_edge(
"ArgumentAST" | "Argument" => super::edges::resolve_argument_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
self,
),
"AssignmentType" => super::edges::resolve_assignment_type_edge(
contexts,
@ -278,6 +296,12 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
parameters,
resolve_info,
),
"Function" => super::edges::resolve_function_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
),
"FunctionBodyAST" | "FunctionBody" => super::edges::resolve_function_body_edge(
contexts,
edge_name.as_ref(),
@ -438,6 +462,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
resolve_info,
self,
),
"ParameterAST" | "Parameter" => super::edges::resolve_parameter_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
self,
),
"ReassignmentAST" | "Reassignment" => super::edges::resolve_reassignment_edge(
contexts,
edge_name.as_ref(),

View file

@ -15,6 +15,8 @@ pub(super) fn resolve_arrow_function_edge<'a, 'b: 'a>(
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
match edge_name {
"span" => arrow_function::span(contexts, resolve_info),
"parameter" => arrow_function::parameter(contexts, resolve_info),
"strip_parens" => strip_parens(contexts),
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
_ => {
@ -27,11 +29,19 @@ pub(super) fn resolve_arrow_function_edge<'a, 'b: 'a>(
mod arrow_function {
use trustfall::provider::{
ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo, VertexIterator,
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
};
use super::super::vertex::Vertex;
pub(super) fn parameter<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
resolve_neighbors_with(contexts, |v| v.function_parameter())
}
pub(super) fn span<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
@ -44,9 +54,13 @@ pub(super) fn resolve_argument_edge<'a, 'b: 'a>(
edge_name: &str,
_parameters: &EdgeParameters,
resolve_info: &ResolveEdgeInfo,
adapter: &'a Adapter<'b>,
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
match edge_name {
"span" => argument::span(contexts, resolve_info),
"value" => argument::value(contexts, resolve_info),
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
_ => {
unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'Argument'")
}
@ -54,12 +68,34 @@ pub(super) fn resolve_argument_edge<'a, 'b: 'a>(
}
mod argument {
use oxc_ast::ast::Argument;
use trustfall::provider::{
ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo, VertexIterator,
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
};
use super::super::vertex::Vertex;
pub(super) fn value<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
resolve_neighbors_with(contexts, |v| {
let expr = match v
.as_argument()
.unwrap_or_else(|| {
panic!("expected to have an argument vertex, instead have: {v:#?}")
})
.argument
{
Argument::SpreadElement(spread) => &spread.argument,
Argument::Expression(expr) => expr,
};
Box::new(std::iter::once(expr.into()))
})
}
pub(super) fn span<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
@ -573,6 +609,45 @@ mod expression {
}
}
pub(super) fn resolve_function_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 {
"parameter" => function::parameter(contexts, resolve_info),
"span" => function::span(contexts, resolve_info),
"strip_parens" => strip_parens(contexts),
_ => {
unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'Function'")
}
}
}
mod function {
use trustfall::provider::{
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
};
use super::super::vertex::Vertex;
pub(super) fn parameter<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
resolve_neighbors_with(contexts, |v| v.function_parameter())
}
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_function_body_edge<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
edge_name: &str,
@ -636,6 +711,8 @@ pub(super) fn resolve_fn_declaration_edge<'a, 'b: 'a>(
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
match edge_name {
"span" => fn_declaration::span(contexts, resolve_info),
"parameter" => fn_declaration::parameter(contexts, resolve_info),
"strip_parens" => strip_parens(contexts),
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
_ => {
@ -648,11 +725,19 @@ pub(super) fn resolve_fn_declaration_edge<'a, 'b: 'a>(
mod fn_declaration {
use trustfall::provider::{
ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo, VertexIterator,
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
};
use super::super::vertex::Vertex;
pub(super) fn parameter<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
resolve_neighbors_with(contexts, |v| v.function_parameter())
}
pub(super) fn span<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
@ -671,6 +756,7 @@ pub(super) fn resolve_file_edge<'a, 'b: 'a>(
match edge_name {
"ast_node" => file::ast_node(contexts, resolve_info, adapter),
"class" => file::class(contexts, resolve_info, adapter),
"function" => file::function(contexts, resolve_info, adapter),
"import" => file::import(contexts, resolve_info, adapter),
"interface" => file::interface(contexts, resolve_info, adapter),
"jsx_element" => file::jsx_element(contexts, resolve_info, adapter),
@ -717,6 +803,23 @@ mod file {
})
}
pub(super) fn function<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
adapter: &'a Adapter<'b>,
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
resolve_neighbors_with(contexts, |_| {
Box::new(
adapter
.semantic
.nodes()
.iter()
.map(|node| (*node).into())
.filter(|x: &Vertex<'_>| x.is_arrow_function() || x.is_fn_declaration()),
)
})
}
pub(super) fn import<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
@ -814,7 +917,7 @@ pub(super) fn resolve_fn_call_edge<'a, 'b: 'a>(
match edge_name {
"span" => fn_call::span(contexts, resolve_info),
"callee" => fn_call::callee(contexts, resolve_info),
"arguments" => fn_call::arguments(contexts, resolve_info),
"argument" => fn_call::argument(contexts, resolve_info),
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
"strip_parens" => strip_parens(contexts),
@ -825,13 +928,13 @@ pub(super) fn resolve_fn_call_edge<'a, 'b: 'a>(
}
mod fn_call {
use oxc_ast::ast::Argument;
use oxc_span::GetSpan;
use trustfall::provider::{
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
};
use crate::vertex::ArgumentVertex;
use super::super::vertex::Vertex;
pub(super) fn callee<'a, 'b: 'a>(
@ -851,7 +954,7 @@ mod fn_call {
})
}
pub(super) fn arguments<'a, 'b: 'a>(
pub(super) fn argument<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_resolve_info: &ResolveEdgeInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
@ -864,11 +967,8 @@ mod fn_call {
.call_expression
.arguments
.iter()
.map(|x| {
Vertex::Argument(match x {
Argument::SpreadElement(spread) => spread.span,
Argument::Expression(expr) => expr.span(),
})
.map(|argument| {
Vertex::Argument(ArgumentVertex { ast_node: None, argument }.into())
}),
)
})
@ -1990,6 +2090,85 @@ mod path_part {
}
}
pub(super) fn resolve_parameter_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 {
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
"span" => parameter::span(contexts, resolve_info),
"assignment" => parameter::assignment(contexts, resolve_info),
"type_annotation" => parameter::type_annotation(contexts, resolve_info),
_ => {
unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'Parameter'")
}
}
}
mod parameter {
use trustfall::provider::{
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
};
use crate::vertex::TypeAnnotationVertex;
use super::{super::vertex::Vertex, get_span};
pub(super) fn assignment<'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(Vertex::AssignmentType(
&v.as_parameter()
.unwrap_or_else(|| {
panic!("expected to have a parameter vertex, instead have: {v:#?}")
})
.parameter
.pattern
.kind,
)))
})
}
pub(super) fn type_annotation<'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_parameter()
.unwrap_or_else(|| {
panic!("expected to have a parameter vertex, instead have: {v:#?}")
})
.parameter
.pattern
.type_annotation
.as_ref()
.map(|type_annotation| {
Vertex::TypeAnnotation(
TypeAnnotationVertex { type_annotation, ast_node: None }.into(),
)
})
.into_iter(),
)
})
}
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_reassignment_edge<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
edge_name: &str,

View file

@ -17,6 +17,25 @@ use crate::{
Adapter,
};
pub(super) fn resolve_arrow_function_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,
_resolve_info: &ResolveInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, FieldValue> {
match property_name {
"is_async" => resolve_property_with(contexts, |v| v.function_is_async().into()),
"is_generator" => resolve_property_with(contexts, |v| v.function_is_generator().into()),
"as_constant_string" => resolve_property_with(contexts, |v| {
v.as_constant_string().map_or(FieldValue::Null, Into::into)
}),
_ => {
unreachable!(
"attempted to read unexpected property '{property_name}' on type 'AssignmentType'"
)
}
}
}
pub(super) fn resolve_assignment_type_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,
@ -205,6 +224,11 @@ pub(super) fn resolve_fn_declaration_property<'a, 'b: 'a>(
.as_ref()
.map_or_else(|| FieldValue::Null, |f| f.name.to_string().into())
}),
"is_async" => resolve_property_with(contexts, |v| v.function_is_async().into()),
"is_generator" => resolve_property_with(contexts, |v| v.function_is_generator().into()),
"as_constant_string" => resolve_property_with(contexts, |v| {
v.as_constant_string().map_or(FieldValue::Null, Into::into)
}),
_ => {
unreachable!(
"attempted to read unexpected property '{property_name}' on type 'FnDeclaration'"
@ -228,6 +252,25 @@ pub(super) fn resolve_fn_call_property<'a, 'b: 'a>(
}
}
pub(super) fn resolve_function_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,
_resolve_info: &ResolveInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, FieldValue> {
match property_name {
"is_async" => resolve_property_with(contexts, |v| v.function_is_async().into()),
"is_generator" => resolve_property_with(contexts, |v| v.function_is_generator().into()),
"as_constant_string" => resolve_property_with(contexts, |v| {
v.as_constant_string().map_or(FieldValue::Null, Into::into)
}),
_ => {
unreachable!(
"attempted to read unexpected property '{property_name}' on type 'Function'"
)
}
}
}
pub(super) fn resolve_import_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,
@ -438,6 +481,29 @@ pub(super) fn resolve_object_literal_property<'a, 'b: 'a>(
}
}
pub(super) fn resolve_parameter_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,
_resolve_info: &ResolveInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, FieldValue> {
match property_name {
"is_readonly" => resolve_property_with(contexts, |v| {
v.as_parameter()
.unwrap_or_else(|| {
panic!("expected to have a parameter vertex, instead have: {v:#?}")
})
.parameter
.readonly
.into()
}),
_ => {
unreachable!(
"attempted to read unexpected property '{property_name}' on type 'Parameter'"
)
}
}
}
pub(super) fn resolve_path_part_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,

View file

@ -62,6 +62,8 @@ type File {
import: [ImportAST!]!
variable_declaration: [VariableDeclarationAST!]!
function: [Function!]!
ast_node: [ASTNode!]!
}
@ -391,13 +393,24 @@ type ObjectLiteralAST implements ObjectLiteral & Expression & HasSpan & ASTNode
span: Span!
}
interface Argument {
interface Argument implements HasSpan {
value: Expression!
# HasSpan
span: Span!
}
type ArgumentAST implements Argument & HasSpan & ASTNode {
value: Expression!
# ASTNode
parent: ASTNode
ancestor: [ASTNode!]!
# HasSpan
span: Span!
}
interface FnCall implements Expression & HasSpan {
callee: Expression!
arguments: [Argument!]!
argument: [Argument!]!
# Expression
as_constant_string: String
@ -408,7 +421,7 @@ interface FnCall implements Expression & HasSpan {
type FnCallAST implements FnCall & Expression & HasSpan & ASTNode {
callee: Expression!
arguments: [Argument!]!
argument: [Argument!]!
# Expression
as_constant_string: String
@ -481,12 +494,79 @@ type FunctionBodyAST implements HasSpan & ASTNode & FunctionBody {
ancestor: [ASTNode!]!
}
interface ArrowFunction implements HasSpan {
interface Function implements Expression & HasSpan {
is_async: Boolean!
is_generator: Boolean!
"""
Does not include rest parameter if it exists.
"""
parameter: [Parameter]!
# Expression
"""
Only non-null if the string can be trivially coerced to a constant string
ie: const a = "apple"; const b = `blueberry`
"""
as_constant_string: String
strip_parens: Expression!
# HasSpan
span: Span!
}
type ArrowFunctionAST implements HasSpan & ArrowFunction & ASTNode {
type Parameter {
is_readonly: Boolean!
assignment: AssignmentType!
type_annotation: TypeAnnotation!
# HasSpan
span: Span!
}
type ParameterAST implements ASTNode & HasSpan {
is_readonly: Boolean!
assignment: AssignmentType!
type_annotation: TypeAnnotation!
# HasSpan
span: Span!
# ASTNode
parent: ASTNode
ancestor: [ASTNode!]!
}
interface ArrowFunction implements Function & HasSpan & Expression {
# Function
is_async: Boolean!
is_generator: Boolean!
"""
Does not include rest parameter if it exists.
"""
parameter: [Parameter]!
# Expression
"""
Only non-null if the string can be trivially coerced to a constant string
ie: const a = "apple"; const b = `blueberry`
"""
as_constant_string: String
strip_parens: Expression!
# HasSpan
span: Span!
}
type ArrowFunctionAST implements Function & HasSpan & ArrowFunction & ASTNode & Expression {
# Function
is_async: Boolean!
is_generator: Boolean!
"""
Does not include rest parameter if it exists.
"""
parameter: [Parameter]!
# Expression
"""
Only non-null if the string can be trivially coerced to a constant string
ie: const a = "apple"; const b = `blueberry`
"""
as_constant_string: String
strip_parens: Expression!
# HasSpan
span: Span!
# ASTNode
@ -497,13 +577,27 @@ type ArrowFunctionAST implements HasSpan & ArrowFunction & ASTNode {
"""
A function defined in the sourcecode.
"""
interface FnDeclaration implements HasSpan {
interface FnDeclaration implements Function & HasSpan & Expression {
"""
If this function is used an an expression, the name can be omitted.
ie: "const a = function() {};"
"""
name: String
# Function
is_async: Boolean!
is_generator: Boolean!
"""
Does not include rest parameter if it exists.
"""
parameter: [Parameter]!
# Expression
"""
Only non-null if the string can be trivially coerced to a constant string
ie: const a = "apple"; const b = `blueberry`
"""
as_constant_string: String
strip_parens: Expression!
# HasSpan
span: Span!
}
@ -511,12 +605,26 @@ interface FnDeclaration implements HasSpan {
"""
A function defined in the sourcecode.
"""
type FnDeclarationAST implements ASTNode & FnDeclaration & HasSpan {
type FnDeclarationAST implements Function & ASTNode & FnDeclaration & HasSpan & Expression {
name: String
# Function
is_async: Boolean!
is_generator: Boolean!
"""
Does not include rest parameter if it exists.
"""
parameter: [Parameter]!
# ASTNode
parent: ASTNode
ancestor: [ASTNode!]!
# Expression
"""
Only non-null if the string can be trivially coerced to a constant string
ie: const a = "apple"; const b = `blueberry`
"""
as_constant_string: String
strip_parens: Expression!
# HasSpan
span: Span!
}

View file

@ -5,7 +5,7 @@ use enum_as_inner::EnumAsInner;
use oxc_ast::{ast::*, AstKind};
use oxc_semantic::{AstNode, AstNodeId};
use oxc_span::{GetSpan, Span};
use trustfall::provider::Typename;
use trustfall::provider::{Typename, VertexIterator};
use url::Url;
use crate::util::{expr_to_maybe_const_string, jsx_attribute_to_constant_string};
@ -52,9 +52,10 @@ pub enum Vertex<'a> {
FnCall(Rc<FnCallVertex<'a>>),
FnDeclaration(Rc<FnDeclarationVertex<'a>>),
ArrowFunction(Rc<ArrowFunctionVertex<'a>>),
Argument(Span),
Argument(Rc<ArgumentVertex<'a>>),
FunctionBody(Rc<FunctionBodyVertex<'a>>),
Statement(&'a Statement<'a>),
Parameter(Rc<ParameterVertex<'a>>),
}
impl<'a> Vertex<'a> {
@ -95,11 +96,12 @@ impl<'a> Vertex<'a> {
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::Argument(data) => data.argument.span(),
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::Parameter(data) => data.parameter.span,
Self::File
| Self::Url(_)
| Self::PathPart(_)
@ -133,6 +135,8 @@ impl<'a> Vertex<'a> {
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::Parameter(data) => data.ast_node.map(|x| x.id()),
Vertex::Argument(data) => data.ast_node.map(|x| x.id()),
Vertex::DefaultImport(_)
| Vertex::Statement(_)
| Vertex::AssignmentType(_)
@ -152,7 +156,6 @@ impl<'a> Vertex<'a> {
| Vertex::SpecificImport(_)
| Vertex::Span(_)
| Vertex::SearchParameter(_)
| Vertex::Argument(_)
| Vertex::ClassProperty(_) => None,
}
}
@ -190,6 +193,39 @@ impl<'a> Vertex<'a> {
) -> Option<Self> {
None
}
pub fn function_is_async(&self) -> bool {
match &self {
Vertex::ArrowFunction(data) => data.arrow_expression.r#async,
Vertex::FnDeclaration(data) => data.function.r#async,
_ => unreachable!(
"'function_is_async' function should only ever be called with an ArrowFunction or FnDeclaration"
),
}
}
pub fn function_is_generator(&self) -> bool {
match &self {
Vertex::ArrowFunction(data) => data.arrow_expression.generator,
Vertex::FnDeclaration(data) => data.function.generator,
_ => unreachable!(
"'function_is_generator' function should only ever be called with an ArrowFunction or FnDeclaration"
),
}
}
pub fn function_parameter(&self) -> VertexIterator<'a, Vertex<'a>> {
let parameter = match &self {
Vertex::ArrowFunction(data) => &data.arrow_expression.params.items,
Vertex::FnDeclaration(data) => &data.function.params.items,
_ => unreachable!(
"'function_parameter' function should only ever be called with an ArrowFunction or FnDeclaration"
),
};
Box::new(parameter.iter().map(|parameter| {
Vertex::Parameter(ParameterVertex { ast_node: None, parameter }.into())
}))
}
}
impl Typename for Vertex<'_> {
@ -235,10 +271,11 @@ impl Typename for Vertex<'_> {
Vertex::ObjectEntry(entry) => entry.typename(),
Vertex::FnCall(fncall) => fncall.typename(),
Vertex::Reassignment(reassignment) => reassignment.typename(),
Vertex::Argument(_) => "Argument",
Vertex::Argument(arg) => arg.typename(),
Vertex::FnDeclaration(fndecl) => fndecl.typename(),
Vertex::ArrowFunction(arrow_fn) => arrow_fn.typename(),
Vertex::FunctionBody(fn_body) => fn_body.typename(),
Vertex::Parameter(param) => param.typename(),
Vertex::Statement(_) => "Statement",
}
}
@ -319,6 +356,12 @@ impl<'a> From<AstNode<'a>> for Vertex<'a> {
AstKind::FunctionBody(function_body) => Vertex::FunctionBody(
FunctionBodyVertex { ast_node: Some(ast_node), function_body }.into(),
),
AstKind::FormalParameter(parameter) => {
Vertex::Parameter(ParameterVertex { ast_node: Some(ast_node), parameter }.into())
}
AstKind::Argument(argument) => {
Vertex::Argument(ArgumentVertex { ast_node: Some(ast_node), argument }.into())
}
_ => Vertex::ASTNode(ast_node),
}
}
@ -502,7 +545,7 @@ impl<'a> Typename for ReturnVertex<'a> {
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct TypeAnnotationVertex<'a> {
ast_node: Option<AstNode<'a>>,
pub ast_node: Option<AstNode<'a>>,
pub type_annotation: &'a TSTypeAnnotation<'a>,
}
@ -743,3 +786,37 @@ impl<'a> Typename for FunctionBodyVertex<'a> {
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct ParameterVertex<'a> {
ast_node: Option<AstNode<'a>>,
pub parameter: &'a FormalParameter<'a>,
}
impl<'a> Typename for ParameterVertex<'a> {
fn typename(&self) -> &'static str {
if self.ast_node.is_some() {
"ParameterAST"
} else {
"Parameter"
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct ArgumentVertex<'a> {
pub ast_node: Option<AstNode<'a>>,
pub argument: &'a Argument<'a>,
}
impl<'a> Typename for ArgumentVertex<'a> {
fn typename(&self) -> &'static str {
if self.ast_node.is_some() {
"ArgumentAST"
} else {
"Argument"
}
}
}