mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(ast_codegen): add ImplGetSpanGenerator. (#3852)
This one is ready to replace the handwritten module.
This commit is contained in:
parent
f6c4ec44ca
commit
09f4d3c4d3
12 changed files with 2576 additions and 799 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
|
@ -1324,11 +1324,12 @@ name = "oxc_ast_codegen"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.13.0",
|
||||
"lazy_static",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
use std::{cell::Cell, hash::Hash};
|
||||
|
||||
use oxc_allocator::Vec;
|
||||
use oxc_span::{Atom, GetSpan, Span};
|
||||
use oxc_span::{Atom, Span};
|
||||
|
||||
use crate::ast::*;
|
||||
|
||||
|
|
@ -103,15 +103,6 @@ impl<'a> TSTypeName<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl GetSpan for TSTypeName<'_> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
TSTypeName::IdentifierReference(ident) => ident.span,
|
||||
TSTypeName::QualifiedName(name) => name.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TSTypeParameter<'a> {
|
||||
pub fn new(
|
||||
span: Span,
|
||||
|
|
|
|||
2175
crates/oxc_ast/src/generated/span.rs
Normal file
2175
crates/oxc_ast/src/generated/span.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -17,11 +17,14 @@ mod ast_builder;
|
|||
mod ast_impl;
|
||||
mod ast_kind;
|
||||
pub mod precedence;
|
||||
mod span;
|
||||
pub mod syntax_directed_operations;
|
||||
mod trivia;
|
||||
pub mod visit;
|
||||
|
||||
mod generated {
|
||||
pub mod span;
|
||||
}
|
||||
|
||||
pub use num_bigint::BigUint;
|
||||
|
||||
pub use crate::{
|
||||
|
|
|
|||
|
|
@ -1,747 +0,0 @@
|
|||
use oxc_span::{GetSpan, Span};
|
||||
|
||||
use crate::ast::*;
|
||||
|
||||
impl<'a> GetSpan for Statement<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::BlockStatement(stmt) => stmt.span,
|
||||
Self::BreakStatement(stmt) => stmt.span,
|
||||
Self::ContinueStatement(stmt) => stmt.span,
|
||||
Self::DebuggerStatement(stmt) => stmt.span,
|
||||
Self::DoWhileStatement(stmt) => stmt.span,
|
||||
Self::EmptyStatement(stmt) => stmt.span,
|
||||
Self::ExpressionStatement(stmt) => stmt.span,
|
||||
Self::ForInStatement(stmt) => stmt.span,
|
||||
Self::ForOfStatement(stmt) => stmt.span,
|
||||
Self::ForStatement(stmt) => stmt.span,
|
||||
Self::IfStatement(stmt) => stmt.span,
|
||||
Self::LabeledStatement(stmt) => stmt.span,
|
||||
Self::ReturnStatement(stmt) => stmt.span,
|
||||
Self::SwitchStatement(stmt) => stmt.span,
|
||||
Self::ThrowStatement(stmt) => stmt.span,
|
||||
Self::TryStatement(stmt) => stmt.span,
|
||||
Self::WhileStatement(stmt) => stmt.span,
|
||||
Self::WithStatement(stmt) => stmt.span,
|
||||
// `ModuleDeclaration`
|
||||
Self::ImportDeclaration(decl) => decl.span,
|
||||
Self::ExportAllDeclaration(decl) => decl.span,
|
||||
Self::ExportDefaultDeclaration(decl) => decl.span,
|
||||
Self::ExportNamedDeclaration(decl) => decl.span,
|
||||
Self::TSExportAssignment(decl) => decl.span,
|
||||
Self::TSNamespaceExportDeclaration(decl) => decl.span,
|
||||
// `Declaration`
|
||||
Self::VariableDeclaration(decl) => decl.span,
|
||||
Self::FunctionDeclaration(decl) => decl.span,
|
||||
Self::ClassDeclaration(decl) => decl.span,
|
||||
Self::UsingDeclaration(decl) => decl.span,
|
||||
Self::TSTypeAliasDeclaration(decl) => decl.span,
|
||||
Self::TSInterfaceDeclaration(decl) => decl.span,
|
||||
Self::TSEnumDeclaration(decl) => decl.span,
|
||||
Self::TSModuleDeclaration(decl) => decl.span,
|
||||
Self::TSImportEqualsDeclaration(decl) => decl.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for Expression<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::BooleanLiteral(e) => e.span,
|
||||
Self::NullLiteral(e) => e.span,
|
||||
Self::NumericLiteral(e) => e.span,
|
||||
Self::BigintLiteral(e) => e.span,
|
||||
Self::RegExpLiteral(e) => e.span,
|
||||
Self::StringLiteral(e) => e.span,
|
||||
Self::TemplateLiteral(e) => e.span,
|
||||
Self::Identifier(e) => e.span,
|
||||
Self::MetaProperty(e) => e.span,
|
||||
Self::Super(e) => e.span,
|
||||
Self::ArrayExpression(e) => e.span,
|
||||
Self::ArrowFunctionExpression(e) => e.span,
|
||||
Self::AssignmentExpression(e) => e.span,
|
||||
Self::AwaitExpression(e) => e.span,
|
||||
Self::BinaryExpression(e) => e.span,
|
||||
Self::PrivateInExpression(e) => e.span,
|
||||
Self::CallExpression(e) => e.span,
|
||||
Self::ChainExpression(e) => e.span,
|
||||
Self::ClassExpression(e) => e.span,
|
||||
Self::ConditionalExpression(e) => e.span,
|
||||
Self::FunctionExpression(e) => e.span,
|
||||
Self::ImportExpression(e) => e.span,
|
||||
Self::LogicalExpression(e) => e.span,
|
||||
Self::NewExpression(e) => e.span,
|
||||
Self::ObjectExpression(e) => e.span,
|
||||
Self::ParenthesizedExpression(e) => e.span,
|
||||
Self::SequenceExpression(e) => e.span,
|
||||
Self::TaggedTemplateExpression(e) => e.span,
|
||||
Self::ThisExpression(e) => e.span,
|
||||
Self::UnaryExpression(e) => e.span,
|
||||
Self::UpdateExpression(e) => e.span,
|
||||
Self::YieldExpression(e) => e.span,
|
||||
Self::JSXElement(e) => e.span,
|
||||
Self::JSXFragment(e) => e.span,
|
||||
Self::TSAsExpression(e) => e.span,
|
||||
Self::TSSatisfiesExpression(e) => e.span,
|
||||
Self::TSTypeAssertion(e) => e.span,
|
||||
Self::TSNonNullExpression(e) => e.span,
|
||||
Self::TSInstantiationExpression(e) => e.span,
|
||||
// `MemberExpression`
|
||||
Self::ComputedMemberExpression(e) => e.span,
|
||||
Self::StaticMemberExpression(e) => e.span,
|
||||
Self::PrivateFieldExpression(e) => e.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for BindingPatternKind<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::BindingIdentifier(ident) => ident.span,
|
||||
Self::ObjectPattern(pat) => pat.span,
|
||||
Self::ArrayPattern(pat) => pat.span,
|
||||
Self::AssignmentPattern(pat) => pat.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for BindingPattern<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match &self.kind {
|
||||
BindingPatternKind::BindingIdentifier(ident) => ident.span,
|
||||
BindingPatternKind::ObjectPattern(pat) => pat.span,
|
||||
BindingPatternKind::ArrayPattern(pat) => pat.span,
|
||||
BindingPatternKind::AssignmentPattern(pat) => pat.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetSpan for BindingProperty<'_> {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ClassElement<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::StaticBlock(block) => block.span,
|
||||
Self::MethodDefinition(def) => def.span,
|
||||
Self::PropertyDefinition(def) => def.span,
|
||||
Self::AccessorProperty(def) => def.span,
|
||||
Self::TSIndexSignature(sig) => sig.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for PropertyKey<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::StaticIdentifier(ident) => ident.span,
|
||||
Self::PrivateIdentifier(ident) => ident.span,
|
||||
// `Expression`
|
||||
Self::BooleanLiteral(e) => e.span,
|
||||
Self::NullLiteral(e) => e.span,
|
||||
Self::NumericLiteral(e) => e.span,
|
||||
Self::BigintLiteral(e) => e.span,
|
||||
Self::RegExpLiteral(e) => e.span,
|
||||
Self::StringLiteral(e) => e.span,
|
||||
Self::TemplateLiteral(e) => e.span,
|
||||
Self::Identifier(e) => e.span,
|
||||
Self::MetaProperty(e) => e.span,
|
||||
Self::Super(e) => e.span,
|
||||
Self::ArrayExpression(e) => e.span,
|
||||
Self::ArrowFunctionExpression(e) => e.span,
|
||||
Self::AssignmentExpression(e) => e.span,
|
||||
Self::AwaitExpression(e) => e.span,
|
||||
Self::BinaryExpression(e) => e.span,
|
||||
Self::CallExpression(e) => e.span,
|
||||
Self::ChainExpression(e) => e.span,
|
||||
Self::ClassExpression(e) => e.span,
|
||||
Self::ConditionalExpression(e) => e.span,
|
||||
Self::FunctionExpression(e) => e.span,
|
||||
Self::ImportExpression(e) => e.span,
|
||||
Self::LogicalExpression(e) => e.span,
|
||||
Self::NewExpression(e) => e.span,
|
||||
Self::ObjectExpression(e) => e.span,
|
||||
Self::ParenthesizedExpression(e) => e.span,
|
||||
Self::SequenceExpression(e) => e.span,
|
||||
Self::TaggedTemplateExpression(e) => e.span,
|
||||
Self::ThisExpression(e) => e.span,
|
||||
Self::UnaryExpression(e) => e.span,
|
||||
Self::UpdateExpression(e) => e.span,
|
||||
Self::YieldExpression(e) => e.span,
|
||||
Self::PrivateInExpression(e) => e.span,
|
||||
Self::JSXElement(e) => e.span,
|
||||
Self::JSXFragment(e) => e.span,
|
||||
Self::TSAsExpression(e) => e.span,
|
||||
Self::TSSatisfiesExpression(e) => e.span,
|
||||
Self::TSTypeAssertion(e) => e.span,
|
||||
Self::TSNonNullExpression(e) => e.span,
|
||||
Self::TSInstantiationExpression(e) => e.span,
|
||||
Self::ComputedMemberExpression(e) => e.span,
|
||||
Self::StaticMemberExpression(e) => e.span,
|
||||
Self::PrivateFieldExpression(e) => e.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for MemberExpression<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::ComputedMemberExpression(expr) => expr.span,
|
||||
Self::StaticMemberExpression(expr) => expr.span,
|
||||
Self::PrivateFieldExpression(expr) => expr.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ImportAttributeKey<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::Identifier(identifier) => identifier.span,
|
||||
Self::StringLiteral(literal) => literal.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ModuleExportName<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::IdentifierName(identifier) => identifier.span,
|
||||
Self::IdentifierReference(identifier) => identifier.span,
|
||||
Self::StringLiteral(literal) => literal.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ModuleDeclaration<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::ImportDeclaration(decl) => decl.span,
|
||||
Self::ExportAllDeclaration(decl) => decl.span,
|
||||
Self::ExportDefaultDeclaration(decl) => decl.span,
|
||||
Self::ExportNamedDeclaration(decl) => decl.span,
|
||||
Self::TSExportAssignment(decl) => decl.span,
|
||||
Self::TSNamespaceExportDeclaration(decl) => decl.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for Declaration<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::VariableDeclaration(decl) => decl.span,
|
||||
Self::FunctionDeclaration(decl) => decl.span,
|
||||
Self::UsingDeclaration(decl) => decl.span,
|
||||
Self::ClassDeclaration(decl) => decl.span,
|
||||
Self::TSTypeAliasDeclaration(decl) => decl.span,
|
||||
Self::TSInterfaceDeclaration(decl) => decl.span,
|
||||
Self::TSEnumDeclaration(decl) => decl.span,
|
||||
Self::TSModuleDeclaration(decl) => decl.span,
|
||||
Self::TSImportEqualsDeclaration(decl) => decl.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for TSModuleDeclarationName<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::Identifier(ident) => ident.span,
|
||||
Self::StringLiteral(lit) => lit.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ObjectPropertyKind<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::ObjectProperty(p) => p.span,
|
||||
Self::SpreadProperty(p) => p.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for AssignmentTarget<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
// `SimpleAssignmentTarget`
|
||||
Self::AssignmentTargetIdentifier(ident) => ident.span,
|
||||
Self::TSAsExpression(expr) => expr.span,
|
||||
Self::TSSatisfiesExpression(expr) => expr.span,
|
||||
Self::TSNonNullExpression(expr) => expr.span,
|
||||
Self::TSTypeAssertion(expr) => expr.span,
|
||||
Self::TSInstantiationExpression(expr) => expr.span,
|
||||
// `AssignmentTargetPattern`
|
||||
Self::ComputedMemberExpression(expr) => expr.span,
|
||||
Self::StaticMemberExpression(expr) => expr.span,
|
||||
Self::PrivateFieldExpression(expr) => expr.span,
|
||||
Self::ArrayAssignmentTarget(pat) => pat.span,
|
||||
Self::ObjectAssignmentTarget(pat) => pat.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for AssignmentTargetProperty<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::AssignmentTargetPropertyIdentifier(identifier) => identifier.span,
|
||||
Self::AssignmentTargetPropertyProperty(literal) => literal.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for Argument<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::SpreadElement(e) => e.span,
|
||||
// `Expression`
|
||||
Self::BooleanLiteral(e) => e.span,
|
||||
Self::NullLiteral(e) => e.span,
|
||||
Self::NumericLiteral(e) => e.span,
|
||||
Self::BigintLiteral(e) => e.span,
|
||||
Self::RegExpLiteral(e) => e.span,
|
||||
Self::StringLiteral(e) => e.span,
|
||||
Self::TemplateLiteral(e) => e.span,
|
||||
Self::Identifier(e) => e.span,
|
||||
Self::MetaProperty(e) => e.span,
|
||||
Self::Super(e) => e.span,
|
||||
Self::ArrayExpression(e) => e.span,
|
||||
Self::ArrowFunctionExpression(e) => e.span,
|
||||
Self::AssignmentExpression(e) => e.span,
|
||||
Self::AwaitExpression(e) => e.span,
|
||||
Self::BinaryExpression(e) => e.span,
|
||||
Self::CallExpression(e) => e.span,
|
||||
Self::ChainExpression(e) => e.span,
|
||||
Self::ClassExpression(e) => e.span,
|
||||
Self::ConditionalExpression(e) => e.span,
|
||||
Self::FunctionExpression(e) => e.span,
|
||||
Self::ImportExpression(e) => e.span,
|
||||
Self::LogicalExpression(e) => e.span,
|
||||
Self::NewExpression(e) => e.span,
|
||||
Self::ObjectExpression(e) => e.span,
|
||||
Self::ParenthesizedExpression(e) => e.span,
|
||||
Self::SequenceExpression(e) => e.span,
|
||||
Self::TaggedTemplateExpression(e) => e.span,
|
||||
Self::ThisExpression(e) => e.span,
|
||||
Self::UnaryExpression(e) => e.span,
|
||||
Self::UpdateExpression(e) => e.span,
|
||||
Self::YieldExpression(e) => e.span,
|
||||
Self::PrivateInExpression(e) => e.span,
|
||||
Self::JSXElement(e) => e.span,
|
||||
Self::JSXFragment(e) => e.span,
|
||||
Self::TSAsExpression(e) => e.span,
|
||||
Self::TSSatisfiesExpression(e) => e.span,
|
||||
Self::TSTypeAssertion(e) => e.span,
|
||||
Self::TSNonNullExpression(e) => e.span,
|
||||
Self::TSInstantiationExpression(e) => e.span,
|
||||
Self::ComputedMemberExpression(e) => e.span,
|
||||
Self::StaticMemberExpression(e) => e.span,
|
||||
Self::PrivateFieldExpression(e) => e.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ArrayExpression<'a> {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ArrayExpressionElement<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::SpreadElement(e) => e.span,
|
||||
// `Expression`
|
||||
Self::BooleanLiteral(e) => e.span,
|
||||
Self::NullLiteral(e) => e.span,
|
||||
Self::NumericLiteral(e) => e.span,
|
||||
Self::BigintLiteral(e) => e.span,
|
||||
Self::RegExpLiteral(e) => e.span,
|
||||
Self::StringLiteral(e) => e.span,
|
||||
Self::TemplateLiteral(e) => e.span,
|
||||
Self::Identifier(e) => e.span,
|
||||
Self::MetaProperty(e) => e.span,
|
||||
Self::Super(e) => e.span,
|
||||
Self::ArrayExpression(e) => e.span,
|
||||
Self::ArrowFunctionExpression(e) => e.span,
|
||||
Self::AssignmentExpression(e) => e.span,
|
||||
Self::AwaitExpression(e) => e.span,
|
||||
Self::BinaryExpression(e) => e.span,
|
||||
Self::CallExpression(e) => e.span,
|
||||
Self::ChainExpression(e) => e.span,
|
||||
Self::ClassExpression(e) => e.span,
|
||||
Self::ConditionalExpression(e) => e.span,
|
||||
Self::FunctionExpression(e) => e.span,
|
||||
Self::ImportExpression(e) => e.span,
|
||||
Self::LogicalExpression(e) => e.span,
|
||||
Self::NewExpression(e) => e.span,
|
||||
Self::ObjectExpression(e) => e.span,
|
||||
Self::ParenthesizedExpression(e) => e.span,
|
||||
Self::SequenceExpression(e) => e.span,
|
||||
Self::TaggedTemplateExpression(e) => e.span,
|
||||
Self::ThisExpression(e) => e.span,
|
||||
Self::UnaryExpression(e) => e.span,
|
||||
Self::UpdateExpression(e) => e.span,
|
||||
Self::YieldExpression(e) => e.span,
|
||||
Self::PrivateInExpression(e) => e.span,
|
||||
Self::JSXElement(e) => e.span,
|
||||
Self::JSXFragment(e) => e.span,
|
||||
Self::TSAsExpression(e) => e.span,
|
||||
Self::TSSatisfiesExpression(e) => e.span,
|
||||
Self::TSTypeAssertion(e) => e.span,
|
||||
Self::TSNonNullExpression(e) => e.span,
|
||||
Self::TSInstantiationExpression(e) => e.span,
|
||||
Self::ComputedMemberExpression(e) => e.span,
|
||||
Self::StaticMemberExpression(e) => e.span,
|
||||
Self::PrivateFieldExpression(e) => e.span,
|
||||
|
||||
Self::Elision(elision) => elision.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ForStatementInit<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::VariableDeclaration(x) => x.span,
|
||||
Self::UsingDeclaration(x) => x.span,
|
||||
// `Expression`
|
||||
Self::BooleanLiteral(e) => e.span,
|
||||
Self::NullLiteral(e) => e.span,
|
||||
Self::NumericLiteral(e) => e.span,
|
||||
Self::BigintLiteral(e) => e.span,
|
||||
Self::RegExpLiteral(e) => e.span,
|
||||
Self::StringLiteral(e) => e.span,
|
||||
Self::TemplateLiteral(e) => e.span,
|
||||
Self::Identifier(e) => e.span,
|
||||
Self::MetaProperty(e) => e.span,
|
||||
Self::Super(e) => e.span,
|
||||
Self::ArrayExpression(e) => e.span,
|
||||
Self::ArrowFunctionExpression(e) => e.span,
|
||||
Self::AssignmentExpression(e) => e.span,
|
||||
Self::AwaitExpression(e) => e.span,
|
||||
Self::BinaryExpression(e) => e.span,
|
||||
Self::CallExpression(e) => e.span,
|
||||
Self::ChainExpression(e) => e.span,
|
||||
Self::ClassExpression(e) => e.span,
|
||||
Self::ConditionalExpression(e) => e.span,
|
||||
Self::FunctionExpression(e) => e.span,
|
||||
Self::ImportExpression(e) => e.span,
|
||||
Self::LogicalExpression(e) => e.span,
|
||||
Self::NewExpression(e) => e.span,
|
||||
Self::ObjectExpression(e) => e.span,
|
||||
Self::ParenthesizedExpression(e) => e.span,
|
||||
Self::SequenceExpression(e) => e.span,
|
||||
Self::TaggedTemplateExpression(e) => e.span,
|
||||
Self::ThisExpression(e) => e.span,
|
||||
Self::UnaryExpression(e) => e.span,
|
||||
Self::UpdateExpression(e) => e.span,
|
||||
Self::YieldExpression(e) => e.span,
|
||||
Self::PrivateInExpression(e) => e.span,
|
||||
Self::JSXElement(e) => e.span,
|
||||
Self::JSXFragment(e) => e.span,
|
||||
Self::TSAsExpression(e) => e.span,
|
||||
Self::TSSatisfiesExpression(e) => e.span,
|
||||
Self::TSTypeAssertion(e) => e.span,
|
||||
Self::TSNonNullExpression(e) => e.span,
|
||||
Self::TSInstantiationExpression(e) => e.span,
|
||||
Self::ComputedMemberExpression(e) => e.span,
|
||||
Self::StaticMemberExpression(e) => e.span,
|
||||
Self::PrivateFieldExpression(e) => e.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ForStatementLeft<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::VariableDeclaration(x) => x.span,
|
||||
// `AssignmentTarget`
|
||||
Self::AssignmentTargetIdentifier(x) => x.span,
|
||||
Self::ComputedMemberExpression(x) => x.span,
|
||||
Self::StaticMemberExpression(x) => x.span,
|
||||
Self::PrivateFieldExpression(x) => x.span,
|
||||
Self::TSAsExpression(x) => x.span,
|
||||
Self::TSSatisfiesExpression(x) => x.span,
|
||||
Self::TSNonNullExpression(x) => x.span,
|
||||
Self::TSTypeAssertion(x) => x.span,
|
||||
Self::TSInstantiationExpression(x) => x.span,
|
||||
Self::ArrayAssignmentTarget(x) => x.span,
|
||||
Self::ObjectAssignmentTarget(x) => x.span,
|
||||
Self::UsingDeclaration(x) => x.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for SimpleAssignmentTarget<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::AssignmentTargetIdentifier(ident) => ident.span,
|
||||
Self::TSAsExpression(expr) => expr.span,
|
||||
Self::TSSatisfiesExpression(expr) => expr.span,
|
||||
Self::TSNonNullExpression(expr) => expr.span,
|
||||
Self::TSTypeAssertion(expr) => expr.span,
|
||||
Self::TSInstantiationExpression(expr) => expr.span,
|
||||
// `MemberExpression`
|
||||
Self::ComputedMemberExpression(expr) => expr.span,
|
||||
Self::StaticMemberExpression(expr) => expr.span,
|
||||
Self::PrivateFieldExpression(expr) => expr.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for JSXElementName<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::Identifier(ident) => ident.span,
|
||||
Self::NamespacedName(name) => name.span,
|
||||
Self::MemberExpression(expr) => expr.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for JSXElement<'a> {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for TSSignature<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::TSIndexSignature(sig) => sig.span,
|
||||
Self::TSPropertySignature(sig) => sig.span,
|
||||
Self::TSCallSignatureDeclaration(decl) => decl.span,
|
||||
Self::TSConstructSignatureDeclaration(decl) => decl.span,
|
||||
Self::TSMethodSignature(sig) => sig.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for TSType<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::TSConditionalType(t) => t.span,
|
||||
Self::TSFunctionType(t) => t.span,
|
||||
Self::TSLiteralType(t) => t.span,
|
||||
Self::TSTypeReference(t) => t.span,
|
||||
Self::TSTypeQuery(t) => t.span,
|
||||
Self::TSUnionType(t) => t.span,
|
||||
Self::TSTupleType(t) => t.span,
|
||||
Self::TSArrayType(t) => t.span,
|
||||
Self::TSIntersectionType(t) => t.span,
|
||||
Self::TSMappedType(t) => t.span,
|
||||
Self::TSNamedTupleMember(t) => t.span,
|
||||
Self::TSInferType(t) => t.span,
|
||||
Self::TSConstructorType(t) => t.span,
|
||||
Self::TSIndexedAccessType(t) => t.span,
|
||||
Self::TSTypeOperatorType(t) => t.span,
|
||||
Self::TSImportType(t) => t.span,
|
||||
Self::TSQualifiedName(t) => t.span,
|
||||
Self::TSTypePredicate(t) => t.span,
|
||||
Self::TSTypeLiteral(t) => t.span,
|
||||
Self::TSTemplateLiteralType(t) => t.span,
|
||||
Self::TSAnyKeyword(t) => t.span,
|
||||
Self::TSUnknownKeyword(t) => t.span,
|
||||
Self::TSUndefinedKeyword(t) => t.span,
|
||||
Self::TSNullKeyword(t) => t.span,
|
||||
Self::TSNumberKeyword(t) => t.span,
|
||||
Self::TSStringKeyword(t) => t.span,
|
||||
Self::TSNeverKeyword(t) => t.span,
|
||||
Self::TSBooleanKeyword(t) => t.span,
|
||||
Self::TSIntrinsicKeyword(t) => t.span,
|
||||
Self::TSSymbolKeyword(t) => t.span,
|
||||
Self::TSBigIntKeyword(t) => t.span,
|
||||
Self::TSThisType(t) => t.span,
|
||||
Self::TSVoidKeyword(t) => t.span,
|
||||
Self::TSObjectKeyword(t) => t.span,
|
||||
Self::JSDocNullableType(t) => t.span,
|
||||
Self::JSDocUnknownType(t) => t.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ExportDefaultDeclarationKind<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::ClassDeclaration(x) => x.span,
|
||||
Self::FunctionDeclaration(x) => x.span,
|
||||
Self::TSInterfaceDeclaration(x) => x.span,
|
||||
// `Expression`
|
||||
Self::BooleanLiteral(e) => e.span,
|
||||
Self::NullLiteral(e) => e.span,
|
||||
Self::NumericLiteral(e) => e.span,
|
||||
Self::BigintLiteral(e) => e.span,
|
||||
Self::RegExpLiteral(e) => e.span,
|
||||
Self::StringLiteral(e) => e.span,
|
||||
Self::TemplateLiteral(e) => e.span,
|
||||
Self::Identifier(e) => e.span,
|
||||
Self::MetaProperty(e) => e.span,
|
||||
Self::Super(e) => e.span,
|
||||
Self::ArrayExpression(e) => e.span,
|
||||
Self::ArrowFunctionExpression(e) => e.span,
|
||||
Self::AssignmentExpression(e) => e.span,
|
||||
Self::AwaitExpression(e) => e.span,
|
||||
Self::BinaryExpression(e) => e.span,
|
||||
Self::CallExpression(e) => e.span,
|
||||
Self::ChainExpression(e) => e.span,
|
||||
Self::ClassExpression(e) => e.span,
|
||||
Self::ConditionalExpression(e) => e.span,
|
||||
Self::FunctionExpression(e) => e.span,
|
||||
Self::ImportExpression(e) => e.span,
|
||||
Self::LogicalExpression(e) => e.span,
|
||||
Self::NewExpression(e) => e.span,
|
||||
Self::ObjectExpression(e) => e.span,
|
||||
Self::ParenthesizedExpression(e) => e.span,
|
||||
Self::SequenceExpression(e) => e.span,
|
||||
Self::TaggedTemplateExpression(e) => e.span,
|
||||
Self::ThisExpression(e) => e.span,
|
||||
Self::UnaryExpression(e) => e.span,
|
||||
Self::UpdateExpression(e) => e.span,
|
||||
Self::YieldExpression(e) => e.span,
|
||||
Self::PrivateInExpression(e) => e.span,
|
||||
Self::JSXElement(e) => e.span,
|
||||
Self::JSXFragment(e) => e.span,
|
||||
Self::TSAsExpression(e) => e.span,
|
||||
Self::TSSatisfiesExpression(e) => e.span,
|
||||
Self::TSTypeAssertion(e) => e.span,
|
||||
Self::TSNonNullExpression(e) => e.span,
|
||||
Self::TSInstantiationExpression(e) => e.span,
|
||||
Self::ComputedMemberExpression(e) => e.span,
|
||||
Self::StaticMemberExpression(e) => e.span,
|
||||
Self::PrivateFieldExpression(e) => e.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for ImportDeclarationSpecifier<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::ImportSpecifier(specifier) => specifier.span,
|
||||
Self::ImportDefaultSpecifier(specifier) => specifier.span,
|
||||
Self::ImportNamespaceSpecifier(specifier) => specifier.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for JSXChild<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::Element(element) => element.span,
|
||||
Self::ExpressionContainer(container) => container.span,
|
||||
Self::Text(text) => text.span,
|
||||
Self::Fragment(fragment) => fragment.span,
|
||||
Self::Spread(spread) => spread.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for AssignmentTargetPattern<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match &self {
|
||||
Self::ArrayAssignmentTarget(x) => x.span,
|
||||
Self::ObjectAssignmentTarget(x) => x.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for JSXAttributeItem<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match &self {
|
||||
JSXAttributeItem::Attribute(attr) => attr.span,
|
||||
JSXAttributeItem::SpreadAttribute(attr) => attr.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for JSXExpression<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match &self {
|
||||
Self::EmptyExpression(empty_expr) => empty_expr.span,
|
||||
// `Expression`
|
||||
Self::BooleanLiteral(e) => e.span,
|
||||
Self::NullLiteral(e) => e.span,
|
||||
Self::NumericLiteral(e) => e.span,
|
||||
Self::BigintLiteral(e) => e.span,
|
||||
Self::RegExpLiteral(e) => e.span,
|
||||
Self::StringLiteral(e) => e.span,
|
||||
Self::TemplateLiteral(e) => e.span,
|
||||
Self::Identifier(e) => e.span,
|
||||
Self::MetaProperty(e) => e.span,
|
||||
Self::Super(e) => e.span,
|
||||
Self::ArrayExpression(e) => e.span,
|
||||
Self::ArrowFunctionExpression(e) => e.span,
|
||||
Self::AssignmentExpression(e) => e.span,
|
||||
Self::AwaitExpression(e) => e.span,
|
||||
Self::BinaryExpression(e) => e.span,
|
||||
Self::CallExpression(e) => e.span,
|
||||
Self::ChainExpression(e) => e.span,
|
||||
Self::ClassExpression(e) => e.span,
|
||||
Self::ConditionalExpression(e) => e.span,
|
||||
Self::FunctionExpression(e) => e.span,
|
||||
Self::ImportExpression(e) => e.span,
|
||||
Self::LogicalExpression(e) => e.span,
|
||||
Self::NewExpression(e) => e.span,
|
||||
Self::ObjectExpression(e) => e.span,
|
||||
Self::ParenthesizedExpression(e) => e.span,
|
||||
Self::SequenceExpression(e) => e.span,
|
||||
Self::TaggedTemplateExpression(e) => e.span,
|
||||
Self::ThisExpression(e) => e.span,
|
||||
Self::UnaryExpression(e) => e.span,
|
||||
Self::UpdateExpression(e) => e.span,
|
||||
Self::YieldExpression(e) => e.span,
|
||||
Self::PrivateInExpression(e) => e.span,
|
||||
Self::JSXElement(e) => e.span,
|
||||
Self::JSXFragment(e) => e.span,
|
||||
Self::TSAsExpression(e) => e.span,
|
||||
Self::TSSatisfiesExpression(e) => e.span,
|
||||
Self::TSTypeAssertion(e) => e.span,
|
||||
Self::TSNonNullExpression(e) => e.span,
|
||||
Self::TSInstantiationExpression(e) => e.span,
|
||||
Self::ComputedMemberExpression(e) => e.span,
|
||||
Self::StaticMemberExpression(e) => e.span,
|
||||
Self::PrivateFieldExpression(e) => e.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for JSXAttributeName<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match &self {
|
||||
JSXAttributeName::Identifier(ident) => ident.span,
|
||||
JSXAttributeName::NamespacedName(namespaced_name) => namespaced_name.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for JSXAttributeValue<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match &self {
|
||||
JSXAttributeValue::StringLiteral(literal) => literal.span,
|
||||
JSXAttributeValue::ExpressionContainer(container) => container.span,
|
||||
JSXAttributeValue::Fragment(fragment) => fragment.span,
|
||||
JSXAttributeValue::Element(element) => element.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for JSXMemberExpressionObject<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match &self {
|
||||
JSXMemberExpressionObject::Identifier(ident) => ident.span,
|
||||
JSXMemberExpressionObject::MemberExpression(expr) => expr.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GetSpan for TSEnumMemberName<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
TSEnumMemberName::StaticIdentifier(ident) => ident.span,
|
||||
TSEnumMemberName::StaticStringLiteral(literal) => literal.span,
|
||||
TSEnumMemberName::StaticNumericLiteral(literal) => literal.span,
|
||||
expr @ match_expression!(TSEnumMemberName) => expr.to_expression().span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,8 +19,9 @@ quote = { workspace = true }
|
|||
proc-macro2 = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
prettyplease = { workspace = true }
|
||||
lazy_static = { workspace = true }
|
||||
|
||||
[package.metadata.cargo-shear]
|
||||
ignored = ["prettyplease"]
|
||||
|
|
|
|||
108
tasks/ast_codegen/src/generators/impl_get_span.rs
Normal file
108
tasks/ast_codegen/src/generators/impl_get_span.rs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use itertools::Itertools;
|
||||
use lazy_static::lazy_static;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_quote, Attribute, Variant};
|
||||
|
||||
use crate::{
|
||||
schema::{REnum, RStruct, RType},
|
||||
CodegenCtx, Generator, GeneratorOutput,
|
||||
};
|
||||
|
||||
use super::generated_header;
|
||||
|
||||
pub struct ImplGetSpanGenerator;
|
||||
|
||||
const EDGE_CASES: [&str; 1] = ["BindingPattern"];
|
||||
|
||||
fn edge_case(it: &std::cell::Ref<RType>) -> bool {
|
||||
!it.ident().is_some_and(|it| EDGE_CASES.contains(&it.to_string().as_str()))
|
||||
}
|
||||
|
||||
fn edge_case_impls() -> TokenStream {
|
||||
quote! {
|
||||
endl!();
|
||||
impl<'a> GetSpan for BindingPattern<'a> {
|
||||
fn span(&self) -> Span {
|
||||
self.kind.span()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Generator for ImplGetSpanGenerator {
|
||||
fn name(&self) -> &'static str {
|
||||
"ImplGetSpanGenerator"
|
||||
}
|
||||
|
||||
fn generate(&mut self, ctx: &CodegenCtx) -> GeneratorOutput {
|
||||
let impls: Vec<TokenStream> = ctx
|
||||
.ty_table
|
||||
.iter()
|
||||
.map(|it| it.borrow())
|
||||
.filter(|it| it.visitable())
|
||||
.filter(|it| matches!(&**it, RType::Enum(_) | RType::Struct(_)))
|
||||
.filter(edge_case)
|
||||
.map(|kind| match &*kind {
|
||||
RType::Enum(it) => impl_enum(it),
|
||||
RType::Struct(it) => impl_struct(it),
|
||||
_ => unreachable!("already filtered out!"),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let edge_impls = edge_case_impls();
|
||||
|
||||
let header = generated_header!();
|
||||
|
||||
GeneratorOutput::One(quote! {
|
||||
#header
|
||||
insert!("#![allow(clippy::match_same_arms)]");
|
||||
endl!();
|
||||
|
||||
use crate::ast::*;
|
||||
use oxc_span::{GetSpan, Span};
|
||||
|
||||
#(#impls)*
|
||||
|
||||
#edge_impls
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_enum(it @ REnum { item, .. }: &REnum) -> TokenStream {
|
||||
let typ = it.as_type();
|
||||
let generics = &item.generics;
|
||||
let matches: Vec<TokenStream> = item
|
||||
.variants
|
||||
.iter()
|
||||
.map(|Variant { ident, .. }| quote!(Self :: #ident(it) => it.span()))
|
||||
.collect_vec();
|
||||
|
||||
quote! {
|
||||
endl!();
|
||||
impl #generics GetSpan for #typ {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
#(#matches),*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_struct(it @ RStruct { item, .. }: &RStruct) -> TokenStream {
|
||||
let typ = it.as_type();
|
||||
let generics = &item.generics;
|
||||
quote! {
|
||||
endl!();
|
||||
impl #generics GetSpan for #typ {
|
||||
#[inline]
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,43 @@
|
|||
mod ast;
|
||||
mod ast_kind;
|
||||
mod impl_get_span;
|
||||
|
||||
/// Inserts a newline in the `TokenStream`.
|
||||
#[allow(unused)]
|
||||
macro_rules! endl {
|
||||
() => {
|
||||
/* only works in the context of `quote` macro family! */
|
||||
};
|
||||
}
|
||||
|
||||
/// Similar to how `insert` macro works in the context of `quote` macro family, But this one can be
|
||||
/// used outside and accepts expressions.
|
||||
/// Wraps the result of the given expression in `insert!({value here});` and outputs it as `TokenStream`.
|
||||
macro_rules! insert {
|
||||
($txt:expr) => {{
|
||||
format!(r#"insert!("{}");"#, $txt.as_str()).parse::<proc_macro2::TokenStream>().unwrap()
|
||||
}};
|
||||
}
|
||||
|
||||
/// Creates a generated file warning + required information for a generated file.
|
||||
macro_rules! generated_header {
|
||||
() => {{
|
||||
let file = file!().replace("\\", "/");
|
||||
let edit_comment = $crate::generators::insert!(format!(
|
||||
"// To edit this generated file you have to edit `{file}`"
|
||||
));
|
||||
// TODO add generation date, AST source hash, etc here.
|
||||
quote! {
|
||||
insert!("// Auto-generated code, DO NOT EDIT DIRECTLY!");
|
||||
#edit_comment
|
||||
endl!();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
pub(crate) use generated_header;
|
||||
pub(crate) use insert;
|
||||
|
||||
pub use ast::AstGenerator;
|
||||
pub use ast_kind::AstKindGenerator;
|
||||
pub use impl_get_span::ImplGetSpanGenerator;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,38 @@ pub trait Linker<'a> {
|
|||
fn link(&'a self, linker: impl FnMut(&mut RType, &'a Self) -> Result<bool>) -> Result<&'a ()>;
|
||||
}
|
||||
|
||||
pub trait Unresolved {
|
||||
fn unresolved(&self) -> bool;
|
||||
fn resolved(&self) -> bool {
|
||||
!self.unresolved()
|
||||
}
|
||||
}
|
||||
|
||||
impl Unresolved for Inherit {
|
||||
fn unresolved(&self) -> bool {
|
||||
matches!(self, Self::Unlinked(_))
|
||||
}
|
||||
}
|
||||
|
||||
impl Unresolved for Vec<Inherit> {
|
||||
fn unresolved(&self) -> bool {
|
||||
self.iter().any(Unresolved::unresolved)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Linker<'a> for CodegenCtx {
|
||||
fn link(
|
||||
&'a self,
|
||||
mut linker: impl FnMut(&mut RType, &'a Self) -> Result<bool>,
|
||||
) -> Result<&'a ()> {
|
||||
let mut unresolved = self.ident_table.keys().collect::<VecDeque<_>>();
|
||||
// we sort by `TypeId` so we always have the same ordering as how it is written in the rust.
|
||||
let mut unresolved = self
|
||||
.ident_table
|
||||
.iter()
|
||||
.sorted_by_key(|it| it.1)
|
||||
.map(|it| it.0)
|
||||
.collect::<VecDeque<_>>();
|
||||
|
||||
while let Some(next) = unresolved.pop_back() {
|
||||
let next_id = *self.type_id(next).unwrap();
|
||||
|
||||
|
|
@ -27,8 +53,7 @@ impl<'a> Linker<'a> for CodegenCtx {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns false if can't resolve
|
||||
/// TODO: right now we don't resolve nested inherits, return is always true for now.
|
||||
/// Returns false if can't resolve at the moment
|
||||
/// # Panics
|
||||
/// On invalid inheritance.
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
|
|
@ -43,25 +68,33 @@ pub fn linker(ty: &mut RType, ctx: &CodegenCtx) -> Result<bool> {
|
|||
return Ok(true);
|
||||
}
|
||||
|
||||
ty.meta.inherits = ty
|
||||
let inherits = ty
|
||||
.meta
|
||||
.inherits
|
||||
.drain(..)
|
||||
.map(|it| match it {
|
||||
Inherit::Unlinked(it) => {
|
||||
let linkee = ctx.find(&Cow::Owned(it.to_string())).unwrap();
|
||||
Inherit::Unlinked(ref sup) => {
|
||||
let linkee = ctx.find(&Cow::Owned(sup.to_string())).unwrap();
|
||||
let variants = match &*linkee.borrow() {
|
||||
RType::Enum(enum_) => enum_.item.variants.clone(),
|
||||
RType::Enum(enum_) => {
|
||||
if enum_.meta.inherits.unresolved() {
|
||||
return Err(it);
|
||||
}
|
||||
enum_.item.variants.clone()
|
||||
}
|
||||
_ => {
|
||||
panic!("invalid inheritance, you can only inherit from enums and in enums.")
|
||||
}
|
||||
};
|
||||
ty.item.variants.extend(variants.clone());
|
||||
Inherit::Linked { super_: it.clone(), variants }
|
||||
Ok(Inherit::Linked { super_: sup.clone(), variants })
|
||||
}
|
||||
Inherit::Linked { .. } => it,
|
||||
Inherit::Linked { .. } => Ok(it),
|
||||
})
|
||||
.collect_vec();
|
||||
.collect::<Vec<std::result::Result<Inherit, Inherit>>>();
|
||||
let unresolved = inherits.iter().any(std::result::Result::is_err);
|
||||
|
||||
Ok(true)
|
||||
ty.meta.inherits = inherits.into_iter().map(|it| it.unwrap_or_else(|it| it)).collect();
|
||||
|
||||
Ok(!unresolved)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,23 @@
|
|||
// TODO: remove me please!
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, unused_imports)]
|
||||
mod defs;
|
||||
mod generators;
|
||||
mod linker;
|
||||
mod pprint;
|
||||
mod schema;
|
||||
|
||||
use std::{borrow::Cow, cell::RefCell, collections::HashMap, io::Read, path::PathBuf, rc::Rc};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
fs,
|
||||
io::{Read, Write},
|
||||
path::PathBuf,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use itertools::Itertools;
|
||||
use pprint::pprint;
|
||||
use proc_macro2::TokenStream;
|
||||
use syn::parse_file;
|
||||
|
||||
|
|
@ -16,6 +26,8 @@ use generators::{AstGenerator, AstKindGenerator};
|
|||
use linker::{linker, Linker};
|
||||
use schema::{Inherit, Module, REnum, RStruct, RType, Schema};
|
||||
|
||||
use crate::generators::ImplGetSpanGenerator;
|
||||
|
||||
type Result<R> = std::result::Result<R, String>;
|
||||
type TypeId = usize;
|
||||
type TypeName = String;
|
||||
|
|
@ -34,11 +46,42 @@ trait Generator {
|
|||
fn generate(&mut self, ctx: &CodegenCtx) -> GeneratorOutput;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
enum GeneratorOutput {
|
||||
None,
|
||||
One(TokenStream),
|
||||
Many(HashMap<String, TokenStream>),
|
||||
Info(String),
|
||||
}
|
||||
|
||||
impl GeneratorOutput {
|
||||
pub fn as_none(&self) {
|
||||
assert!(matches!(self, Self::None));
|
||||
}
|
||||
|
||||
pub fn as_one(&self) -> &TokenStream {
|
||||
if let Self::One(it) = self {
|
||||
it
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_many(&self) -> &HashMap<String, TokenStream> {
|
||||
if let Self::Many(it) = self {
|
||||
it
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_info(&self) -> &String {
|
||||
if let Self::Info(it) = self {
|
||||
it
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CodegenCtx {
|
||||
|
|
@ -73,7 +116,7 @@ impl CodegenCtx {
|
|||
}
|
||||
|
||||
fn find(&self, key: &TypeName) -> Option<TypeRef> {
|
||||
self.ident_table.get(key).map(|id| TypeRef::clone(&self.ty_table[*id]))
|
||||
self.type_id(key).map(|id| TypeRef::clone(&self.ty_table[*id]))
|
||||
}
|
||||
|
||||
fn type_id<'b>(&'b self, key: &'b TypeName) -> Option<&'b TypeId> {
|
||||
|
|
@ -107,6 +150,8 @@ impl AstCodegen {
|
|||
.map(Module::from)
|
||||
.map(Module::load)
|
||||
.map_ok(Module::expand)
|
||||
.flatten()
|
||||
.map_ok(Module::analyze)
|
||||
.collect::<Result<Result<Vec<_>>>>()??;
|
||||
|
||||
let ctx = CodegenCtx::new(modules);
|
||||
|
|
@ -123,22 +168,43 @@ impl AstCodegen {
|
|||
}
|
||||
}
|
||||
|
||||
fn files() -> std::array::IntoIter<String, 4> {
|
||||
const AST_ROOT_DIR: &str = "crates/oxc_ast";
|
||||
|
||||
fn files() -> impl std::iter::Iterator<Item = String> {
|
||||
fn path(path: &str) -> String {
|
||||
format!("crates/oxc_ast/src/ast/{path}.rs")
|
||||
format!("{AST_ROOT_DIR}/src/ast/{path}.rs")
|
||||
}
|
||||
|
||||
[path("literal"), path("js"), path("ts"), path("jsx")].into_iter()
|
||||
vec![path("literal"), path("js"), path("ts"), path("jsx")].into_iter()
|
||||
}
|
||||
|
||||
fn output_dir() -> Result<String> {
|
||||
let dir = format!("{AST_ROOT_DIR}/src/generated");
|
||||
fs::create_dir_all(&dir).map_err(|e| e.to_string())?;
|
||||
Ok(dir)
|
||||
}
|
||||
|
||||
#[allow(clippy::print_stdout)]
|
||||
fn main() -> Result<()> {
|
||||
let CodegenResult { schema, .. } = files()
|
||||
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||
let CodegenResult { outputs, .. } = files()
|
||||
.fold(AstCodegen::default(), AstCodegen::add_file)
|
||||
.with(AstGenerator)
|
||||
.with(AstKindGenerator)
|
||||
.with(ImplGetSpanGenerator)
|
||||
.generate()?;
|
||||
|
||||
let output_dir = output_dir()?;
|
||||
let outputs: HashMap<_, _> = outputs.into_iter().collect();
|
||||
|
||||
{
|
||||
let span_path = format!("{output_dir}/span.rs");
|
||||
let mut span_file = fs::File::create(span_path)?;
|
||||
let output = outputs[ImplGetSpanGenerator.name()].as_one();
|
||||
let span_content = pprint(output);
|
||||
|
||||
span_file.write_all(span_content.as_bytes())?;
|
||||
}
|
||||
|
||||
// NOTE: Print AstKind
|
||||
// println!(
|
||||
// "{}",
|
||||
|
|
@ -175,7 +241,7 @@ fn main() -> Result<()> {
|
|||
// .unwrap()
|
||||
// );
|
||||
|
||||
let schema = serde_json::to_string_pretty(&schema).map_err(|e| e.to_string())?;
|
||||
println!("{schema}");
|
||||
// let schema = serde_json::to_string_pretty(&schema).map_err(|e| e.to_string())?;
|
||||
// println!("{schema}");
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
48
tasks/ast_codegen/src/pprint.rs
Normal file
48
tasks/ast_codegen/src/pprint.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
use lazy_static::lazy_static;
|
||||
use proc_macro2::TokenStream;
|
||||
use regex::{Captures, Regex, Replacer};
|
||||
use syn::parse_file;
|
||||
|
||||
static INSERT_MACRO_IDENT: &str = "insert";
|
||||
static INSERT_MACRO_IDENT_LEN: usize = INSERT_MACRO_IDENT.len();
|
||||
|
||||
static ENDL_MACRO_IDENT: &str = "endl";
|
||||
static ENDL_MACRO_IDENT_LEN: usize = ENDL_MACRO_IDENT.len();
|
||||
|
||||
struct InsertReplacer;
|
||||
|
||||
impl Replacer for InsertReplacer {
|
||||
fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
|
||||
assert_eq!(caps.len(), 2);
|
||||
let arg = caps.get(1);
|
||||
if let Some(arg) = arg {
|
||||
dst.push_str(arg.as_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EndlReplacer;
|
||||
|
||||
impl Replacer for EndlReplacer {
|
||||
fn replace_append(&mut self, _: &Captures, _: &mut String) {}
|
||||
}
|
||||
|
||||
pub fn pprint(input: &TokenStream) -> String {
|
||||
lazy_static! {
|
||||
static ref INSERT_REGEX: Regex = Regex::new(
|
||||
format!(r#"(?m)^{INSERT_MACRO_IDENT}!\([\n\s\S]*?\"([\s\S]*?)\"[\n\s\S]*?\);$"#)
|
||||
.as_str()
|
||||
)
|
||||
.unwrap();
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
static ref ENDL_REGEX: Regex =
|
||||
Regex::new(format!(r"{ENDL_MACRO_IDENT}!\(\);").as_str()).unwrap();
|
||||
};
|
||||
|
||||
let result = prettyplease::unparse(&parse_file(input.to_string().as_str()).unwrap());
|
||||
let result = ENDL_REGEX.replace_all(&result, EndlReplacer);
|
||||
let result = INSERT_REGEX.replace_all(&result, InsertReplacer).to_string();
|
||||
result
|
||||
}
|
||||
|
|
@ -39,6 +39,7 @@ impl From<Ident> for Inherit {
|
|||
#[derive(Debug, Default, Clone)]
|
||||
pub struct EnumMeta {
|
||||
pub inherits: Vec<Inherit>,
|
||||
pub visitable: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -55,6 +56,12 @@ impl REnum {
|
|||
pub fn ident(&self) -> &Ident {
|
||||
&self.item.ident
|
||||
}
|
||||
|
||||
pub fn as_type(&self) -> Type {
|
||||
let ident = self.ident();
|
||||
let generics = &self.item.generics;
|
||||
parse_quote!(#ident #generics)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ItemEnum> for REnum {
|
||||
|
|
@ -65,7 +72,9 @@ impl From<ItemEnum> for REnum {
|
|||
|
||||
/// Placeholder for now!
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct StructMeta;
|
||||
pub struct StructMeta {
|
||||
pub visitable: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RStruct {
|
||||
|
|
@ -77,11 +86,17 @@ impl RStruct {
|
|||
pub fn ident(&self) -> &Ident {
|
||||
&self.item.ident
|
||||
}
|
||||
|
||||
pub fn as_type(&self) -> Type {
|
||||
let ident = self.ident();
|
||||
let generics = &self.item.generics;
|
||||
parse_quote!(#ident #generics)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ItemStruct> for RStruct {
|
||||
fn from(item: ItemStruct) -> Self {
|
||||
Self { item, meta: StructMeta }
|
||||
Self { item, meta: StructMeta::default() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,14 +136,29 @@ impl RType {
|
|||
}
|
||||
|
||||
pub fn as_type(&self) -> Option<Type> {
|
||||
if let RType::Enum(REnum { item: ItemEnum { ident, generics, .. }, .. })
|
||||
| RType::Struct(RStruct { item: ItemStruct { ident, generics, .. }, .. }) = self
|
||||
{
|
||||
Some(parse_quote!(#ident #generics))
|
||||
} else {
|
||||
None
|
||||
match self {
|
||||
RType::Enum(it) => Some(it.as_type()),
|
||||
RType::Struct(it) => Some(it.as_type()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visitable(&self) -> bool {
|
||||
match self {
|
||||
RType::Enum(it) => it.meta.visitable,
|
||||
RType::Struct(it) => it.meta.visitable,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_visitable(&mut self, value: bool) -> Result<()> {
|
||||
match self {
|
||||
RType::Enum(it) => it.meta.visitable = value,
|
||||
RType::Struct(it) => it.meta.visitable = value,
|
||||
_ => return Err("Unsupported type!".to_string()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Item> for RType {
|
||||
|
|
@ -183,25 +213,20 @@ impl Module {
|
|||
.items
|
||||
.into_iter()
|
||||
.filter(|it| match it {
|
||||
// Path through these for generators, doesn't get included in the final schema.
|
||||
Item::Use(_) | Item::Const(_) => true,
|
||||
Item::Enum(_) | Item::Struct(_) | Item::Use(_) | Item::Const(_) => true,
|
||||
// These contain enums with inheritance
|
||||
Item::Macro(m) if m.mac.path.is_ident("inherit_variants") => true,
|
||||
// Only include types with `visited_node` since right now we don't have dedicated
|
||||
// definition files.
|
||||
Item::Enum(ItemEnum { attrs, .. }) | Item::Struct(ItemStruct { attrs, .. }) => {
|
||||
attrs.iter().any(|attr| attr.path().is_ident("visited_node"))
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
.map(TryInto::try_into)
|
||||
.map_ok(|it| Rc::new(RefCell::new(it)))
|
||||
// .collect::<Vec<RType>>();
|
||||
.collect::<Result<_>>()?;
|
||||
self.loaded = true;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Expand `inherit_variants` macros to their inner enum.
|
||||
/// This would also populate `inherits` field of `EnumMeta` types.
|
||||
pub fn expand(self) -> Result<Self> {
|
||||
if !self.loaded {
|
||||
return Err(String::from(LOAD_ERROR));
|
||||
|
|
@ -211,12 +236,23 @@ impl Module {
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
/// Fills the Meta types.
|
||||
pub fn analyze(self) -> Result<Self> {
|
||||
if !self.loaded {
|
||||
return Err(String::from(LOAD_ERROR));
|
||||
}
|
||||
|
||||
self.items.iter().try_for_each(analyze)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<Schema> {
|
||||
if !self.loaded {
|
||||
return Err(String::from(LOAD_ERROR));
|
||||
}
|
||||
|
||||
let definitions = Definitions {
|
||||
// We filter map to get rid of stuff we don't need in our schema.
|
||||
types: self.items.into_iter().filter_map(|it| (&*it.borrow()).into()).collect(),
|
||||
};
|
||||
Ok(Schema { source: self.path, definitions })
|
||||
|
|
@ -229,6 +265,11 @@ pub fn expand(type_def: &TypeRef) -> Result<()> {
|
|||
let (enum_, inherits) = mac
|
||||
.mac
|
||||
.parse_body_with(|input: &ParseBuffer| {
|
||||
// Because of `@inherit`s we can't use the actual `ItemEnum` parse,
|
||||
// This closure is similar to how `ItemEnum` parser works, With the exception
|
||||
// of how we approach our variants, First we try to parse a variant out of our
|
||||
// tokens if we fail we try parsing the inheritance, And we would raise an
|
||||
// error only if both of these fail.
|
||||
let attrs = input.call(Attribute::parse_outer)?;
|
||||
let vis = input.parse::<Visibility>()?;
|
||||
let enum_token = input.parse::<Token![enum]>()?;
|
||||
|
|
@ -273,7 +314,10 @@ pub fn expand(type_def: &TypeRef) -> Result<()> {
|
|||
.map_err(|e| e.to_string())?;
|
||||
Some(RType::Enum(REnum::with_meta(
|
||||
enum_,
|
||||
EnumMeta { inherits: inherits.into_iter().map(Into::into).collect() },
|
||||
EnumMeta {
|
||||
inherits: inherits.into_iter().map(Into::into).collect(),
|
||||
..EnumMeta::default()
|
||||
},
|
||||
)))
|
||||
}
|
||||
_ => None,
|
||||
|
|
@ -286,6 +330,22 @@ pub fn expand(type_def: &TypeRef) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn analyze(type_def: &TypeRef) -> Result<()> {
|
||||
let is_visitable = match &*type_def.borrow() {
|
||||
RType::Enum(REnum { item: ItemEnum { attrs, .. }, .. })
|
||||
| RType::Struct(RStruct { item: ItemStruct { attrs, .. }, .. }) => {
|
||||
Some(attrs.iter().any(|attr| attr.path().is_ident("visited_node")))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(is_visitable) = is_visitable {
|
||||
type_def.borrow_mut().set_visitable(is_visitable)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl From<PathBuf> for Module {
|
||||
fn from(path: PathBuf) -> Self {
|
||||
Self::with_path(path)
|
||||
|
|
|
|||
Loading…
Reference in a new issue