feat(query): add many types to oxc_query (#724)

Adds `Name(AST)?`, `IfStatementAST`, `SpreadIntoObject(AST)?`,
`ObjectEntry(AST)?`, `DotProperty(AST)?` types

Fixes `ObjectLiteral`'s value field's output type

Added `entry` field to `ObjectLiteral(AST)?`
This commit is contained in:
u9g 2023-08-12 04:43:58 -04:00 committed by GitHub
parent 7daab49ca5
commit 9566378119
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 689 additions and 12 deletions

View file

@ -96,6 +96,11 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
property_name.as_ref(),
resolve_info,
),
"DotPropertyAST" | "DotProperty" => super::properties::resolve_dot_property_property(
contexts,
property_name.as_ref(),
resolve_info,
),
"Expression" => super::properties::resolve_expression_property(
contexts,
property_name.as_ref(),
@ -143,6 +148,11 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
property_name.as_ref(),
resolve_info,
),
"NameAST" | "Name" => super::properties::resolve_name_property(
contexts,
property_name.as_ref(),
resolve_info,
),
"NumberLiteralAST" | "NumberLiteral" => {
super::properties::resolve_number_literal_property(
contexts,
@ -239,6 +249,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
parameters,
resolve_info,
),
"DotPropertyAST" | "DotProperty" => super::edges::resolve_dot_property_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
self,
),
"DefaultImport" => super::edges::resolve_default_import_edge(
contexts,
edge_name.as_ref(),
@ -264,6 +281,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
parameters,
resolve_info,
),
"IfStatementAST" => super::edges::resolve_if_statement_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
self,
),
"Import" | "ImportAST" => super::edges::resolve_import_edge(
contexts,
edge_name.as_ref(),
@ -342,6 +366,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
parameters,
resolve_info,
),
"NameAST" | "Name" => super::edges::resolve_name_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
self,
),
"NumberLiteralAST" | "NumberLiteral" => super::edges::resolve_number_literal_edge(
contexts,
edge_name.as_ref(),
@ -349,6 +380,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
resolve_info,
self,
),
"ObjectEntryAST" | "ObjectEntry" => super::edges::resolve_object_entry_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
self,
),
"ObjectLiteral" | "ObjectLiteralAST" => super::edges::resolve_object_literal_edge(
contexts,
edge_name.as_ref(),
@ -356,6 +394,12 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
resolve_info,
self,
),
"ObjectProperty" => super::edges::resolve_object_property_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
),
"PathPart" => super::edges::resolve_path_part_edge(
contexts,
edge_name.as_ref(),
@ -382,6 +426,15 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
parameters,
resolve_info,
),
"SpreadIntoObjectAST" | "SpreadIntoObject" => {
super::edges::resolve_spread_into_object_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
self,
)
}
"TypeAnnotation" | "TypeAnnotationAST" => super::edges::resolve_type_annotation_edge(
contexts,
edge_name.as_ref(),

View file

@ -391,6 +391,83 @@ mod default_import {
}
}
pub(super) fn resolve_dot_property_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" => 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),
_ => {
unreachable!(
"attempted to resolve unexpected edge '{edge_name}' on type 'ClassProperty'"
)
}
}
}
mod dot_property {
use trustfall::provider::{
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
};
use crate::vertex::NameVertex;
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 called_on<'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_dot_property()
.unwrap_or_else(|| {
panic!("expected to have a dotproperty vertex, instead have: {v:#?}")
})
.static_member_expr
.object)
.into(),
))
})
}
pub(super) fn accessed_property<'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::Name(
NameVertex {
ast_node: None,
name: &v
.as_dot_property()
.unwrap_or_else(|| {
panic!("expected to have a dotproperty vertex, instead have: {v:#?}")
})
.static_member_expr
.property,
}
.into(),
)))
})
}
}
pub(super) fn resolve_expression_edge<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
edge_name: &str,
@ -592,6 +669,59 @@ mod has_span {
}
}
pub(super) fn resolve_if_statement_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" => if_statement::span(contexts, resolve_info),
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
"condition" => if_statement::condition(contexts, resolve_info),
_ => {
unreachable!(
"attempted to resolve unexpected edge '{edge_name}' on type 'IfStatementAST'"
)
}
}
}
mod if_statement {
use trustfall::provider::{
resolve_neighbors_with, 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 condition<'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_if_statement_ast()
.unwrap_or_else(|| {
panic!("expected to have an if_statement_ast vertex, instead have: {v:#?}")
})
.return_statement
.test)
.into(),
))
})
}
}
pub(super) fn resolve_import_edge<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
edge_name: &str,
@ -1277,6 +1407,38 @@ mod member_extend {
}
}
pub(super) fn resolve_name_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" => name::span(contexts, resolve_info),
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
_ => {
unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'Name'")
}
}
}
mod name {
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_number_literal_edge<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
edge_name: &str,
@ -1290,7 +1452,7 @@ pub(super) fn resolve_number_literal_edge<'a, 'b: 'a>(
"parent" => parents(contexts, adapter),
_ => {
unreachable!(
"attempted to resolve unexpected edge '{edge_name}' on type 'MemberExtend'"
"attempted to resolve unexpected edge '{edge_name}' on type 'NumberLiteral'"
)
}
}
@ -1311,6 +1473,83 @@ mod number_literal {
}
}
pub(super) fn resolve_object_entry_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" => object_entry::span(contexts, resolve_info),
"key" => object_entry::key(contexts, resolve_info),
"value" => object_entry::value(contexts, resolve_info),
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
_ => {
unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'ObjectEntry'")
}
}
}
mod object_entry {
use trustfall::provider::{
resolve_neighbors_with, 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 key<'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 key = &v
.as_object_entry()
.map_or_else(
|| panic!("expected to have a objectentry vertex, instead have: {v:#?}"),
|x| &x.property,
)
.key;
let vertex: Vertex<'_> = match &key {
oxc_ast::ast::PropertyKey::Identifier(_) => return Box::new(std::iter::empty()), // TODO: FINISH
oxc_ast::ast::PropertyKey::PrivateIdentifier(_) => unreachable!(
"private identifiers don't exist in objects, so this should never be called"
),
oxc_ast::ast::PropertyKey::Expression(expr) => expr.into(),
};
Box::new(std::iter::once(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 value = &v
.as_object_entry()
.map_or_else(
|| panic!("expected to have a objectentry vertex, instead have: {v:#?}"),
|x| &x.property,
)
.value;
Box::new(std::iter::once(value.into()))
})
}
}
pub(super) fn resolve_object_literal_edge<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
edge_name: &str,
@ -1328,6 +1567,7 @@ pub(super) fn resolve_object_literal_edge<'a, 'b: 'a>(
.expect("unexpected null or other incorrect datatype for Trustfall type 'String!'");
object_literal::value(contexts, key, resolve_info)
}
"entry" => object_literal::entry(contexts, parameters, resolve_info),
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
_ => {
@ -1343,12 +1583,15 @@ mod object_literal {
use oxc_ast::ast::ObjectPropertyKind;
use trustfall::provider::{
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, EdgeParameters,
ResolveEdgeInfo, VertexIterator,
};
use super::{super::vertex::Vertex, get_span};
use crate::util::expr_to_maybe_const_string;
use crate::{
util::expr_to_maybe_const_string,
vertex::{ObjectEntryVertex, SpreadIntoObjectVertex},
};
pub(super) fn span<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
@ -1389,6 +1632,58 @@ mod object_literal {
}))
})
}
pub(super) fn entry<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
_parameters: &EdgeParameters,
_resolve_info: &ResolveEdgeInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, VertexIterator<'a, Vertex<'b>>> {
resolve_neighbors_with(contexts, |v| {
let obj = v.as_object_literal().unwrap_or_else(|| {
panic!("expected to have an objectliteral vertex, instead have: {v:#?}")
});
Box::new(obj.object_expression.properties.iter().map(|property| match property {
oxc_ast::ast::ObjectPropertyKind::ObjectProperty(property) => {
Vertex::ObjectEntry(ObjectEntryVertex { property, ast_node: None }.into())
}
oxc_ast::ast::ObjectPropertyKind::SpreadProperty(property) => {
Vertex::SpreadIntoObject(
SpreadIntoObjectVertex { property, ast_node: None }.into(),
)
}
}))
})
}
}
pub(super) fn resolve_object_property_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" => object_property::span(contexts, resolve_info),
_ => {
unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'Name'")
}
}
}
mod object_property {
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_path_part_edge<'a, 'b: 'a>(
@ -1584,6 +1879,59 @@ mod specific_import {
}
}
pub(super) fn resolve_spread_into_object_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" => resolve_spread_into_object_edge::span(contexts, resolve_info),
"value" => resolve_spread_into_object_edge::value(contexts, resolve_info),
"ancestor" => ancestors(contexts, adapter),
"parent" => parents(contexts, adapter),
_ => {
unreachable!(
"attempted to resolve unexpected edge '{edge_name}' on type 'SpreadIntoObject'"
)
}
}
}
mod resolve_spread_into_object_edge {
use trustfall::provider::{
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
};
use super::{super::vertex::Vertex, get_span};
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 argument = &v
.as_spread_into_object()
.map_or_else(
|| panic!("expected to have a spreadintoobject vertex, instead have: {v:#?}"),
|x| &x.property,
)
.argument;
Box::new(std::iter::once(argument.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_type_annotation_edge<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
edge_name: &str,

View file

@ -196,6 +196,23 @@ pub(super) fn resolve_default_import_property<'a, 'b: 'a>(
}
}
pub(super) fn resolve_dot_property_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,
_resolve_info: &ResolveInfo,
) -> ContextOutcomeIterator<'a, Vertex<'b>, FieldValue> {
match property_name {
"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 'DotProperty'"
)
}
}
}
pub(super) fn resolve_expression_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,
@ -384,6 +401,26 @@ pub(super) fn resolve_member_extend_property<'a, 'b: 'a>(
}
}
pub(super) fn resolve_name_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_name()
.unwrap_or_else(|| panic!("expected to have a name vertex, instead have: {v:#?}"))
.name
.name
.to_string()
.into()
}),
_ => {
unreachable!("attempted to read unexpected property '{property_name}' on type 'Name'")
}
}
}
pub(super) fn resolve_number_literal_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,
@ -410,7 +447,7 @@ pub(super) fn resolve_number_literal_property<'a, 'b: 'a>(
}),
_ => {
unreachable!(
"attempted to read unexpected property '{property_name}' on type 'MemberExtend'"
"attempted to read unexpected property '{property_name}' on type 'NumberLiteral'"
)
}
}

