0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 12:16:11 -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; } = core.ops;
// Keep in sync with Rust // Keep in sync with Rust
/** const AST_PROP_TYPE = 0;
* @enum {number} const AST_PROP_PARENT = 1;
*/ const AST_PROP_RANGE = 2;
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());
// Keep in sync with Rust // Keep in sync with Rust
/** @enum {number} */ /** @enum {number} */
@ -274,7 +31,10 @@ const PropFlags = {
* strTable: Map<number, string>, * strTable: Map<number, string>,
* strTableOffset: number, * strTableOffset: number,
* rootId: number, * rootId: number,
* nodes: Map<number, Node> * nodes: Map<number, Node>,
* strByType: number[],
* typeByStr: Map<string, number>,
* strByProp: number[]
* }} AstContext * }} AstContext
*/ */
@ -421,7 +181,7 @@ function readValue(ctx, offset, search) {
const type = buf[offset]; const type = buf[offset];
if (search === AST_PROP_TYPE) { if (search === AST_PROP_TYPE) {
return AstTypeName[type]; return getString(ctx, ctx.strByType[type]);
} else if (search === AST_PROP_RANGE) { } else if (search === AST_PROP_RANGE) {
const start = readU32(buf, offset + 1 + 4); const start = readU32(buf, offset + 1 + 4);
const end = readU32(buf, offset + 1 + 4 + 4); const end = readU32(buf, offset + 1 + 4 + 4);
@ -484,7 +244,7 @@ function toJsValue(ctx, offset) {
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const prop = buf[offset++]; const prop = buf[offset++];
const kind = buf[offset++]; const kind = buf[offset++];
const name = AstPropName[prop]; const name = getString(ctx, ctx.strByProp[prop]);
if (kind === PropFlags.Ref) { if (kind === PropFlags.Ref) {
const v = readU32(buf, offset); const v = readU32(buf, offset);
@ -545,13 +305,28 @@ class Node {
} }
} }
for (let i = 0; i < AstPropName.length; i++) { /** @type {Set<number>} */
const name = AstPropName[i]; const appliedGetters = new Set();
Object.defineProperty(Node.prototype, name, {
get() { /**
return readValue(this[INTERNAL_CTX], this[INTERNAL_OFFSET], i); * @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(); const DECODER = new TextDecoder();
@ -590,6 +365,8 @@ function createAstContext(buf) {
// console.log(JSON.stringify(buf, null, 2)); // 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 strTableOffset = readU32(buf, buf.length - 8);
const rootId = readU32(buf, buf.length - 4); const rootId = readU32(buf, buf.length - 4);
// console.log({ strTableOffset, rootId }); // console.log({ strTableOffset, rootId });
@ -618,10 +395,48 @@ function createAstContext(buf) {
); );
} }
/** @type {AstContext} */ offset = typeMapOffset;
const ctx = { buf, strTable, rootId, nodes: new Map(), strTableOffset }; 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; return ctx;
} }
@ -709,11 +524,11 @@ function traverse(ctx, visitor) {
// TODO: create visiting types // TODO: create visiting types
for (const name in visitor) { for (const name in visitor) {
const id = AstType.get(name); const id = ctx.typeByStr.get(name);
if (id === undefined) continue;
visitTypes.set(id, name); visitTypes.set(id, name);
} }
// console.log("buffer len", ctx.buf.length, ctx.buf.byteLength);
console.log("merged visitor", visitor); console.log("merged visitor", visitor);
console.log("visiting types", visitTypes); console.log("visiting types", visitTypes);
@ -779,13 +594,31 @@ function traverseInner(ctx, visitTypes, visitor, offset) {
* @param {AstContext} ctx * @param {AstContext} ctx
*/ */
function _dump(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; let offset = 0;
while (offset < strTableOffset) { while (offset < strTableOffset) {
const type = buf[offset]; const type = buf[offset];
const name = AstTypeName[type]; const name = getString(ctx, ctx.strByType[type]);
// @ts-ignore dump fn // @ts-ignore dump fn
console.log(`${name}, offset: ${offset}, type: ${type}`); console.log(`${name}, offset: ${offset}, type: ${type}`);
offset += 1; offset += 1;
@ -800,7 +633,7 @@ function _dump(ctx) {
const end = readU32(buf, offset); const end = readU32(buf, offset);
offset += 4; offset += 4;
// @ts-ignore dump fn // @ts-ignore dump fn
console.log(` range: ${start} -> ${end}}`); console.log(` range: ${start} -> ${end}`);
const count = buf[offset++]; const count = buf[offset++];
// @ts-ignore dump fn // @ts-ignore dump fn
@ -809,7 +642,7 @@ function _dump(ctx) {
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const prop = buf[offset++]; const prop = buf[offset++];
const kind = buf[offset++]; const kind = buf[offset++];
const name = AstPropName[prop]; const name = getString(ctx, ctx.strByProp[prop]);
let kindName = "unknown"; let kindName = "unknown";
for (const k in PropFlags) { for (const k in PropFlags) {
@ -823,35 +656,35 @@ function _dump(ctx) {
const v = readU32(buf, offset); const v = readU32(buf, offset);
offset += 4; offset += 4;
// @ts-ignore dump fn // @ts-ignore dump fn
console.log(` ${name}: ${v} (${kindName})`); console.log(` ${name}: ${v} (${kindName}, ${prop})`);
} else if (kind === PropFlags.RefArr) { } else if (kind === PropFlags.RefArr) {
const len = readU32(buf, offset); const len = readU32(buf, offset);
offset += 4; offset += 4;
// @ts-ignore dump fn // @ts-ignore dump fn
console.log(` ${name}: Array(${len}) (${kindName})`); console.log(` ${name}: Array(${len}) (${kindName}, ${prop})`);
for (let j = 0; j < len; j++) { for (let j = 0; j < len; j++) {
const v = readU32(buf, offset); const v = readU32(buf, offset);
offset += 4; offset += 4;
// @ts-ignore dump fn // @ts-ignore dump fn
console.log(` - ${v}`); console.log(` - ${v} (${prop})`);
} }
} else if (kind === PropFlags.Bool) { } else if (kind === PropFlags.Bool) {
const v = buf[offset]; const v = buf[offset];
offset += 1; offset += 1;
// @ts-ignore dump fn // @ts-ignore dump fn
console.log(` ${name}: ${v} (${kindName})`); console.log(` ${name}: ${v} (${kindName}, ${prop})`);
} else if (kind === PropFlags.String) { } else if (kind === PropFlags.String) {
const v = readU32(buf, offset); const v = readU32(buf, offset);
offset += 4; offset += 4;
// @ts-ignore dump fn // @ts-ignore dump fn
console.log(` ${name}: ${getString(ctx, v)} (${kindName})`); console.log(` ${name}: ${getString(ctx, v)} (${kindName}, ${prop})`);
} else if (kind === PropFlags.Null) { } else if (kind === PropFlags.Null) {
// @ts-ignore dump fn // @ts-ignore dump fn
console.log(` ${name}: null (${kindName})`); console.log(` ${name}: null (${kindName}, ${prop})`);
} else if (kind === PropFlags.Undefined) { } else if (kind === PropFlags.Undefined) {
// @ts-ignore dump fn // @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 deno_ast::swc::common::{Span, DUMMY_SP};
use indexmap::IndexMap; 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)] #[derive(Debug, PartialEq)]
pub enum PropFlags { pub enum PropFlags {
Ref, Ref,
@ -346,26 +71,6 @@ pub fn write_usize(result: &mut [u8], value: usize, idx: usize) {
result[idx + 3] = v4; 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)] #[derive(Debug)]
pub struct StringTable { pub struct StringTable {
id: usize, id: usize,
@ -411,42 +116,118 @@ impl StringTable {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct NodeRef(pub usize); 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)] #[derive(Debug)]
pub struct SerializeCtx { pub struct SerializeCtx {
pub buf: Vec<u8>, buf: Vec<u8>,
pub start_buf: NodeRef, start_buf: NodeRef,
pub str_table: StringTable, str_table: StringTable,
kind_map: Vec<usize>,
prop_map: Vec<usize>,
} }
impl SerializeCtx { 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 { let mut ctx = Self {
start_buf: NodeRef(0), start_buf: NodeRef(0),
buf: vec![], buf: vec![],
str_table: StringTable::new(), str_table: StringTable::new(),
kind_map: vec![0; kind_size + 1],
prop_map: vec![0; prop_size + 1],
}; };
ctx.str_table.insert(""); ctx.str_table.insert("");
// Placeholder node // Placeholder node is always 0
ctx.push_node(AstNode::Invalid, NodeRef(0), &DUMMY_SP); ctx.append_node(0, NodeRef(0), &DUMMY_SP, 0);
ctx.kind_map[0] = 0;
ctx.start_buf = NodeRef(ctx.buf.len()); 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 ctx
} }
/// Begin writing a node fn field_header<P>(&mut self, prop: P, prop_flags: PropFlags) -> usize
pub fn header( 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, &mut self,
kind: AstNode, kind: u8,
parent: NodeRef, parent: NodeRef,
span: &Span, span: &Span,
prop_count: usize, prop_count: usize,
) -> NodeRef { ) -> NodeRef {
let offset = self.buf.len(); let offset = self.buf.len();
let kind_value: u8 = kind.into(); self.buf.push(kind);
self.buf.push(kind_value);
append_usize(&mut self.buf, parent.0); append_usize(&mut self.buf, parent.0);
@ -460,11 +241,42 @@ impl SerializeCtx {
NodeRef(offset) 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) 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); let offset = self.field(prop, PropFlags::RefArr);
for _ in 0..len { for _ in 0..len {
@ -474,45 +286,37 @@ impl SerializeCtx {
offset 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) self.field(prop, PropFlags::String)
} }
fn field_header(&mut self, prop: AstProp, prop_flags: PropFlags) -> usize { pub fn bool_field<P>(&mut self, prop: P) -> usize
let offset = self.buf.len(); where
P: Into<u8> + Display + Clone,
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 {
let offset = self.field_header(prop, PropFlags::Bool); let offset = self.field_header(prop, PropFlags::Bool);
self.buf.push(0); self.buf.push(0);
offset 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) self.field_header(prop, PropFlags::Undefined)
} }
#[allow(dead_code)] #[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) 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) { pub fn write_ref(&mut self, field_offset: usize, value: NodeRef) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
@ -586,15 +390,6 @@ impl SerializeCtx {
self.buf[field_offset + 2] = if value { 1 } else { 0 }; 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> { pub fn serialize(&mut self) -> Vec<u8> {
let mut buf: Vec<u8> = vec![]; let mut buf: Vec<u8> = vec![];
@ -607,6 +402,20 @@ impl SerializeCtx {
// eprintln!("STRING {:#?}", self.str_table); // eprintln!("STRING {:#?}", self.str_table);
buf.append(&mut self.str_table.serialize()); 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, offset_str_table);
append_usize(&mut buf, self.start_buf.0); append_usize(&mut buf, self.start_buf.0);

View file

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

View file

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