feat(query): add FnCall and Argument types (#737)

This commit is contained in:
u9g 2023-08-13 22:25:03 -04:00 committed by GitHub
parent a041fbd96b
commit 99a7ad4319
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 203 additions and 6 deletions

View file

@ -106,6 +106,11 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
property_name.as_ref(),
resolve_info,
),
"FnCallAST" | "FnCall" => super::properties::resolve_fn_call_property(
contexts,
property_name.as_ref(),
resolve_info,
),
"ImportAST" | "Import" => super::properties::resolve_import_property(
contexts,
property_name.as_ref(),
@ -209,6 +214,12 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
resolve_info,
self,
),
"Argument" => super::edges::resolve_argument_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
),
"AssignmentType" => super::edges::resolve_assignment_type_edge(
contexts,
edge_name.as_ref(),
@ -260,6 +271,13 @@ impl<'a, 'b: 'a> trustfall::provider::Adapter<'a> for &'a Adapter<'b> {
resolve_info,
self,
),
"FnCallAST" | "FnCall" => super::edges::resolve_fn_call_edge(
contexts,
edge_name.as_ref(),
parameters,
resolve_info,
self,
),
"HasSpan" => super::edges::resolve_has_span_edge(
contexts,
edge_name.as_ref(),

View file

@ -5,6 +5,35 @@ use trustfall::provider::{
use super::vertex::Vertex;
use crate::Adapter;
pub(super) fn resolve_argument_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" => argument::span(contexts, resolve_info),
_ => {
unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'Argument'")
}
}
}
mod argument {
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_astnode_edge<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
edge_name: &str,
@ -640,6 +669,83 @@ mod file {
}
}
pub(super) fn resolve_fn_call_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_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),
_ => {
unreachable!("attempted to resolve unexpected edge '{edge_name}' on type 'FnCall'")
}
}
}
mod fn_call {
use oxc_ast::ast::Argument;
use oxc_span::GetSpan;
use trustfall::provider::{
resolve_neighbors_with, ContextIterator, ContextOutcomeIterator, ResolveEdgeInfo,
VertexIterator,
};
use super::super::vertex::Vertex;
pub(super) fn callee<'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_fn_call()
.unwrap_or_else(|| {
panic!("expected to have a fncall vertex, instead have: {v:#?}")
})
.call_expression
.callee)
.into(),
))
})
}
pub(super) fn arguments<'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_fn_call()
.unwrap_or_else(|| {
panic!("expected to have a fncall vertex, instead have: {v:#?}")
})
.call_expression
.arguments
.iter()
.map(|x| {
Vertex::Argument(match x {
Argument::SpreadElement(spread) => spread.span,
Argument::Expression(expr) => expr.span(),
})
}),
)
})
}
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_has_span_edge<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
edge_name: &str,

View file

@ -189,6 +189,21 @@ pub(super) fn resolve_expression_property<'a, 'b: 'a>(
}
}
pub(super) fn resolve_fn_call_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 'FnCall'")
}
}
}
pub(super) fn resolve_import_property<'a, 'b: 'a>(
contexts: ContextIterator<'a, Vertex<'b>>,
property_name: &str,

View file

@ -386,6 +386,33 @@ type ObjectLiteralAST implements ObjectLiteral & Expression & HasSpan & ASTNode
span: Span!
}
interface Argument {
span: Span!
}
interface FnCall implements Expression & HasSpan {
callee: Expression!
arguments: [Argument!]!
# Expression
as_constant_string: String
# HasSpan
span: Span!
}
type FnCallAST implements FnCall & Expression & HasSpan & ASTNode {
callee: Expression!
arguments: [Argument!]!
# Expression
as_constant_string: String
# ASTNode
parent: ASTNode
ancestor: [ASTNode!]!
# HasSpan
span: Span!
}
"""
Any assignment that isn't a variable declaration, which means no const/let/var.
ie: "a = 1;", "a /= 1;", "a += 1;", etc.

View file

@ -3,12 +3,12 @@ use std::rc::Rc;
use enum_as_inner::EnumAsInner;
use oxc_ast::{
ast::{
AssignmentExpression, 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,
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,
@ -59,6 +59,8 @@ pub enum Vertex<'a> {
ObjectEntry(Rc<ObjectEntryVertex<'a>>),
DotProperty(Rc<DotPropertyVertex<'a>>),
Reassignment(Rc<ReassignmentVertex<'a>>),
FnCall(Rc<FnCallVertex<'a>>),
Argument(Span),
}
impl<'a> Vertex<'a> {
@ -98,6 +100,8 @@ impl<'a> Vertex<'a> {
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::File
| Self::Url(_)
| Self::PathPart(_)
@ -127,6 +131,7 @@ impl<'a> Vertex<'a> {
Vertex::ObjectEntry(data) => data.ast_node.map(|x| x.id()),
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::DefaultImport(_)
| Vertex::AssignmentType(_)
| Vertex::ClassMethod(_)
@ -145,6 +150,7 @@ impl<'a> Vertex<'a> {
| Vertex::SpecificImport(_)
| Vertex::Span(_)
| Vertex::SearchParameter(_)
| Vertex::Argument(_)
| Vertex::ClassProperty(_) => None,
}
}
@ -225,7 +231,9 @@ impl Typename for Vertex<'_> {
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",
}
}
}
@ -293,6 +301,9 @@ impl<'a> From<AstNode<'a>> for Vertex<'a> {
AstKind::AssignmentExpression(assignment_expression) => Vertex::Reassignment(
ReassignmentVertex { ast_node: Some(ast_node), assignment_expression }.into(),
),
AstKind::CallExpression(call_expression) => {
Vertex::FnCall(FnCallVertex { ast_node: Some(ast_node), call_expression }.into())
}
_ => Vertex::ASTNode(ast_node),
}
}
@ -321,6 +332,9 @@ impl<'a> From<&'a Expression<'a>> for Vertex<'a> {
Expression::AssignmentExpression(assignment_expression) => Vertex::Reassignment(
ReassignmentVertex { ast_node: None, assignment_expression }.into(),
),
Expression::CallExpression(call_expression) => {
Vertex::FnCall(FnCallVertex { ast_node: None, call_expression }.into())
}
_ => Vertex::Expression(expr),
}
}
@ -619,3 +633,20 @@ impl<'a> Typename for ReassignmentVertex<'a> {
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct FnCallVertex<'a> {
ast_node: Option<AstNode<'a>>,
pub call_expression: &'a CallExpression<'a>,
}
impl<'a> Typename for FnCallVertex<'a> {
fn typename(&self) -> &'static str {
if self.ast_node.is_some() {
"FnCallAST"
} else {
"FnCall"
}
}
}