1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 04:52:26 -05:00
This commit is contained in:
Marvin Hagemeister 2024-12-15 19:15:29 +01:00
parent 23ca8dff06
commit 963abe986a
5 changed files with 796 additions and 684 deletions

View file

@ -10,252 +10,9 @@ const {
} = core.ops;
// Keep in sync with Rust
/**
* @enum {number}
*/
const AstTypeName = [
"Invalid",
"Program",
"Import",
"ImportDecl",
"ExportDecl",
"ExportNamed",
"ExportDefaultDecl",
"ExportDefaultExpr",
"ExportAll",
"TSImportEquals",
"TSExportAssignment",
"TSNamespaceExport",
// Decls
"ClassDeclaration",
"FunctionDeclaration",
"VariableDeclaration",
"Using",
"TsInterface",
"TsTypeAlias",
"TsEnum",
"TsModule",
// Statements
"BlockStatement",
"Empty",
"DebuggerStatement",
"WithStatement",
"ReturnStatement",
"LabeledStatement",
"BreakStatement",
"ContinueStatement",
"IfStatement",
"SwitchStatement",
"SwitchCase",
"ThrowStatement",
"TryStatement",
"WhileStatement",
"DoWhileStatement",
"ForStatement",
"ForInStatement",
"ForOfStatement",
"Decl",
"ExpressionStatement",
// Expressions
"This",
"ArrayExpression",
"ObjectExpression",
"FunctionExpression",
"UnaryExpression",
"UpdateExpression",
"BinaryExpression",
"AssignmentExpression",
"MemberExpression",
"Super",
"ConditionalExpression",
"CallExpression",
"NewExpression",
"ParenthesisExpression",
"SequenceExpression",
"Identifier",
"TemplateLiteral",
"TaggedTemplateExpression",
"ArrowFunctionExpression",
"ClassExpr",
"YieldExpression",
"MetaProperty",
"AwaitExpression",
"LogicalExpression",
"TSTypeAssertion",
"TSConstAssertion",
"TSNonNull",
"TSAs",
"TSInstantiation",
"TSSatisfies",
"PrivateIdentifier",
"ChainExpression",
"StringLiteral",
"BooleanLiteral",
"NullLiteral",
"NumericLiteral",
"BigIntLiteral",
"RegExpLiteral",
// Custom
"EmptyExpr",
"SpreadElement",
"Property",
"VariableDeclarator",
"CatchClause",
"RestElement",
"ExportSpecifier",
"TemplateElement",
"MethodDefinition",
// Patterns
"ArrayPattern",
"AssignmentPattern",
"ObjectPattern",
// JSX
"JSXAttribute",
"JSXClosingElement",
"JSXClosingFragment",
"JSXElement",
"JSXEmptyExpression",
"JSXExpressionContainer",
"JSXFragment",
"JSXIdentifier",
"JSXMemberExpression",
"JSXNamespacedName",
"JSXOpeningElement",
"JSXOpeningFragment",
"JSXSpreadAttribute",
"JSXSpreadChild",
"JSXText",
];
/** @type {Map<string, number>} */
const AstType = new Map();
for (let i = 0; i < AstTypeName.length; i++) {
AstType.set(AstTypeName[i], i);
}
// Keep in sync with Rust
const AstPropArr = [
// Base
"parent",
"range",
"type",
"_InternalFlags",
// Node
"abstract",
"accessibility",
"alternate",
"argument",
"arguments",
"async",
"attributes",
"await",
"block",
"body",
"callee",
"cases",
"children",
"checkType",
"closingElement",
"closingFragment",
"computed",
"consequent",
"const",
"constraint",
"cooked",
"declarations",
"declare",
"default",
"definite",
"delegate",
"discriminant",
"elements",
"elementTypes",
"exprName",
"expression",
"expressions",
"exported",
"extendsType",
"falseType",
"finalizer",
"flags",
"generator",
"handler",
"id",
"in",
"init",
"initializer",
"implements",
"key",
"kind",
"label",
"left",
"literal",
"local",
"members",
"meta",
"method",
"name",
"namespace",
"nameType",
"object",
"openingElement",
"openingFragment",
"operator",
"optional",
"out",
"param",
"params",
"pattern",
"prefix",
"properties",
"property",
"quasi",
"quasis",
"raw",
"readonly",
"returnType",
"right",
"selfClosing",
"shorthand",
"source",
"sourceType",
"specifiers",
"superClass",
"superTypeArguments",
"tag",
"tail",
"test",
"trueType",
"typeAnnotation",
"typeArguments",
"typeName",
"typeParameter",
"typeParameters",
"types",
"update",
"value",
];
/** @type {Map<string, number>} */
const AstProp = new Map();
for (let i = 0; i < AstPropArr.length; i++) {
AstProp.set(AstPropArr[i], i);
}
const AST_PROP_TYPE = /** @type {number} */ (AstProp.get("type"));
const AST_PROP_PARENT = /** @type {number} */ (AstProp.get("parent"));
const AST_PROP_RANGE = /** @type {number} */ (AstProp.get("range"));
const AstPropName = Array.from(AstProp.keys());
const AST_PROP_TYPE = 0;
const AST_PROP_PARENT = 1;
const AST_PROP_RANGE = 2;
// Keep in sync with Rust
/** @enum {number} */
@ -274,7 +31,10 @@ const PropFlags = {
* strTable: Map<number, string>,
* strTableOffset: number,
* rootId: number,
* nodes: Map<number, Node>
* nodes: Map<number, Node>,
* strByType: number[],
* typeByStr: Map<string, number>,
* strByProp: number[]
* }} AstContext
*/
@ -421,7 +181,7 @@ function readValue(ctx, offset, search) {
const type = buf[offset];
if (search === AST_PROP_TYPE) {
return AstTypeName[type];
return getString(ctx, ctx.strByType[type]);
} else if (search === AST_PROP_RANGE) {
const start = readU32(buf, offset + 1 + 4);
const end = readU32(buf, offset + 1 + 4 + 4);
@ -484,7 +244,7 @@ function toJsValue(ctx, offset) {
for (let i = 0; i < count; i++) {
const prop = buf[offset++];
const kind = buf[offset++];
const name = AstPropName[prop];
const name = getString(ctx, ctx.strByProp[prop]);
if (kind === PropFlags.Ref) {
const v = readU32(buf, offset);
@ -545,13 +305,28 @@ class Node {
}
}
for (let i = 0; i < AstPropName.length; i++) {
const name = AstPropName[i];
Object.defineProperty(Node.prototype, name, {
get() {
return readValue(this[INTERNAL_CTX], this[INTERNAL_OFFSET], i);
},
});
/** @type {Set<number>} */
const appliedGetters = new Set();
/**
* @param {AstContext} ctx
*/
function setNodeGetters(ctx) {
if (appliedGetters.size === ctx.strByProp.length) return;
for (let i = 0; i < ctx.strByProp.length; i++) {
const id = ctx.strByProp[i];
if (id === 0 || appliedGetters.has(i)) continue;
appliedGetters.add(i);
const name = getString(ctx, id);
Object.defineProperty(Node.prototype, name, {
get() {
return readValue(this[INTERNAL_CTX], this[INTERNAL_OFFSET], i);
},
});
}
}
const DECODER = new TextDecoder();
@ -590,6 +365,8 @@ function createAstContext(buf) {
// console.log(JSON.stringify(buf, null, 2));
const typeMapOffset = readU32(buf, buf.length - 16);
const propMapOffset = readU32(buf, buf.length - 12);
const strTableOffset = readU32(buf, buf.length - 8);
const rootId = readU32(buf, buf.length - 4);
// console.log({ strTableOffset, rootId });
@ -618,10 +395,48 @@ function createAstContext(buf) {
);
}
/** @type {AstContext} */
const ctx = { buf, strTable, rootId, nodes: new Map(), strTableOffset };
offset = typeMapOffset;
const typeCount = readU32(buf, offset);
offset += 4;
// dump(ctx);
const typeByStr = new Map();
const strByType = new Array(typeCount).fill(0);
for (let i = 0; i < typeCount; i++) {
const v = readU32(buf, offset);
offset += 4;
// console.log("type: ", i, v, strTable.get(v));
strByType[i] = v;
typeByStr.set(strTable.get(v), i);
}
offset = propMapOffset;
const propCount = readU32(buf, offset);
offset += 4;
const strByProp = new Array(propCount).fill(0);
for (let i = 0; i < propCount; i++) {
const v = readU32(buf, offset);
offset += 4;
strByProp[i] = v;
}
/** @type {AstContext} */
const ctx = {
buf,
strTable,
rootId,
nodes: new Map(),
strTableOffset,
strByProp,
strByType,
typeByStr,
};
setNodeGetters(ctx);
// _dump(ctx);
return ctx;
}
@ -709,11 +524,11 @@ function traverse(ctx, visitor) {
// TODO: create visiting types
for (const name in visitor) {
const id = AstType.get(name);
const id = ctx.typeByStr.get(name);
if (id === undefined) continue;
visitTypes.set(id, name);
}
// console.log("buffer len", ctx.buf.length, ctx.buf.byteLength);
console.log("merged visitor", visitor);
console.log("visiting types", visitTypes);
@ -779,13 +594,31 @@ function traverseInner(ctx, visitTypes, visitor, offset) {
* @param {AstContext} ctx
*/
function _dump(ctx) {
const { buf, strTableOffset } = ctx;
const { buf, strTableOffset, strTable, strByType, strByProp } = ctx;
// @ts-ignore dump fn
console.log(strTable);
for (let i = 0; i < strByType.length; i++) {
const v = strByType[i];
// @ts-ignore dump fn
if (v > 0) console.log(" > type:", i, getString(ctx, v), v);
}
// @ts-ignore dump fn
console.log();
for (let i = 0; i < strByProp.length; i++) {
const v = strByProp[i];
// @ts-ignore dump fn
if (v > 0) console.log(" > prop:", i, getString(ctx, v), v);
}
// @ts-ignore dump fn
console.log();
let offset = 0;
while (offset < strTableOffset) {
const type = buf[offset];
const name = AstTypeName[type];
const name = getString(ctx, ctx.strByType[type]);
// @ts-ignore dump fn
console.log(`${name}, offset: ${offset}, type: ${type}`);
offset += 1;
@ -800,7 +633,7 @@ function _dump(ctx) {
const end = readU32(buf, offset);
offset += 4;
// @ts-ignore dump fn
console.log(` range: ${start} -> ${end}}`);
console.log(` range: ${start} -> ${end}`);
const count = buf[offset++];
// @ts-ignore dump fn
@ -809,7 +642,7 @@ function _dump(ctx) {
for (let i = 0; i < count; i++) {
const prop = buf[offset++];
const kind = buf[offset++];
const name = AstPropName[prop];
const name = getString(ctx, ctx.strByProp[prop]);
let kindName = "unknown";
for (const k in PropFlags) {
@ -823,35 +656,35 @@ function _dump(ctx) {
const v = readU32(buf, offset);
offset += 4;
// @ts-ignore dump fn
console.log(` ${name}: ${v} (${kindName})`);
console.log(` ${name}: ${v} (${kindName}, ${prop})`);
} else if (kind === PropFlags.RefArr) {
const len = readU32(buf, offset);
offset += 4;
// @ts-ignore dump fn
console.log(` ${name}: Array(${len}) (${kindName})`);
console.log(` ${name}: Array(${len}) (${kindName}, ${prop})`);
for (let j = 0; j < len; j++) {
const v = readU32(buf, offset);
offset += 4;
// @ts-ignore dump fn
console.log(` - ${v}`);
console.log(` - ${v} (${prop})`);
}
} else if (kind === PropFlags.Bool) {
const v = buf[offset];
offset += 1;
// @ts-ignore dump fn
console.log(` ${name}: ${v} (${kindName})`);
console.log(` ${name}: ${v} (${kindName}, ${prop})`);
} else if (kind === PropFlags.String) {
const v = readU32(buf, offset);
offset += 4;
// @ts-ignore dump fn
console.log(` ${name}: ${getString(ctx, v)} (${kindName})`);
console.log(` ${name}: ${getString(ctx, v)} (${kindName}, ${prop})`);
} else if (kind === PropFlags.Null) {
// @ts-ignore dump fn
console.log(` ${name}: null (${kindName})`);
console.log(` ${name}: null (${kindName}, ${prop})`);
} else if (kind === PropFlags.Undefined) {
// @ts-ignore dump fn
console.log(` ${name}: undefined (${kindName})`);
console.log(` ${name}: undefined (${kindName}, ${prop})`);
}
}
}

View file

@ -1,283 +1,8 @@
use std::fmt::Display;
use deno_ast::swc::common::{Span, DUMMY_SP};
use indexmap::IndexMap;
// Keep in sync with JS
#[derive(Debug, PartialEq)]
pub enum AstNode {
Invalid,
//
Program,
// Module declarations
Import,
ImportDecl,
ExportDecl,
ExportNamedDeclaration,
ExportDefaultDecl,
ExportDefaultExpr,
ExportAll,
TsImportEquals,
TsExportAssignment,
TsNamespaceExport,
// Decls
ClassDeclaration,
Fn,
Var,
Using,
TSInterface,
TsTypeAlias,
TSEnumDeclaration,
TsModule,
// Statements
Block,
Empty,
Debugger,
With,
Return,
Labeled,
Break,
Continue,
IfStatement,
Switch,
SwitchCase,
Throw,
TryStatement,
WhileStatement,
DoWhileStatement,
ForStatement,
ForInStatement,
ForOfStatement,
Decl,
ExpressionStatement,
// Expressions
This,
ArrayExpression,
Object,
FunctionExpression,
UnaryExpression,
UpdateExpression,
BinaryExpression,
Assign,
MemberExpression,
Super,
ConditionalExpression,
CallExpression,
New,
Paren,
SequenceExpression,
Identifier,
TemplateLiteral,
TaggedTemplateExpression,
ArrowFunctionExpression,
ClassExpr,
YieldExpression,
MetaProp,
AwaitExpression,
LogicalExpression,
TSTypeAssertion,
TsConstAssertion,
TSNonNullExpression,
TSAsExpression,
TsInstantiation,
TSSatisfiesExpression,
PrivateIdentifier,
ChainExpression,
// Literals
StringLiteral,
Bool,
Null,
NumericLiteral,
BigIntLiteral,
RegExpLiteral,
// Custom
EmptyExpr,
Spread,
Property,
VariableDeclarator,
CatchClause,
RestElement,
ExportSpecifier,
TemplateElement,
MethodDefinition,
// Patterns
ArrayPattern,
AssignmentPattern,
ObjectPattern,
// JSX
JSXAttribute,
JSXClosingElement,
JSXClosingFragment,
JSXElement,
JSXEmptyExpression,
JSXExpressionContainer,
JSXFragment,
JSXIdentifier,
JSXMemberExpression,
JSXNamespacedName,
JSXOpeningElement,
JSXOpeningFragment,
JSXSpreadAttribute,
JSXSpreadChild,
JSXText,
TSTypeAnnotation,
TSTypeParameterDeclaration,
TSTypeParameter,
TSEnumMember,
TSInterfaceBody,
TSInterfaceHeritage,
TSTypeReference,
TSThisType,
TSLiteralType,
TSInferType,
TSConditionalType,
TSUnionType,
TSIntersectionType,
TSMappedType,
TSTypeQuery,
TSTupleType,
TSFunctionType,
TsCallSignatureDeclaration,
TSAnyKeyword,
TSBigIntKeyword,
TSBooleanKeyword,
TSIntrinsicKeyword,
TSNeverKeyword,
TSNullKeyword,
TSNumberKeyword,
TSObjectKeyword,
TSStringKeyword,
TSSymbolKeyword,
TSUndefinedKeyword,
TSUnknownKeyword,
TSVoidKeyword,
TSEnumBody,
}
impl From<AstNode> for u8 {
fn from(m: AstNode) -> u8 {
m as u8
}
}
// Keep in sync with JS
pub enum AstProp {
// Base
Parent,
Range,
Type,
_InternalFlags, // Private
// Node
Abstract,
Accessibility,
Alternate,
Argument,
Arguments,
Async,
Attributes,
Await,
Block,
Body,
Callee,
Cases,
Children,
CheckType,
ClosingElement,
ClosingFragment,
Computed,
Consequent,
Const,
Constraint,
Cooked,
Declarations,
Declare,
Default,
Definite,
Delegate,
Discriminant,
Elements,
ElementTypes,
ExprName,
Expression,
Expressions,
Exported,
ExtendsType,
FalseType,
Finalizer,
Flags,
Generator,
Handler,
Id,
In,
Init,
Initializer,
Implements,
Key,
Kind,
Label,
Left,
Literal,
Local,
Members,
Meta,
Method,
Name,
Namespace,
NameType,
Object,
OpeningElement,
OpeningFragment,
Operator,
Optional,
Out,
Param,
Params,
Pattern,
Prefix,
Properties,
Property,
Quasi,
Quasis,
Raw,
Readonly,
ReturnType,
Right,
SelfClosing,
Shorthand,
Source,
SourceType,
Specifiers,
SuperClass,
SuperTypeArguments,
Tag,
Tail,
Test,
TrueType,
TypeAnnotation,
TypeArguments,
TypeName,
TypeParameter,
TypeParameters,
Types,
Update,
Value,
}
impl From<AstProp> for u8 {
fn from(m: AstProp) -> u8 {
m as u8
}
}
#[derive(Debug, PartialEq)]
pub enum PropFlags {
Ref,
@ -346,26 +71,6 @@ pub fn write_usize(result: &mut [u8], value: usize, idx: usize) {
result[idx + 3] = v4;
}
#[derive(Debug, Clone)]
pub struct FlagValue(pub u8);
impl FlagValue {
pub fn new() -> Self {
Self(0)
}
pub fn set(&mut self, flag: impl Into<u8>) {
let value: u8 = flag.into();
self.0 |= value;
}
}
impl From<FlagValue> for u8 {
fn from(item: FlagValue) -> Self {
item.0
}
}
#[derive(Debug)]
pub struct StringTable {
id: usize,
@ -411,42 +116,118 @@ impl StringTable {
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct NodeRef(pub usize);
pub trait AstBufSerializer<K, P>
where
K: Into<u8> + Display,
P: Into<u8> + Display,
{
fn header(
&mut self,
kind: K,
parent: NodeRef,
span: &Span,
prop_count: usize,
) -> NodeRef;
fn ref_field(&mut self, prop: P) -> usize;
fn ref_vec_field(&mut self, prop: P, len: usize) -> usize;
fn str_field(&mut self, prop: P) -> usize;
fn bool_field(&mut self, prop: P) -> usize;
fn undefined_field(&mut self, prop: P) -> usize;
#[allow(dead_code)]
fn null_field(&mut self, prop: P) -> usize;
fn write_ref(&mut self, pos: usize, value: NodeRef);
fn write_maybe_ref(&mut self, pos: usize, value: Option<NodeRef>);
fn write_refs(&mut self, pos: usize, value: Vec<NodeRef>);
fn write_str(&mut self, pos: usize, value: &str);
fn write_bool(&mut self, pos: usize, value: bool);
fn serialize(&mut self) -> Vec<u8>;
}
#[derive(Debug)]
pub struct SerializeCtx {
pub buf: Vec<u8>,
pub start_buf: NodeRef,
pub str_table: StringTable,
buf: Vec<u8>,
start_buf: NodeRef,
str_table: StringTable,
kind_map: Vec<usize>,
prop_map: Vec<usize>,
}
impl SerializeCtx {
pub fn new() -> Self {
pub fn new(kind_len: u8, prop_len: u8) -> Self {
let kind_size = kind_len as usize;
let prop_size = prop_len as usize;
let mut ctx = Self {
start_buf: NodeRef(0),
buf: vec![],
str_table: StringTable::new(),
kind_map: vec![0; kind_size + 1],
prop_map: vec![0; prop_size + 1],
};
ctx.str_table.insert("");
// Placeholder node
ctx.push_node(AstNode::Invalid, NodeRef(0), &DUMMY_SP);
// Placeholder node is always 0
ctx.append_node(0, NodeRef(0), &DUMMY_SP, 0);
ctx.kind_map[0] = 0;
ctx.start_buf = NodeRef(ctx.buf.len());
// Insert default props that are always present
let type_str = ctx.str_table.insert("type");
let parent_str = ctx.str_table.insert("parent");
let range_str = ctx.str_table.insert("range");
ctx.prop_map[0] = type_str;
ctx.prop_map[1] = parent_str;
ctx.prop_map[2] = range_str;
ctx
}
/// Begin writing a node
pub fn header(
fn field_header<P>(&mut self, prop: P, prop_flags: PropFlags) -> usize
where
P: Into<u8> + Display + Clone,
{
let offset = self.buf.len();
let n: u8 = prop.clone().into();
self.buf.push(n);
if let Some(v) = self.prop_map.get::<usize>(n.into()) {
if *v == 0 {
let id = self.str_table.insert(&format!("{prop}"));
self.prop_map[n as usize] = id;
}
}
let flags: u8 = prop_flags.into();
self.buf.push(flags);
offset
}
fn field<P>(&mut self, prop: P, prop_flags: PropFlags) -> usize
where
P: Into<u8> + Display + Clone,
{
let offset = self.field_header(prop, prop_flags);
append_usize(&mut self.buf, 0);
offset
}
fn append_node(
&mut self,
kind: AstNode,
kind: u8,
parent: NodeRef,
span: &Span,
prop_count: usize,
) -> NodeRef {
let offset = self.buf.len();
let kind_value: u8 = kind.into();
self.buf.push(kind_value);
self.buf.push(kind);
append_usize(&mut self.buf, parent.0);
@ -460,11 +241,42 @@ impl SerializeCtx {
NodeRef(offset)
}
pub fn ref_field(&mut self, prop: AstProp) -> usize {
/// Begin writing a node
pub fn header<N>(
&mut self,
kind: N,
parent: NodeRef,
span: &Span,
prop_count: usize,
) -> NodeRef
where
N: Into<u8> + Display + Clone,
{
let n: u8 = kind.clone().into();
if let Some(v) = self.kind_map.get::<usize>(n.into()) {
if *v == 0 {
let id = self.str_table.insert(&format!("{kind}"));
self.kind_map[n as usize] = id;
}
}
let offset = self.append_node(n, parent, span, prop_count);
offset
}
pub fn ref_field<P>(&mut self, prop: P) -> usize
where
P: Into<u8> + Display + Clone,
{
self.field(prop, PropFlags::Ref)
}
pub fn ref_vec_field(&mut self, prop: AstProp, len: usize) -> usize {
pub fn ref_vec_field<P>(&mut self, prop: P, len: usize) -> usize
where
P: Into<u8> + Display + Clone,
{
let offset = self.field(prop, PropFlags::RefArr);
for _ in 0..len {
@ -474,45 +286,37 @@ impl SerializeCtx {
offset
}
pub fn str_field(&mut self, prop: AstProp) -> usize {
pub fn str_field<P>(&mut self, prop: P) -> usize
where
P: Into<u8> + Display + Clone,
{
self.field(prop, PropFlags::String)
}
fn field_header(&mut self, prop: AstProp, prop_flags: PropFlags) -> usize {
let offset = self.buf.len();
let kind: u8 = prop.into();
self.buf.push(kind);
let flags: u8 = prop_flags.into();
self.buf.push(flags);
offset
}
pub fn bool_field(&mut self, prop: AstProp) -> usize {
pub fn bool_field<P>(&mut self, prop: P) -> usize
where
P: Into<u8> + Display + Clone,
{
let offset = self.field_header(prop, PropFlags::Bool);
self.buf.push(0);
offset
}
pub fn undefined_field(&mut self, prop: AstProp) -> usize {
pub fn undefined_field<P>(&mut self, prop: P) -> usize
where
P: Into<u8> + Display + Clone,
{
self.field_header(prop, PropFlags::Undefined)
}
#[allow(dead_code)]
pub fn null_field(&mut self, prop: AstProp) -> usize {
pub fn null_field<P>(&mut self, prop: P) -> usize
where
P: Into<u8> + Display + Clone,
{
self.field_header(prop, PropFlags::Null)
}
fn field(&mut self, prop: AstProp, prop_flags: PropFlags) -> usize {
let offset = self.field_header(prop, prop_flags);
append_usize(&mut self.buf, 0);
offset
}
pub fn write_ref(&mut self, field_offset: usize, value: NodeRef) {
#[cfg(debug_assertions)]
{
@ -586,15 +390,6 @@ impl SerializeCtx {
self.buf[field_offset + 2] = if value { 1 } else { 0 };
}
pub fn push_node(
&mut self,
kind: AstNode,
parent: NodeRef,
span: &Span,
) -> NodeRef {
self.header(kind, parent, span, 0)
}
pub fn serialize(&mut self) -> Vec<u8> {
let mut buf: Vec<u8> = vec![];
@ -607,6 +402,20 @@ impl SerializeCtx {
// eprintln!("STRING {:#?}", self.str_table);
buf.append(&mut self.str_table.serialize());
let offset_kind_map = buf.len();
append_usize(&mut buf, self.kind_map.len());
for v in &self.kind_map {
append_usize(&mut buf, *v);
}
let offset_prop_map = buf.len();
append_usize(&mut buf, self.prop_map.len());
for v in &self.prop_map {
append_usize(&mut buf, *v);
}
append_usize(&mut buf, offset_kind_map);
append_usize(&mut buf, offset_prop_map);
append_usize(&mut buf, offset_str_table);
append_usize(&mut buf, self.start_buf.0);

View file

@ -59,6 +59,7 @@ mod plugins;
mod reporters;
mod rules;
mod swc;
mod ts_estree;
pub use linter::CliLinter;
pub use linter::CliLinterOptions;

View file

@ -23,10 +23,13 @@ use deno_ast::{
ParsedSource,
};
use super::ast_buf::{append_usize, AstNode, AstProp, NodeRef, SerializeCtx};
use super::{
ast_buf::{AstBufSerializer, NodeRef},
ts_estree::{AstNode, AstProp, TsEsTreeBuilder},
};
pub fn serialize_ast_bin(parsed_source: &ParsedSource) -> Vec<u8> {
let mut ctx = SerializeCtx::new();
let mut ctx = TsEsTreeBuilder::new();
let program = &parsed_source.program();
@ -70,16 +73,16 @@ pub fn serialize_ast_bin(parsed_source: &ParsedSource) -> Vec<u8> {
}
fn serialize_module_decl(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
module_decl: &ModuleDecl,
parent: NodeRef,
) -> NodeRef {
match module_decl {
ModuleDecl::Import(node) => {
ctx.push_node(AstNode::Import, parent, &node.span)
ctx.header(AstNode::Import, parent, &node.span, 0)
}
ModuleDecl::ExportDecl(node) => {
ctx.push_node(AstNode::ExportDecl, parent, &node.span)
ctx.header(AstNode::ExportDecl, parent, &node.span, 0)
}
ModuleDecl::ExportNamed(node) => {
let id =
@ -139,28 +142,28 @@ fn serialize_module_decl(
id
}
ModuleDecl::ExportDefaultDecl(node) => {
ctx.push_node(AstNode::ExportDefaultDecl, parent, &node.span)
ctx.header(AstNode::ExportDefaultDecl, parent, &node.span, 0)
}
ModuleDecl::ExportDefaultExpr(node) => {
ctx.push_node(AstNode::ExportDefaultExpr, parent, &node.span)
ctx.header(AstNode::ExportDefaultExpr, parent, &node.span, 0)
}
ModuleDecl::ExportAll(node) => {
ctx.push_node(AstNode::ExportAll, parent, &node.span)
ctx.header(AstNode::ExportAll, parent, &node.span, 0)
}
ModuleDecl::TsImportEquals(node) => {
ctx.push_node(AstNode::TsImportEquals, parent, &node.span)
ctx.header(AstNode::TsImportEquals, parent, &node.span, 0)
}
ModuleDecl::TsExportAssignment(node) => {
ctx.push_node(AstNode::TsExportAssignment, parent, &node.span)
ctx.header(AstNode::TsExportAssignment, parent, &node.span, 0)
}
ModuleDecl::TsNamespaceExport(node) => {
ctx.push_node(AstNode::TsNamespaceExport, parent, &node.span)
ctx.header(AstNode::TsNamespaceExport, parent, &node.span, 0)
}
}
}
fn serialize_stmt(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
stmt: &Stmt,
parent: NodeRef,
) -> NodeRef {
@ -181,7 +184,7 @@ fn serialize_stmt(
}
Stmt::Empty(_) => NodeRef(0),
Stmt::Debugger(node) => {
ctx.push_node(AstNode::Debugger, parent, &node.span)
ctx.header(AstNode::Debugger, parent, &node.span, 0)
}
Stmt::With(_) => todo!(),
Stmt::Return(node) => {
@ -438,12 +441,12 @@ fn serialize_stmt(
}
fn serialize_expr(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
expr: &Expr,
parent: NodeRef,
) -> NodeRef {
match expr {
Expr::This(node) => ctx.push_node(AstNode::This, parent, &node.span),
Expr::This(node) => ctx.header(AstNode::This, parent, &node.span, 0),
Expr::Array(node) => {
let pos = ctx.header(AstNode::ArrayExpression, parent, &node.span, 1);
let elems_pos = ctx.ref_vec_field(AstProp::Elements, node.elems.len());
@ -681,7 +684,7 @@ fn serialize_expr(
let obj_pos = ctx.ref_field(AstProp::Object);
let prop_pos = ctx.ref_field(AstProp::Property);
let obj = ctx.push_node(AstNode::Super, pos, &node.obj.span);
let obj = ctx.header(AstNode::Super, pos, &node.obj.span, 0);
let mut computed = false;
let prop = match &node.prop {
@ -726,7 +729,7 @@ fn serialize_expr(
let callee = match &node.callee {
Callee::Super(super_node) => {
ctx.push_node(AstNode::Super, pos, &super_node.span)
ctx.header(AstNode::Super, pos, &super_node.span, 0)
}
Callee::Import(import) => todo!(),
Callee::Expr(expr) => serialize_expr(ctx, expr, pos),
@ -891,7 +894,7 @@ fn serialize_expr(
pos
}
Expr::Class(node) => {
let id = ctx.push_node(AstNode::ClassExpr, parent, &node.class.span);
let id = ctx.header(AstNode::ClassExpr, parent, &node.class.span, 0);
// FIXME
@ -913,7 +916,7 @@ fn serialize_expr(
pos
}
Expr::MetaProp(node) => {
ctx.push_node(AstNode::MetaProp, parent, &node.span)
ctx.header(AstNode::MetaProp, parent, &node.span, 0)
}
Expr::Await(node) => {
let pos = ctx.header(AstNode::AwaitExpression, parent, &node.span, 1);
@ -1061,7 +1064,7 @@ fn serialize_expr(
}
fn serialize_prop_or_spread(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
prop: &PropOrSpread,
parent: NodeRef,
) -> NodeRef {
@ -1204,7 +1207,7 @@ fn serialize_prop_or_spread(
}
fn serialize_member_expr(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &MemberExpr,
parent: NodeRef,
optional: bool,
@ -1239,7 +1242,7 @@ fn serialize_member_expr(
}
fn serialize_class_member(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
member: &ClassMember,
parent: NodeRef,
) -> NodeRef {
@ -1334,7 +1337,7 @@ fn serialize_class_member(
}
fn serialize_expr_or_spread(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
arg: &ExprOrSpread,
parent: NodeRef,
) -> NodeRef {
@ -1346,7 +1349,7 @@ fn serialize_expr_or_spread(
}
fn serialize_ident(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
ident: &Ident,
parent: NodeRef,
) -> NodeRef {
@ -1358,7 +1361,7 @@ fn serialize_ident(
}
fn serialize_module_exported_name(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
name: &ModuleExportName,
parent: NodeRef,
) -> NodeRef {
@ -1371,7 +1374,7 @@ fn serialize_module_exported_name(
}
fn serialize_decl(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
decl: &Decl,
parent: NodeRef,
) -> NodeRef {
@ -1521,7 +1524,7 @@ fn serialize_decl(
id
}
Decl::Using(node) => {
let id = ctx.push_node(AstNode::Using, parent, &node.span);
let id = ctx.header(AstNode::Using, parent, &node.span, 0);
for (i, decl) in node.decls.iter().enumerate() {
// FIXME
@ -1687,7 +1690,7 @@ fn serialize_decl(
pos
}
Decl::TsModule(ts_module_decl) => {
ctx.push_node(AstNode::TsModule, parent, &ts_module_decl.span)
ctx.header(AstNode::TsModule, parent, &ts_module_decl.span, 0)
}
}
}
@ -1701,7 +1704,7 @@ fn accessibility_to_str(accessibility: Accessibility) -> String {
}
fn serialize_private_name(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &PrivateName,
parent: NodeRef,
) -> NodeRef {
@ -1714,7 +1717,7 @@ fn serialize_private_name(
}
fn serialize_jsx_element(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &JSXElement,
parent: NodeRef,
) -> NodeRef {
@ -1746,7 +1749,7 @@ fn serialize_jsx_element(
}
fn serialize_jsx_fragment(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &JSXFragment,
parent: NodeRef,
) -> NodeRef {
@ -1757,9 +1760,9 @@ fn serialize_jsx_fragment(
let children_pos = ctx.ref_vec_field(AstProp::Children, node.children.len());
let opening_id =
ctx.push_node(AstNode::JSXOpeningFragment, pos, &node.opening.span);
ctx.header(AstNode::JSXOpeningFragment, pos, &node.opening.span, 0);
let closing_id =
ctx.push_node(AstNode::JSXClosingFragment, pos, &node.closing.span);
ctx.header(AstNode::JSXClosingFragment, pos, &node.closing.span, 0);
let children = serialize_jsx_children(ctx, &node.children, pos);
@ -1771,7 +1774,7 @@ fn serialize_jsx_fragment(
}
fn serialize_jsx_children(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
children: &[JSXElementChild],
parent: NodeRef,
) -> Vec<NodeRef> {
@ -1806,7 +1809,7 @@ fn serialize_jsx_children(
}
fn serialize_jsx_member_expr(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &JSXMemberExpr,
parent: NodeRef,
) -> NodeRef {
@ -1830,7 +1833,7 @@ fn serialize_jsx_member_expr(
}
fn serialize_jsx_element_name(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &JSXElementName,
parent: NodeRef,
) -> NodeRef {
@ -1848,7 +1851,7 @@ fn serialize_jsx_element_name(
}
fn serialize_jsx_opening_element(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &JSXOpeningElement,
parent: NodeRef,
) -> NodeRef {
@ -1919,7 +1922,7 @@ fn serialize_jsx_opening_element(
}
fn serialize_jsx_container_expr(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &JSXExprContainer,
parent: NodeRef,
) -> NodeRef {
@ -1937,15 +1940,15 @@ fn serialize_jsx_container_expr(
}
fn serialize_jsx_empty_expr(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &JSXEmptyExpr,
parent: NodeRef,
) -> NodeRef {
ctx.push_node(AstNode::JSXEmptyExpression, parent, &node.span)
ctx.header(AstNode::JSXEmptyExpression, parent, &node.span, 0)
}
fn serialize_jsx_namespaced_name(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &JSXNamespacedName,
parent: NodeRef,
) -> NodeRef {
@ -1963,7 +1966,7 @@ fn serialize_jsx_namespaced_name(
}
fn serialize_ident_name_as_jsx_identifier(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &IdentName,
parent: NodeRef,
) -> NodeRef {
@ -1976,7 +1979,7 @@ fn serialize_ident_name_as_jsx_identifier(
}
fn serialize_jsx_identifier(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &Ident,
parent: NodeRef,
) -> NodeRef {
@ -1989,7 +1992,7 @@ fn serialize_jsx_identifier(
}
fn serialize_pat(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
pat: &Pat,
parent: NodeRef,
) -> NodeRef {
@ -2116,7 +2119,7 @@ fn serialize_pat(
}
fn serialize_for_head(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
for_head: &ForHead,
parent: NodeRef,
) -> NodeRef {
@ -2132,7 +2135,7 @@ fn serialize_for_head(
}
fn serialize_spread(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
expr: &Expr,
span: &Span,
parent: NodeRef,
@ -2147,7 +2150,7 @@ fn serialize_spread(
}
fn serialize_ident_name(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
ident_name: &IdentName,
parent: NodeRef,
) -> NodeRef {
@ -2159,7 +2162,7 @@ fn serialize_ident_name(
}
fn serialize_prop_name(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
prop_name: &PropName,
parent: NodeRef,
) -> NodeRef {
@ -2168,13 +2171,12 @@ fn serialize_prop_name(
serialize_ident_name(ctx, ident_name, parent)
}
PropName::Str(str_prop) => {
let child_id =
ctx.push_node(AstNode::StringLiteral, parent, &str_prop.span);
let child_pos =
ctx.header(AstNode::StringLiteral, parent, &str_prop.span, 1);
let value_pos = ctx.str_field(AstProp::Value);
ctx.write_str(value_pos, &str_prop.value);
let str_id = ctx.str_table.insert(str_prop.value.as_str());
append_usize(&mut ctx.buf, str_id);
child_id
child_pos
}
PropName::Num(number) => {
serialize_lit(ctx, &Lit::Num(number.clone()), parent)
@ -2187,7 +2189,7 @@ fn serialize_prop_name(
}
fn serialize_lit(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
lit: &Lit,
parent: NodeRef,
) -> NodeRef {
@ -2208,7 +2210,7 @@ fn serialize_lit(
pos
}
Lit::Null(node) => ctx.push_node(AstNode::Null, parent, &node.span),
Lit::Null(node) => ctx.header(AstNode::Null, parent, &node.span, 0),
Lit::Num(node) => {
let pos = ctx.header(AstNode::NumericLiteral, parent, &node.span, 1);
let value_pos = ctx.str_field(AstProp::Value);
@ -2237,13 +2239,13 @@ fn serialize_lit(
pos
}
Lit::JSXText(jsxtext) => {
ctx.push_node(AstNode::JSXText, parent, &jsxtext.span)
ctx.header(AstNode::JSXText, parent, &jsxtext.span, 0)
}
}
}
fn serialize_ts_type(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &TsType,
parent: NodeRef,
) -> NodeRef {
@ -2265,10 +2267,10 @@ fn serialize_ts_type(
TsKeywordTypeKind::TsIntrinsicKeyword => AstNode::TSIntrinsicKeyword,
};
ctx.push_node(kind, parent, &node.span)
ctx.header(kind, parent, &node.span, 0)
}
TsType::TsThisType(node) => {
ctx.push_node(AstNode::TSThisType, parent, &node.span)
ctx.header(AstNode::TSThisType, parent, &node.span, 0)
}
TsType::TsFnOrConstructorType(node) => match node {
TsFnOrConstructorType::TsFnType(node) => {
@ -2455,7 +2457,7 @@ fn serialize_ts_type(
}
fn create_true_plus_minus_field(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
prop: AstProp,
value: Option<TruePlusMinus>,
) -> usize {
@ -2470,7 +2472,7 @@ fn create_true_plus_minus_field(
}
fn write_true_plus_minus(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
pos: usize,
value: Option<TruePlusMinus>,
) {
@ -2486,7 +2488,7 @@ fn write_true_plus_minus(
}
fn serialize_ts_entity_name(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &TsEntityName,
parent: NodeRef,
) -> NodeRef {
@ -2497,7 +2499,7 @@ fn serialize_ts_entity_name(
}
fn maybe_serialize_ts_type_ann(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &Option<Box<TsTypeAnn>>,
parent: NodeRef,
) -> Option<NodeRef> {
@ -2507,7 +2509,7 @@ fn maybe_serialize_ts_type_ann(
}
fn serialize_ts_type_ann(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &TsTypeAnn,
parent: NodeRef,
) -> NodeRef {
@ -2522,7 +2524,7 @@ fn serialize_ts_type_ann(
}
fn maybe_serialize_ts_type(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &Option<Box<TsType>>,
parent: NodeRef,
) -> Option<NodeRef> {
@ -2532,7 +2534,7 @@ fn maybe_serialize_ts_type(
}
fn serialize_ts_type_param(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &TsTypeParam,
parent: NodeRef,
) -> NodeRef {
@ -2559,7 +2561,7 @@ fn serialize_ts_type_param(
}
fn maybe_serialize_ts_type_param(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &Option<Box<TsTypeParamDecl>>,
parent: NodeRef,
) -> Option<NodeRef> {
@ -2581,7 +2583,7 @@ fn maybe_serialize_ts_type_param(
}
fn serialize_ts_fn_param(
ctx: &mut SerializeCtx,
ctx: &mut TsEsTreeBuilder,
node: &TsFnParam,
parent: NodeRef,
) -> NodeRef {

467
cli/tools/lint/ts_estree.rs Normal file
View file

@ -0,0 +1,467 @@
use std::fmt::{self, Debug, Display};
use deno_ast::swc::common::Span;
use super::ast_buf::{AstBufSerializer, NodeRef, SerializeCtx};
// Keep in sync with JS
#[derive(Debug, Clone, PartialEq)]
pub enum AstNode {
Invalid,
//
Program,
// Module declarations
Import,
ImportDecl,
ExportDecl,
ExportNamedDeclaration,
ExportDefaultDecl,
ExportDefaultExpr,
ExportAll,
TsImportEquals,
TsExportAssignment,
TsNamespaceExport,
// Decls
ClassDeclaration,
Fn,
Var,
Using,
TSInterface,
TsTypeAlias,
TSEnumDeclaration,
TsModule,
// Statements
Block,
Empty,
Debugger,
With,
Return,
Labeled,
Break,
Continue,
IfStatement,
Switch,
SwitchCase,
Throw,
TryStatement,
WhileStatement,
DoWhileStatement,
ForStatement,
ForInStatement,
ForOfStatement,
Decl,
ExpressionStatement,
// Expressions
This,
ArrayExpression,
Object,
FunctionExpression,
UnaryExpression,
UpdateExpression,
BinaryExpression,
Assign,
MemberExpression,
Super,
ConditionalExpression,
CallExpression,
New,
Paren,
SequenceExpression,
Identifier,
TemplateLiteral,
TaggedTemplateExpression,
ArrowFunctionExpression,
ClassExpr,
YieldExpression,
MetaProp,
AwaitExpression,
LogicalExpression,
TSTypeAssertion,
TsConstAssertion,
TSNonNullExpression,
TSAsExpression,
TsInstantiation,
TSSatisfiesExpression,
PrivateIdentifier,
ChainExpression,
// Literals
StringLiteral,
Bool,
Null,
NumericLiteral,
BigIntLiteral,
RegExpLiteral,
// Custom
EmptyExpr,
Spread,
Property,
VariableDeclarator,
CatchClause,
RestElement,
ExportSpecifier,
TemplateElement,
MethodDefinition,
// Patterns
ArrayPattern,
AssignmentPattern,
ObjectPattern,
// JSX
JSXAttribute,
JSXClosingElement,
JSXClosingFragment,
JSXElement,
JSXEmptyExpression,
JSXExpressionContainer,
JSXFragment,
JSXIdentifier,
JSXMemberExpression,
JSXNamespacedName,
JSXOpeningElement,
JSXOpeningFragment,
JSXSpreadAttribute,
JSXSpreadChild,
JSXText,
TSTypeAnnotation,
TSTypeParameterDeclaration,
TSTypeParameter,
TSEnumMember,
TSInterfaceBody,
TSInterfaceHeritage,
TSTypeReference,
TSThisType,
TSLiteralType,
TSInferType,
TSConditionalType,
TSUnionType,
TSIntersectionType,
TSMappedType,
TSTypeQuery,
TSTupleType,
TSFunctionType,
TsCallSignatureDeclaration,
TSAnyKeyword,
TSBigIntKeyword,
TSBooleanKeyword,
TSIntrinsicKeyword,
TSNeverKeyword,
TSNullKeyword,
TSNumberKeyword,
TSObjectKeyword,
TSStringKeyword,
TSSymbolKeyword,
TSUndefinedKeyword,
TSUnknownKeyword,
TSVoidKeyword,
TSEnumBody, // Last value is used for max value
}
impl Display for AstNode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(self, f)
}
}
impl From<AstNode> for u8 {
fn from(m: AstNode) -> u8 {
m as u8
}
}
#[derive(Debug, Clone)]
pub enum AstProp {
// Base, these three must be in sync with JS
Type,
Parent,
Range,
// Node
Abstract,
Accessibility,
Alternate,
Argument,
Arguments,
Async,
Attributes,
Await,
Block,
Body,
Callee,
Cases,
Children,
CheckType,
ClosingElement,
ClosingFragment,
Computed,
Consequent,
Const,
Constraint,
Cooked,
Declarations,
Declare,
Default,
Definite,
Delegate,
Discriminant,
Elements,
ElementTypes,
ExprName,
Expression,
Expressions,
Exported,
ExtendsType,
FalseType,
Finalizer,
Flags,
Generator,
Handler,
Id,
In,
Init,
Initializer,
Implements,
Key,
Kind,
Label,
Left,
Literal,
Local,
Members,
Meta,
Method,
Name,
Namespace,
NameType,
Object,
OpeningElement,
OpeningFragment,
Operator,
Optional,
Out,
Param,
Params,
Pattern,
Prefix,
Properties,
Property,
Quasi,
Quasis,
Raw,
Readonly,
ReturnType,
Right,
SelfClosing,
Shorthand,
Source,
SourceType,
Specifiers,
SuperClass,
SuperTypeArguments,
Tag,
Tail,
Test,
TrueType,
TypeAnnotation,
TypeArguments,
TypeName,
TypeParameter,
TypeParameters,
Types,
Update,
Value, // Last value is used for max value
}
impl Display for AstProp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match self {
AstProp::Parent => "parent",
AstProp::Range => "range",
AstProp::Type => "type",
AstProp::Abstract => "abstract",
AstProp::Accessibility => "accessibility",
AstProp::Alternate => "alternate",
AstProp::Argument => "argument",
AstProp::Arguments => "arguments",
AstProp::Async => "async",
AstProp::Attributes => "attributes",
AstProp::Await => "await",
AstProp::Block => "block",
AstProp::Body => "body",
AstProp::Callee => "callee",
AstProp::Cases => "cases",
AstProp::Children => "children",
AstProp::CheckType => "checkType",
AstProp::ClosingElement => "closingElement",
AstProp::ClosingFragment => "closingFragment",
AstProp::Computed => "computed",
AstProp::Consequent => "consequent",
AstProp::Const => "const",
AstProp::Constraint => "constraint",
AstProp::Cooked => "cooked",
AstProp::Declarations => "declarations",
AstProp::Declare => "declare",
AstProp::Default => "default",
AstProp::Definite => "definite",
AstProp::Delegate => "delegate",
AstProp::Discriminant => "discriminant",
AstProp::Elements => "elements",
AstProp::ElementTypes => "elementTypes",
AstProp::ExprName => "exprName",
AstProp::Expression => "expression",
AstProp::Expressions => "expressions",
AstProp::Exported => "exported",
AstProp::ExtendsType => "extendsType",
AstProp::FalseType => "falseType",
AstProp::Finalizer => "finalizer",
AstProp::Flags => "flags",
AstProp::Generator => "generator",
AstProp::Handler => "handler",
AstProp::Id => "id",
AstProp::In => "in",
AstProp::Init => "init",
AstProp::Initializer => "initializer",
AstProp::Implements => "implements",
AstProp::Key => "key",
AstProp::Kind => "kind",
AstProp::Label => "label",
AstProp::Left => "left",
AstProp::Literal => "literal",
AstProp::Local => "local",
AstProp::Members => "members",
AstProp::Meta => "meta",
AstProp::Method => "method",
AstProp::Name => "name",
AstProp::Namespace => "namespace",
AstProp::NameType => "nameType",
AstProp::Object => "object",
AstProp::OpeningElement => "openingElement",
AstProp::OpeningFragment => "openingFragment",
AstProp::Operator => "operator",
AstProp::Optional => "optional",
AstProp::Out => "out",
AstProp::Param => "param",
AstProp::Params => "params",
AstProp::Pattern => "pattern",
AstProp::Prefix => "prefix",
AstProp::Properties => "properties",
AstProp::Property => "property",
AstProp::Quasi => "quasi",
AstProp::Quasis => "quasis",
AstProp::Raw => "raw",
AstProp::Readonly => "readonly",
AstProp::ReturnType => "returnType",
AstProp::Right => "right",
AstProp::SelfClosing => "selfClosing",
AstProp::Shorthand => "shorthand",
AstProp::Source => "source",
AstProp::SourceType => "sourceType",
AstProp::Specifiers => "specifiers",
AstProp::SuperClass => "superClass",
AstProp::SuperTypeArguments => "superTypeArguments",
AstProp::Tag => "tag",
AstProp::Tail => "tail",
AstProp::Test => "test",
AstProp::TrueType => "trueType",
AstProp::TypeAnnotation => "typeAnnotation",
AstProp::TypeArguments => "typeArguments",
AstProp::TypeName => "typeName",
AstProp::TypeParameter => "typeParameter",
AstProp::TypeParameters => "typeParameters",
AstProp::Types => "types",
AstProp::Update => "update",
AstProp::Value => "value",
};
write!(f, "{}", s)
}
}
impl From<AstProp> for u8 {
fn from(m: AstProp) -> u8 {
m as u8
}
}
pub struct TsEsTreeBuilder {
ctx: SerializeCtx,
}
impl TsEsTreeBuilder {
pub fn new() -> Self {
// Max values
let kind_count: u8 = AstNode::TSEnumBody.into();
let prop_count: u8 = AstProp::Value.into();
Self {
ctx: SerializeCtx::new(kind_count, prop_count),
}
}
}
impl AstBufSerializer<AstNode, AstProp> for TsEsTreeBuilder {
fn header(
&mut self,
kind: AstNode,
parent: NodeRef,
span: &Span,
prop_count: usize,
) -> NodeRef {
self.ctx.header(kind, parent, span, prop_count)
}
fn ref_field(&mut self, prop: AstProp) -> usize {
self.ctx.ref_field(prop)
}
fn ref_vec_field(&mut self, prop: AstProp, len: usize) -> usize {
self.ctx.ref_vec_field(prop, len)
}
fn str_field(&mut self, prop: AstProp) -> usize {
self.ctx.str_field(prop)
}
fn bool_field(&mut self, prop: AstProp) -> usize {
self.ctx.bool_field(prop)
}
fn undefined_field(&mut self, prop: AstProp) -> usize {
self.ctx.undefined_field(prop)
}
fn null_field(&mut self, prop: AstProp) -> usize {
self.ctx.null_field(prop)
}
fn write_ref(&mut self, pos: usize, value: NodeRef) {
self.ctx.write_ref(pos, value);
}
fn write_maybe_ref(&mut self, pos: usize, value: Option<NodeRef>) {
self.ctx.write_maybe_ref(pos, value);
}
fn write_refs(&mut self, pos: usize, value: Vec<NodeRef>) {
self.ctx.write_refs(pos, value);
}
fn write_str(&mut self, pos: usize, value: &str) {
self.ctx.write_str(pos, value);
}
fn write_bool(&mut self, pos: usize, value: bool) {
self.ctx.write_bool(pos, value);
}
fn serialize(&mut self) -> Vec<u8> {
self.ctx.serialize()
}
}