View file

@ -326,8 +326,52 @@ interface JSXElement implements Expression & HasSpan {
span: Span!
}
interface ObjectProperty implements HasSpan {
# HasSpan
span: Span!
}
interface SpreadIntoObject implements ObjectProperty & HasSpan {
value: Expression!
# HasSpan
span: Span!
}
type SpreadIntoObjectAST implements ASTNode & SpreadIntoObject & ObjectProperty & HasSpan {
value: Expression!
# ASTNode
parent: ASTNode
ancestor: [ASTNode!]!
# HasSpan
span: Span!
}
interface ObjectEntry implements ObjectProperty & HasSpan {
key: Expression!
value: Expression!
# HasSpan
span: Span!
}
type ObjectEntryAST implements ASTNode & ObjectEntry & ObjectProperty & HasSpan {
key: Expression!
value: Expression!
# ASTNode
parent: ASTNode
ancestor: [ASTNode!]!
# HasSpan
span: Span!
}
interface ObjectLiteral implements Expression & HasSpan {
value(key: String!): [Expression!]!
value(key: String!): Expression
entry: [ObjectProperty!]!
# Expression
as_constant_string: String
@ -336,7 +380,8 @@ interface ObjectLiteral implements Expression & HasSpan {
}
type ObjectLiteralAST implements ObjectLiteral & Expression & HasSpan & ASTNode {
value(key: String!): [Expression!]!
value(key: String!): Expression
entry: [ObjectProperty!]!
# Expression
as_constant_string: String
@ -347,6 +392,54 @@ type ObjectLiteralAST implements ObjectLiteral & Expression & HasSpan & ASTNode
span: Span!
}
interface Name implements HasSpan {
name: String!
# HasSpan
span: Span!
}
type NameAST implements ASTNode & Name & HasSpan {
name: String!
# ASTNode
parent: ASTNode
ancestor: [ASTNode!]!
# HasSpan
span: Span!
}
interface DotProperty implements HasSpan & Expression {
"""
In "data.user.name", this would be "data.user"
"""
called_on: Expression!
"""
In "data.user.name", this would be "name"
"""
accessed_property: Name!
# Expression
as_constant_string: String
# HasSpan
span: Span!
}
type DotPropertyAST implements DotProperty & ASTNode & HasSpan & Expression {
"""
In "data.user.name", this would be "data.user"
"""
called_on: Expression!
"""
In "data.user.name", this would be "name"
"""
accessed_property: Name!
# ASTNode
parent: ASTNode
ancestor: [ASTNode!]!
# Expression
as_constant_string: String
# HasSpan
span: Span!
}
interface Expression implements HasSpan {
"""
Only non-null if the string can be trivially coerced to a constant string
@ -464,6 +557,17 @@ type ClassAST implements ASTNode & Class & HasSpan {
span: Span!
}
type IfStatementAST implements ASTNode & HasSpan {
condition: Expression!
# ASTNode
parent: ASTNode
ancestor: [ASTNode!]!
# HasSpan
span: Span!
}
type ReturnStatementAST implements ASTNode & HasSpan {
expression: Expression

View file

@ -3,11 +3,12 @@ use std::rc::Rc;
use enum_as_inner::EnumAsInner;
use oxc_ast::{
ast::{
BindingPatternKind, Class, Expression, IdentifierReference, ImportDeclaration,
ImportDefaultSpecifier, ImportSpecifier, JSXAttribute, JSXElement, JSXExpressionContainer,
JSXFragment, JSXOpeningElement, JSXSpreadAttribute, JSXSpreadChild, JSXText,
MemberExpression, MethodDefinition, ModuleDeclaration, NumberLiteral, ObjectExpression,
PropertyDefinition, ReturnStatement, TSInterfaceDeclaration, TSType, TSTypeAnnotation,
BindingPatternKind, 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,
@ -43,6 +44,7 @@ pub enum Vertex<'a> {
JSXText(&'a JSXText),
ObjectLiteral(Rc<ObjectLiteralVertex<'a>>),
NumberLiteral(Rc<NumberLiteralVertex<'a>>),
Name(Rc<NameVertex<'a>>),
PathPart(usize),
SearchParameter(Rc<SearchParameterVertex>),
Span(Span),
@ -52,6 +54,10 @@ pub enum Vertex<'a> {
Url(Rc<Url>),
VariableDeclaration(Rc<VariableDeclarationVertex<'a>>),
ReturnStatementAST(Rc<ReturnStatementVertex<'a>>),
IfStatementAST(Rc<IfStatementVertex<'a>>),
SpreadIntoObject(Rc<SpreadIntoObjectVertex<'a>>),
ObjectEntry(Rc<ObjectEntryVertex<'a>>),
DotProperty(Rc<DotPropertyVertex<'a>>),
}
impl<'a> Vertex<'a> {
@ -75,16 +81,21 @@ impl<'a> Vertex<'a> {
Self::JSXExpressionContainer(data) => data.span,
Self::JSXFragment(data) => data.span,
Self::JSXOpeningElement(data) => data.opening_element.span,
Self::DotProperty(data) => data.static_member_expr.span,
Self::JSXSpreadAttribute(data) => data.span,
Self::JSXSpreadChild(data) => data.span,
Self::JSXText(data) => data.span,
Self::ObjectLiteral(data) => data.object_expression.span,
Self::SpreadIntoObject(data) => data.property.span,
Self::ObjectEntry(data) => data.property.span,
Self::SpecificImport(data) => data.span,
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::IfStatementAST(data) => data.return_statement.span,
Self::NumberLiteral(data) => data.number_literal.span,
Self::Name(data) => data.name.span,
Self::File
| Self::Url(_)
| Self::PathPart(_)
@ -106,8 +117,13 @@ impl<'a> Vertex<'a> {
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::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()),
Vertex::Name(data) => data.ast_node.map(|x| x.id()),
Vertex::SpreadIntoObject(data) => data.ast_node.map(|x| x.id()),
Vertex::ObjectEntry(data) => data.ast_node.map(|x| x.id()),
Vertex::DotProperty(data) => data.ast_node.map(|x| x.id()),
Vertex::DefaultImport(_)
| Vertex::AssignmentType(_)
| Vertex::ClassMethod(_)
@ -160,6 +176,7 @@ impl Typename for Vertex<'_> {
Vertex::Import(import) => import.typename(),
Vertex::Interface(iface) => iface.typename(),
Vertex::NumberLiteral(nlit) => nlit.typename(),
Vertex::DotProperty(dot_property) => dot_property.typename(),
Vertex::InterfaceExtend(iex) => match **iex {
InterfaceExtendVertex::Identifier(_) => "SimpleExtend",
InterfaceExtendVertex::MemberExpression(_) => "MemberExtend",
@ -181,7 +198,11 @@ impl Typename for Vertex<'_> {
Vertex::Type(_) => "Type",
Vertex::Url(_) => "URL",
Vertex::VariableDeclaration(vd) => vd.typename(),
Vertex::Name(name) => name.typename(),
Vertex::ReturnStatementAST(_) => "ReturnStatementAST",
Vertex::IfStatementAST(_) => "IfStatementAST",
Vertex::SpreadIntoObject(obj) => obj.typename(),
Vertex::ObjectEntry(entry) => entry.typename(),
}
}
}
@ -192,6 +213,10 @@ impl<'a> From<AstNode<'a>> for Vertex<'a> {
AstKind::ReturnStatement(return_statement) => Self::ReturnStatementAST(
ReturnStatementVertex { 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(),
),
AstKind::JSXElement(element) => {
Self::JSXElement(JSXElementVertex { ast_node: Some(ast_node), element }.into())
}
@ -219,6 +244,29 @@ impl<'a> From<AstNode<'a>> for Vertex<'a> {
AstKind::NumberLiteral(number_literal) => Self::NumberLiteral(
NumberLiteralVertex { ast_node: Some(ast_node), number_literal }.into(),
),
AstKind::IdentifierName(identifier_name) => {
Self::Name(NameVertex { ast_node: Some(ast_node), name: identifier_name }.into())
}
AstKind::ObjectProperty(property) => {
Self::ObjectEntry(ObjectEntryVertex { ast_node: Some(ast_node), property }.into())
}
AstKind::SpreadElement(property) => Self::SpreadIntoObject(
SpreadIntoObjectVertex { ast_node: Some(ast_node), property }.into(),
),
AstKind::MemberExpression(member_expr)
if matches!(member_expr, MemberExpression::StaticMemberExpression(_)) =>
{
match member_expr {
MemberExpression::StaticMemberExpression(member_expr) => Self::DotProperty(
DotPropertyVertex {
ast_node: Some(ast_node),
static_member_expr: member_expr,
}
.into(),
),
_ => unreachable!("we should only ever have StaticMemberExpression"),
}
}
_ => Vertex::ASTNode(ast_node),
}
}
@ -239,6 +287,18 @@ impl<'a> From<&'a Expression<'a>> for Vertex<'a> {
Expression::NumberLiteral(number_literal) => {
Vertex::NumberLiteral(NumberLiteralVertex { ast_node: None, number_literal }.into())
}
Expression::MemberExpression(member_expr)
if matches!(**member_expr, MemberExpression::StaticMemberExpression(_)) =>
{
match &**member_expr {
MemberExpression::StaticMemberExpression(static_member_expr) => {
Vertex::DotProperty(
DotPropertyVertex { ast_node: None, static_member_expr }.into(),
)
}
_ => unreachable!("we should only ever have StaticMemberExpression"),
}
}
_ => Vertex::Expression(expr),
}
}
@ -347,6 +407,13 @@ impl<'a> Typename for JSXElementVertex<'a> {
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct IfStatementVertex<'a> {
ast_node: Option<AstNode<'a>>,
pub return_statement: &'a IfStatement<'a>,
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct ReturnStatementVertex<'a> {
@ -445,3 +512,71 @@ impl<'a> Typename for NumberLiteralVertex<'a> {
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct NameVertex<'a> {
pub ast_node: Option<AstNode<'a>>,
pub name: &'a IdentifierName,
}
impl<'a> Typename for NameVertex<'a> {
fn typename(&self) -> &'static str {
if self.ast_node.is_some() {
"NameAST"
} else {
"Name"
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct ObjectEntryVertex<'a> {
pub ast_node: Option<AstNode<'a>>,
pub property: &'a ObjectProperty<'a>,
}
impl<'a> Typename for ObjectEntryVertex<'a> {
fn typename(&self) -> &'static str {
if self.ast_node.is_some() {
"ObjectEntryAST"
} else {
"ObjectEntry"
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct SpreadIntoObjectVertex<'a> {
pub ast_node: Option<AstNode<'a>>,
pub property: &'a SpreadElement<'a>,
}
impl<'a> Typename for SpreadIntoObjectVertex<'a> {
fn typename(&self) -> &'static str {
if self.ast_node.is_some() {
"SpreadIntoObjectAST"
} else {
"SpreadIntoObject"
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct DotPropertyVertex<'a> {
ast_node: Option<AstNode<'a>>,
pub static_member_expr: &'a StaticMemberExpression<'a>,
}
impl<'a> Typename for DotPropertyVertex<'a> {
fn typename(&self) -> &'static str {
if self.ast_node.is_some() {
"DotPropertyAST"
} else {
"DotProperty"
}
}
}