vendor tsgo
This commit is contained in:
3059
tools/tsgo/internal/ast/ast.go
Normal file
3059
tools/tsgo/internal/ast/ast.go
Normal file
File diff suppressed because it is too large
Load Diff
10047
tools/tsgo/internal/ast/ast_generated.go
Normal file
10047
tools/tsgo/internal/ast/ast_generated.go
Normal file
File diff suppressed because it is too large
Load Diff
36
tools/tsgo/internal/ast/checkflags.go
Normal file
36
tools/tsgo/internal/ast/checkflags.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package ast
|
||||
|
||||
// CheckFlags
|
||||
|
||||
type CheckFlags uint32
|
||||
|
||||
const (
|
||||
CheckFlagsNone CheckFlags = 0
|
||||
CheckFlagsInstantiated CheckFlags = 1 << 0 // Instantiated symbol
|
||||
CheckFlagsSyntheticProperty CheckFlags = 1 << 1 // Property in union or intersection type
|
||||
CheckFlagsSyntheticMethod CheckFlags = 1 << 2 // Method in union or intersection type
|
||||
CheckFlagsReadonly CheckFlags = 1 << 3 // Readonly transient symbol
|
||||
CheckFlagsReadPartial CheckFlags = 1 << 4 // Synthetic property present in some but not all constituents
|
||||
CheckFlagsWritePartial CheckFlags = 1 << 5 // Synthetic property present in some but only satisfied by an index signature in others
|
||||
CheckFlagsHasNonUniformType CheckFlags = 1 << 6 // Synthetic property with non-uniform type in constituents
|
||||
CheckFlagsHasLiteralType CheckFlags = 1 << 7 // Synthetic property with at least one literal type in constituents
|
||||
CheckFlagsContainsPublic CheckFlags = 1 << 8 // Synthetic property with public constituent(s)
|
||||
CheckFlagsContainsProtected CheckFlags = 1 << 9 // Synthetic property with protected constituent(s)
|
||||
CheckFlagsContainsPrivate CheckFlags = 1 << 10 // Synthetic property with private constituent(s)
|
||||
CheckFlagsContainsStatic CheckFlags = 1 << 11 // Synthetic property with static constituent(s)
|
||||
CheckFlagsLate CheckFlags = 1 << 12 // Late-bound symbol for a computed property with a dynamic name
|
||||
CheckFlagsReverseMapped CheckFlags = 1 << 13 // Property of reverse-inferred homomorphic mapped type
|
||||
CheckFlagsOptionalParameter CheckFlags = 1 << 14 // Optional parameter
|
||||
CheckFlagsRestParameter CheckFlags = 1 << 15 // Rest parameter
|
||||
CheckFlagsDeferredType CheckFlags = 1 << 16 // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType`
|
||||
CheckFlagsHasNeverType CheckFlags = 1 << 17 // Synthetic property with at least one never type in constituents
|
||||
CheckFlagsMapped CheckFlags = 1 << 18 // Property of mapped type
|
||||
CheckFlagsStripOptional CheckFlags = 1 << 19 // Strip optionality in mapped property
|
||||
CheckFlagsUnresolved CheckFlags = 1 << 20 // Unresolved type alias symbol
|
||||
CheckFlagsIsDiscriminantComputed CheckFlags = 1 << 21 // IsDiscriminant flags has been computed
|
||||
CheckFlagsIsDiscriminant CheckFlags = 1 << 22 // Discriminant property
|
||||
CheckFlagsIndexSymbol CheckFlags = 1 << 23 // Synthetic property created from index signature
|
||||
CheckFlagsSynthetic = CheckFlagsSyntheticProperty | CheckFlagsSyntheticMethod
|
||||
CheckFlagsNonUniformAndLiteral = CheckFlagsHasNonUniformType | CheckFlagsHasLiteralType
|
||||
CheckFlagsPartial = CheckFlagsReadPartial | CheckFlagsWritePartial
|
||||
)
|
||||
86
tools/tsgo/internal/ast/deepclone.go
Normal file
86
tools/tsgo/internal/ast/deepclone.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package ast
|
||||
|
||||
import "github.com/microsoft/typescript-go/internal/core"
|
||||
|
||||
// Ideally, this would get cached on the node factory so there's only ever one set of closures made per factory
|
||||
func getDeepCloneVisitor(f *NodeFactory, syntheticLocation bool) *NodeVisitor {
|
||||
var visitor *NodeVisitor
|
||||
visitor = NewNodeVisitor(
|
||||
func(node *Node) *Node {
|
||||
visited := visitor.VisitEachChild(node)
|
||||
if visited != node {
|
||||
if syntheticLocation {
|
||||
visited.Loc = core.NewTextRange(-1, -1)
|
||||
}
|
||||
return visited
|
||||
}
|
||||
c := node.Clone(f) // forcibly clone leaf nodes, which will then cascade new nodes/arrays upwards via `update` calls
|
||||
// In strada, `factory.cloneNode` was dynamic and did _not_ clone positions for any "special cases", meanwhile
|
||||
// Node.Clone in corsa reliably uses `Update` calls for all nodes and so copies locations by default.
|
||||
// Deep clones are done to copy a node across files, so here, we explicitly make the location range synthetic on all cloned nodes
|
||||
if syntheticLocation {
|
||||
c.Loc = core.NewTextRange(-1, -1)
|
||||
}
|
||||
return c
|
||||
},
|
||||
f,
|
||||
NodeVisitorHooks{
|
||||
VisitNodes: func(nodes *NodeList, v *NodeVisitor) *NodeList {
|
||||
if nodes == nil {
|
||||
return nil
|
||||
}
|
||||
visited := v.VisitNodes(nodes)
|
||||
var newList *NodeList
|
||||
if visited != nodes {
|
||||
newList = visited
|
||||
} else {
|
||||
newList = nodes.Clone(v.Factory)
|
||||
}
|
||||
if syntheticLocation {
|
||||
newList.Loc = core.NewTextRange(-1, -1)
|
||||
if nodes.HasTrailingComma() {
|
||||
newList.Nodes[len(newList.Nodes)-1].Loc = core.NewTextRange(-2, -2)
|
||||
}
|
||||
}
|
||||
return newList
|
||||
},
|
||||
VisitModifiers: func(nodes *ModifierList, v *NodeVisitor) *ModifierList {
|
||||
if nodes == nil {
|
||||
return nil
|
||||
}
|
||||
visited := v.VisitModifiers(nodes)
|
||||
var newList *ModifierList
|
||||
if visited != nodes {
|
||||
newList = visited
|
||||
} else {
|
||||
newList = nodes.Clone(v.Factory)
|
||||
}
|
||||
if syntheticLocation {
|
||||
newList.Loc = core.NewTextRange(-1, -1)
|
||||
if nodes.HasTrailingComma() {
|
||||
newList.Nodes[len(newList.Nodes)-1].Loc = core.NewTextRange(-2, -2)
|
||||
}
|
||||
}
|
||||
return newList
|
||||
},
|
||||
},
|
||||
)
|
||||
return visitor
|
||||
}
|
||||
|
||||
func (f *NodeFactory) DeepCloneNode(node *Node) *Node {
|
||||
return getDeepCloneVisitor(f, true /*syntheticLocation*/).VisitNode(node)
|
||||
}
|
||||
|
||||
func (f *NodeFactory) DeepCloneReparse(node *Node) *Node {
|
||||
if node != nil {
|
||||
node = getDeepCloneVisitor(f, false /*syntheticLocation*/).VisitNode(node)
|
||||
SetParentInChildren(node)
|
||||
node.Flags |= NodeFlagsReparsed
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
func (f *NodeFactory) DeepCloneReparseModifiers(modifiers *ModifierList) *ModifierList {
|
||||
return getDeepCloneVisitor(f, false /*syntheticLocation*/).VisitModifiers(modifiers)
|
||||
}
|
||||
599
tools/tsgo/internal/ast/deepclone_test.go
Normal file
599
tools/tsgo/internal/ast/deepclone_test.go
Normal file
@@ -0,0 +1,599 @@
|
||||
package ast_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/parsetestutil"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
type NodeComparisonWorkItem struct {
|
||||
original *ast.Node
|
||||
copy *ast.Node
|
||||
}
|
||||
|
||||
func getChildren(node *ast.Node) []*ast.Node {
|
||||
children := []*ast.Node{}
|
||||
node.VisitEachChild(ast.NewNodeVisitor(func(node *ast.Node) *ast.Node {
|
||||
children = append(children, node)
|
||||
return node
|
||||
}, nil, ast.NodeVisitorHooks{}))
|
||||
return children
|
||||
}
|
||||
|
||||
func TestDeepCloneNodeSanityCheck(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := []struct {
|
||||
title string
|
||||
input string
|
||||
jsx bool
|
||||
}{
|
||||
{title: "StringLiteral#1", input: `;"test"`},
|
||||
{title: "StringLiteral#2", input: `;'test'`},
|
||||
{title: "NumericLiteral", input: `0`},
|
||||
{title: "BigIntLiteral", input: `0n`},
|
||||
{title: "BooleanLiteral#1", input: `true`},
|
||||
{title: "BooleanLiteral#2", input: `false`},
|
||||
{title: "NoSubstitutionTemplateLiteral", input: "``"},
|
||||
{title: "RegularExpressionLiteral#1", input: `/a/`},
|
||||
{title: "RegularExpressionLiteral#2", input: `/a/g`},
|
||||
{title: "NullLiteral", input: `null`},
|
||||
{title: "ThisExpression", input: `this`},
|
||||
{title: "SuperExpression", input: `super()`},
|
||||
{title: "ImportExpression", input: `import()`},
|
||||
{title: "PropertyAccess#1", input: `a.b`},
|
||||
{title: "PropertyAccess#2", input: `a.#b`},
|
||||
{title: "PropertyAccess#3", input: `a?.b`},
|
||||
{title: "PropertyAccess#4", input: `a?.b.c`},
|
||||
{title: "PropertyAccess#5", input: `1..b`},
|
||||
{title: "PropertyAccess#6", input: `1.0.b`},
|
||||
{title: "PropertyAccess#7", input: `0x1.b`},
|
||||
{title: "PropertyAccess#8", input: `0b1.b`},
|
||||
{title: "PropertyAccess#9", input: `0o1.b`},
|
||||
{title: "PropertyAccess#10", input: `10e1.b`},
|
||||
{title: "PropertyAccess#11", input: `10E1.b`},
|
||||
{title: "ElementAccess#1", input: `a[b]`},
|
||||
{title: "ElementAccess#2", input: `a?.[b]`},
|
||||
{title: "ElementAccess#3", input: `a?.[b].c`},
|
||||
{title: "CallExpression#1", input: `a()`},
|
||||
{title: "CallExpression#2", input: `a<T>()`},
|
||||
{title: "CallExpression#3", input: `a(b)`},
|
||||
{title: "CallExpression#4", input: `a<T>(b)`},
|
||||
{title: "CallExpression#5", input: `a(b).c`},
|
||||
{title: "CallExpression#6", input: `a<T>(b).c`},
|
||||
{title: "CallExpression#7", input: `a?.(b)`},
|
||||
{title: "CallExpression#8", input: `a?.<T>(b)`},
|
||||
{title: "CallExpression#9", input: `a?.(b).c`},
|
||||
{title: "CallExpression#10", input: `a?.<T>(b).c`},
|
||||
{title: "CallExpression#11", input: `a<T, U>()`},
|
||||
{title: "CallExpression#12", input: `a<T,>()`},
|
||||
{title: "NewExpression#1", input: `new a`},
|
||||
{title: "NewExpression#2", input: `new a.b`},
|
||||
{title: "NewExpression#3", input: `new a()`},
|
||||
{title: "NewExpression#4", input: `new a.b()`},
|
||||
{title: "NewExpression#5", input: `new a<T>()`},
|
||||
{title: "NewExpression#6", input: `new a.b<T>()`},
|
||||
{title: "NewExpression#7", input: `new a(b)`},
|
||||
{title: "NewExpression#8", input: `new a.b(c)`},
|
||||
{title: "NewExpression#9", input: `new a<T>(b)`},
|
||||
{title: "NewExpression#10", input: `new a.b<T>(c)`},
|
||||
{title: "NewExpression#11", input: `new a(b).c`},
|
||||
{title: "NewExpression#12", input: `new a<T>(b).c`},
|
||||
{title: "TaggedTemplateExpression#1", input: "tag``"},
|
||||
{title: "TaggedTemplateExpression#2", input: "tag<T>``"},
|
||||
{title: "TypeAssertionExpression#1", input: `<T>a`},
|
||||
{title: "FunctionExpression#1", input: `(function(){})`},
|
||||
{title: "FunctionExpression#2", input: `(function f(){})`},
|
||||
{title: "FunctionExpression#3", input: `(function*f(){})`},
|
||||
{title: "FunctionExpression#4", input: `(async function f(){})`},
|
||||
{title: "FunctionExpression#5", input: `(async function*f(){})`},
|
||||
{title: "FunctionExpression#6", input: `(function<T>(){})`},
|
||||
{title: "FunctionExpression#7", input: `(function(a){})`},
|
||||
{title: "FunctionExpression#8", input: `(function():T{})`},
|
||||
{title: "ArrowFunction#1", input: `a=>{}`},
|
||||
{title: "ArrowFunction#2", input: `()=>{}`},
|
||||
{title: "ArrowFunction#3", input: `(a)=>{}`},
|
||||
{title: "ArrowFunction#4", input: `<T>(a)=>{}`},
|
||||
{title: "ArrowFunction#5", input: `async a=>{}`},
|
||||
{title: "ArrowFunction#6", input: `async()=>{}`},
|
||||
{title: "ArrowFunction#7", input: `async<T>()=>{}`},
|
||||
{title: "ArrowFunction#8", input: `():T=>{}`},
|
||||
{title: "ArrowFunction#9", input: `()=>a`},
|
||||
{title: "DeleteExpression", input: `delete a`},
|
||||
{title: "TypeOfExpression", input: `typeof a`},
|
||||
{title: "VoidExpression", input: `void a`},
|
||||
{title: "AwaitExpression", input: `await a`},
|
||||
{title: "PrefixUnaryExpression#1", input: `+a`},
|
||||
{title: "PrefixUnaryExpression#2", input: `++a`},
|
||||
{title: "PrefixUnaryExpression#3", input: `+ +a`},
|
||||
{title: "PrefixUnaryExpression#4", input: `+ ++a`},
|
||||
{title: "PrefixUnaryExpression#5", input: `-a`},
|
||||
{title: "PrefixUnaryExpression#6", input: `--a`},
|
||||
{title: "PrefixUnaryExpression#7", input: `- -a`},
|
||||
{title: "PrefixUnaryExpression#8", input: `- --a`},
|
||||
{title: "PrefixUnaryExpression#9", input: `+-a`},
|
||||
{title: "PrefixUnaryExpression#10", input: `+--a`},
|
||||
{title: "PrefixUnaryExpression#11", input: `-+a`},
|
||||
{title: "PrefixUnaryExpression#12", input: `-++a`},
|
||||
{title: "PrefixUnaryExpression#13", input: `~a`},
|
||||
{title: "PrefixUnaryExpression#14", input: `!a`},
|
||||
{title: "PostfixUnaryExpression#1", input: `a++`},
|
||||
{title: "PostfixUnaryExpression#2", input: `a--`},
|
||||
{title: "BinaryExpression#1", input: `a,b`},
|
||||
{title: "BinaryExpression#2", input: `a+b`},
|
||||
{title: "BinaryExpression#3", input: `a**b`},
|
||||
{title: "BinaryExpression#4", input: `a instanceof b`},
|
||||
{title: "BinaryExpression#5", input: `a in b`},
|
||||
{title: "ConditionalExpression", input: `a?b:c`},
|
||||
{title: "TemplateExpression#1", input: "`a${b}c`"},
|
||||
{title: "TemplateExpression#2", input: "`a${b}c${d}e`"},
|
||||
{title: "YieldExpression#1", input: `(function*() { yield })`},
|
||||
{title: "YieldExpression#2", input: `(function*() { yield a })`},
|
||||
{title: "YieldExpression#3", input: `(function*() { yield*a })`},
|
||||
{title: "SpreadElement", input: `[...a]`},
|
||||
{title: "ClassExpression#1", input: `(class {})`},
|
||||
{title: "ClassExpression#2", input: `(class a {})`},
|
||||
{title: "ClassExpression#3", input: `(class<T>{})`},
|
||||
{title: "ClassExpression#4", input: `(class a<T>{})`},
|
||||
{title: "ClassExpression#5", input: `(class extends b {})`},
|
||||
{title: "ClassExpression#6", input: `(class a extends b {})`},
|
||||
{title: "ClassExpression#7", input: `(class implements b {})`},
|
||||
{title: "ClassExpression#8", input: `(class a implements b {})`},
|
||||
{title: "ClassExpression#9", input: `(class implements b, c {})`},
|
||||
{title: "ClassExpression#10", input: `(class a implements b, c {})`},
|
||||
{title: "ClassExpression#11", input: `(class extends b implements c, d {})`},
|
||||
{title: "ClassExpression#12", input: `(class a extends b implements c, d {})`},
|
||||
{title: "ClassExpression#13", input: `(@a class {})`},
|
||||
{title: "OmittedExpression", input: `[,]`},
|
||||
{title: "ExpressionWithTypeArguments", input: `a<T>`},
|
||||
{title: "AsExpression", input: `a as T`},
|
||||
{title: "SatisfiesExpression", input: `a satisfies T`},
|
||||
{title: "NonNullExpression", input: `a!`},
|
||||
{title: "MetaProperty#1", input: `new.target`},
|
||||
{title: "MetaProperty#2", input: `import.meta`},
|
||||
{title: "ArrayLiteralExpression#1", input: `[]`},
|
||||
{title: "ArrayLiteralExpression#2", input: `[a]`},
|
||||
{title: "ArrayLiteralExpression#3", input: `[a,]`},
|
||||
{title: "ArrayLiteralExpression#4", input: `[,a]`},
|
||||
{title: "ArrayLiteralExpression#5", input: `[...a]`},
|
||||
{title: "ObjectLiteralExpression#1", input: `({})`},
|
||||
{title: "ObjectLiteralExpression#2", input: `({a,})`},
|
||||
{title: "ShorthandPropertyAssignment", input: `({a})`},
|
||||
{title: "PropertyAssignment", input: `({a:b})`},
|
||||
{title: "SpreadAssignment", input: `({...a})`},
|
||||
{title: "Block", input: `{}`},
|
||||
{title: "VariableStatement#1", input: `var a`},
|
||||
{title: "VariableStatement#2", input: `let a`},
|
||||
{title: "VariableStatement#3", input: `const a = b`},
|
||||
{title: "VariableStatement#4", input: `using a = b`},
|
||||
{title: "VariableStatement#5", input: `await using a = b`},
|
||||
{title: "EmptyStatement", input: `;`},
|
||||
{title: "IfStatement#1", input: `if(a);`},
|
||||
{title: "IfStatement#2", input: `if(a);else;`},
|
||||
{title: "IfStatement#3", input: `if(a);else{}`},
|
||||
{title: "IfStatement#4", input: `if(a);else if(b);`},
|
||||
{title: "IfStatement#5", input: `if(a);else if(b) {}`},
|
||||
{title: "IfStatement#6", input: `if(a) {}`},
|
||||
{title: "IfStatement#7", input: `if(a) {} else;`},
|
||||
{title: "IfStatement#8", input: `if(a) {} else {}`},
|
||||
{title: "IfStatement#9", input: `if(a) {} else if(b);`},
|
||||
{title: "IfStatement#10", input: `if(a) {} else if(b){}`},
|
||||
{title: "DoStatement#1", input: `do;while(a);`},
|
||||
{title: "DoStatement#2", input: `do {} while(a);`},
|
||||
{title: "WhileStatement#1", input: `while(a);`},
|
||||
{title: "WhileStatement#2", input: `while(a) {}`},
|
||||
{title: "ForStatement#1", input: `for(;;);`},
|
||||
{title: "ForStatement#2", input: `for(a;;);`},
|
||||
{title: "ForStatement#3", input: `for(var a;;);`},
|
||||
{title: "ForStatement#4", input: `for(;a;);`},
|
||||
{title: "ForStatement#5", input: `for(;;a);`},
|
||||
{title: "ForStatement#6", input: `for(;;){}`},
|
||||
{title: "ForInStatement#1", input: `for(a in b);`},
|
||||
{title: "ForInStatement#2", input: `for(var a in b);`},
|
||||
{title: "ForInStatement#3", input: `for(a in b){}`},
|
||||
{title: "ForOfStatement#1", input: `for(a of b);`},
|
||||
{title: "ForOfStatement#2", input: `for(var a of b);`},
|
||||
{title: "ForOfStatement#3", input: `for(a of b){}`},
|
||||
{title: "ForOfStatement#4", input: `for await(a of b);`},
|
||||
{title: "ForOfStatement#5", input: `for await(var a of b);`},
|
||||
{title: "ForOfStatement#6", input: `for await(a of b){}`},
|
||||
{title: "ContinueStatement#1", input: `continue`},
|
||||
{title: "ContinueStatement#2", input: `continue a`},
|
||||
{title: "BreakStatement#1", input: `break`},
|
||||
{title: "BreakStatement#2", input: `break a`},
|
||||
{title: "ReturnStatement#1", input: `return`},
|
||||
{title: "ReturnStatement#2", input: `return a`},
|
||||
{title: "WithStatement#1", input: `with(a);`},
|
||||
{title: "WithStatement#2", input: `with(a){}`},
|
||||
{title: "SwitchStatement", input: `switch (a) {}`},
|
||||
{title: "CaseClause#1", input: `switch (a) {case b:}`},
|
||||
{title: "CaseClause#2", input: `switch (a) {case b:;}`},
|
||||
{title: "DefaultClause#1", input: `switch (a) {default:}`},
|
||||
{title: "DefaultClause#2", input: `switch (a) {default:;}`},
|
||||
{title: "LabeledStatement", input: `a:;`},
|
||||
{title: "ThrowStatement", input: `throw a`},
|
||||
{title: "TryStatement#1", input: `try {} catch {}`},
|
||||
{title: "TryStatement#2", input: `try {} finally {}`},
|
||||
{title: "TryStatement#3", input: `try {} catch {} finally {}`},
|
||||
{title: "DebuggerStatement", input: `debugger`},
|
||||
{title: "FunctionDeclaration#1", input: `export default function(){}`},
|
||||
{title: "FunctionDeclaration#2", input: `function f(){}`},
|
||||
{title: "FunctionDeclaration#3", input: `function*f(){}`},
|
||||
{title: "FunctionDeclaration#4", input: `async function f(){}`},
|
||||
{title: "FunctionDeclaration#5", input: `async function*f(){}`},
|
||||
{title: "FunctionDeclaration#6", input: `function f<T>(){}`},
|
||||
{title: "FunctionDeclaration#7", input: `function f(a){}`},
|
||||
{title: "FunctionDeclaration#8", input: `function f():T{}`},
|
||||
{title: "FunctionDeclaration#9", input: `function f();`},
|
||||
{title: "ClassDeclaration#1", input: `class a {}`},
|
||||
{title: "ClassDeclaration#2", input: `class a<T>{}`},
|
||||
{title: "ClassDeclaration#3", input: `class a extends b {}`},
|
||||
{title: "ClassDeclaration#4", input: `class a implements b {}`},
|
||||
{title: "ClassDeclaration#5", input: `class a implements b, c {}`},
|
||||
{title: "ClassDeclaration#6", input: `class a extends b implements c, d {}`},
|
||||
{title: "ClassDeclaration#7", input: `export default class {}`},
|
||||
{title: "ClassDeclaration#8", input: `export default class<T>{}`},
|
||||
{title: "ClassDeclaration#9", input: `export default class extends b {}`},
|
||||
{title: "ClassDeclaration#10", input: `export default class implements b {}`},
|
||||
{title: "ClassDeclaration#11", input: `export default class implements b, c {}`},
|
||||
{title: "ClassDeclaration#12", input: `export default class extends b implements c, d {}`},
|
||||
{title: "ClassDeclaration#13", input: `@a class b {}`},
|
||||
{title: "ClassDeclaration#14", input: `@a export class b {}`},
|
||||
{title: "ClassDeclaration#15", input: `export @a class b {}`},
|
||||
{title: "InterfaceDeclaration#1", input: `interface a {}`},
|
||||
{title: "InterfaceDeclaration#2", input: `interface a<T>{}`},
|
||||
{title: "InterfaceDeclaration#3", input: `interface a extends b {}`},
|
||||
{title: "InterfaceDeclaration#4", input: `interface a extends b, c {}`},
|
||||
{title: "TypeAliasDeclaration#1", input: `type a = b`},
|
||||
{title: "TypeAliasDeclaration#2", input: `type a<T> = b`},
|
||||
{title: "EnumDeclaration#1", input: `enum a{}`},
|
||||
{title: "EnumDeclaration#2", input: `enum a{b}`},
|
||||
{title: "EnumDeclaration#3", input: `enum a{b=c}`},
|
||||
{title: "ModuleDeclaration#1", input: `module a{}`},
|
||||
{title: "ModuleDeclaration#2", input: `module a.b{}`},
|
||||
{title: "ModuleDeclaration#3", input: `module "a";`},
|
||||
{title: "ModuleDeclaration#4", input: `module "a"{}`},
|
||||
{title: "ModuleDeclaration#5", input: `namespace a{}`},
|
||||
{title: "ModuleDeclaration#6", input: `namespace a.b{}`},
|
||||
{title: "ModuleDeclaration#7", input: `global;`},
|
||||
{title: "ModuleDeclaration#8", input: `global{}`},
|
||||
{title: "ImportEqualsDeclaration#1", input: `import a = b`},
|
||||
{title: "ImportEqualsDeclaration#2", input: `import a = b.c`},
|
||||
{title: "ImportEqualsDeclaration#3", input: `import a = require("b")`},
|
||||
{title: "ImportEqualsDeclaration#4", input: `export import a = b`},
|
||||
{title: "ImportEqualsDeclaration#5", input: `export import a = require("b")`},
|
||||
{title: "ImportEqualsDeclaration#6", input: `import type a = b`},
|
||||
{title: "ImportEqualsDeclaration#7", input: `import type a = b.c`},
|
||||
{title: "ImportEqualsDeclaration#8", input: `import type a = require("b")`},
|
||||
{title: "ImportDeclaration#1", input: `import "a"`},
|
||||
{title: "ImportDeclaration#2", input: `import a from "b"`},
|
||||
{title: "ImportDeclaration#3", input: `import type a from "b"`},
|
||||
{title: "ImportDeclaration#4", input: `import * as a from "b"`},
|
||||
{title: "ImportDeclaration#5", input: `import type * as a from "b"`},
|
||||
{title: "ImportDeclaration#6", input: `import {} from "b"`},
|
||||
{title: "ImportDeclaration#7", input: `import type {} from "b"`},
|
||||
{title: "ImportDeclaration#8", input: `import { a } from "b"`},
|
||||
{title: "ImportDeclaration#9", input: `import type { a } from "b"`},
|
||||
{title: "ImportDeclaration#8", input: `import { a as b } from "c"`},
|
||||
{title: "ImportDeclaration#9", input: `import type { a as b } from "c"`},
|
||||
{title: "ImportDeclaration#10", input: `import { "a" as b } from "c"`},
|
||||
{title: "ImportDeclaration#11", input: `import type { "a" as b } from "c"`},
|
||||
{title: "ImportDeclaration#12", input: `import a, {} from "b"`},
|
||||
{title: "ImportDeclaration#13", input: `import a, * as b from "c"`},
|
||||
{title: "ImportDeclaration#14", input: `import {} from "a" with {}`},
|
||||
{title: "ImportDeclaration#15", input: `import {} from "a" with { b: "c" }`},
|
||||
{title: "ImportDeclaration#16", input: `import {} from "a" with { "b": "c" }`},
|
||||
{title: "ExportAssignment#1", input: `export = a`},
|
||||
{title: "ExportAssignment#2", input: `export default a`},
|
||||
{title: "NamespaceExportDeclaration", input: `export as namespace a`},
|
||||
{title: "ExportDeclaration#1", input: `export * from "a"`},
|
||||
{title: "ExportDeclaration#2", input: `export type * from "a"`},
|
||||
{title: "ExportDeclaration#3", input: `export * as a from "b"`},
|
||||
{title: "ExportDeclaration#4", input: `export type * as a from "b"`},
|
||||
{title: "ExportDeclaration#5", input: `export { } from "a"`},
|
||||
{title: "ExportDeclaration#6", input: `export type { } from "a"`},
|
||||
{title: "ExportDeclaration#7", input: `export { a } from "b"`},
|
||||
{title: "ExportDeclaration#8", input: `export { type a } from "b"`},
|
||||
{title: "ExportDeclaration#9", input: `export type { a } from "b"`},
|
||||
{title: "ExportDeclaration#10", input: `export { a as b } from "c"`},
|
||||
{title: "ExportDeclaration#11", input: `export { type a as b } from "c"`},
|
||||
{title: "ExportDeclaration#12", input: `export type { a as b } from "c"`},
|
||||
{title: "ExportDeclaration#13", input: `export { a as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#14", input: `export { type a as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#15", input: `export type { a as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#16", input: `export { "a" } from "b"`},
|
||||
{title: "ExportDeclaration#17", input: `export { type "a" } from "b"`},
|
||||
{title: "ExportDeclaration#18", input: `export type { "a" } from "b"`},
|
||||
{title: "ExportDeclaration#19", input: `export { "a" as b } from "c"`},
|
||||
{title: "ExportDeclaration#20", input: `export { type "a" as b } from "c"`},
|
||||
{title: "ExportDeclaration#21", input: `export type { "a" as b } from "c"`},
|
||||
{title: "ExportDeclaration#22", input: `export { "a" as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#23", input: `export { type "a" as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#24", input: `export type { "a" as "b" } from "c"`},
|
||||
{title: "ExportDeclaration#25", input: `export { }`},
|
||||
{title: "ExportDeclaration#26", input: `export type { }`},
|
||||
{title: "ExportDeclaration#27", input: `export { a }`},
|
||||
{title: "ExportDeclaration#28", input: `export { type a }`},
|
||||
{title: "ExportDeclaration#29", input: `export type { a }`},
|
||||
{title: "ExportDeclaration#30", input: `export { a as b }`},
|
||||
{title: "ExportDeclaration#31", input: `export { type a as b }`},
|
||||
{title: "ExportDeclaration#32", input: `export type { a as b }`},
|
||||
{title: "ExportDeclaration#33", input: `export { a as "b" }`},
|
||||
{title: "ExportDeclaration#34", input: `export { type a as "b" }`},
|
||||
{title: "ExportDeclaration#35", input: `export type { a as "b" }`},
|
||||
{title: "ExportDeclaration#36", input: `export {} from "a" with {}`},
|
||||
{title: "ExportDeclaration#37", input: `export {} from "a" with { b: "c" }`},
|
||||
{title: "ExportDeclaration#38", input: `export {} from "a" with { "b": "c" }`},
|
||||
{title: "KeywordTypeNode#1", input: `type T = any`},
|
||||
{title: "KeywordTypeNode#2", input: `type T = unknown`},
|
||||
{title: "KeywordTypeNode#3", input: `type T = never`},
|
||||
{title: "KeywordTypeNode#4", input: `type T = void`},
|
||||
{title: "KeywordTypeNode#5", input: `type T = undefined`},
|
||||
{title: "KeywordTypeNode#6", input: `type T = null`},
|
||||
{title: "KeywordTypeNode#7", input: `type T = object`},
|
||||
{title: "KeywordTypeNode#8", input: `type T = string`},
|
||||
{title: "KeywordTypeNode#9", input: `type T = symbol`},
|
||||
{title: "KeywordTypeNode#10", input: `type T = number`},
|
||||
{title: "KeywordTypeNode#11", input: `type T = bigint`},
|
||||
{title: "KeywordTypeNode#12", input: `type T = boolean`},
|
||||
{title: "KeywordTypeNode#13", input: `type T = intrinsic`},
|
||||
{title: "TypePredicateNode#1", input: `function f(): asserts a`},
|
||||
{title: "TypePredicateNode#2", input: `function f(): asserts a is b`},
|
||||
{title: "TypePredicateNode#3", input: `function f(): asserts this`},
|
||||
{title: "TypePredicateNode#4", input: `function f(): asserts this is b`},
|
||||
{title: "TypeReferenceNode#1", input: `type T = a`},
|
||||
{title: "TypeReferenceNode#2", input: `type T = a.b`},
|
||||
{title: "TypeReferenceNode#3", input: `type T = a<U>`},
|
||||
{title: "TypeReferenceNode#4", input: `type T = a.b<U>`},
|
||||
{title: "FunctionTypeNode#1", input: `type T = () => a`},
|
||||
{title: "FunctionTypeNode#2", input: `type T = <T>() => a`},
|
||||
{title: "FunctionTypeNode#3", input: `type T = (a) => b`},
|
||||
{title: "ConstructorTypeNode#1", input: `type T = new () => a`},
|
||||
{title: "ConstructorTypeNode#2", input: `type T = new <T>() => a`},
|
||||
{title: "ConstructorTypeNode#3", input: `type T = new (a) => b`},
|
||||
{title: "ConstructorTypeNode#4", input: `type T = abstract new () => a`},
|
||||
{title: "TypeQueryNode#1", input: `type T = typeof a`},
|
||||
{title: "TypeQueryNode#2", input: `type T = typeof a.b`},
|
||||
{title: "TypeQueryNode#3", input: `type T = typeof a<U>`},
|
||||
{title: "TypeLiteralNode#1", input: `type T = {}`},
|
||||
{title: "TypeLiteralNode#2", input: `type T = {a}`},
|
||||
{title: "ArrayTypeNode", input: `type T = a[]`},
|
||||
{title: "TupleTypeNode#1", input: `type T = []`},
|
||||
{title: "TupleTypeNode#2", input: `type T = [a]`},
|
||||
{title: "TupleTypeNode#3", input: `type T = [a,]`},
|
||||
{title: "RestTypeNode", input: `type T = [...a]`},
|
||||
{title: "OptionalTypeNode", input: `type T = [a?]`},
|
||||
{title: "NamedTupleMember#1", input: `type T = [a: b]`},
|
||||
{title: "NamedTupleMember#2", input: `type T = [a?: b]`},
|
||||
{title: "NamedTupleMember#3", input: `type T = [...a: b]`},
|
||||
{title: "UnionTypeNode#1", input: `type T = a | b`},
|
||||
{title: "UnionTypeNode#2", input: `type T = a | b | c`},
|
||||
{title: "UnionTypeNode#3", input: `type T = | a | b`},
|
||||
{title: "IntersectionTypeNode#1", input: `type T = a & b`},
|
||||
{title: "IntersectionTypeNode#2", input: `type T = a & b & c`},
|
||||
{title: "IntersectionTypeNode#3", input: `type T = & a & b`},
|
||||
{title: "ConditionalTypeNode", input: `type T = a extends b ? c : d`},
|
||||
{title: "InferTypeNode#1", input: `type T = a extends infer b ? c : d`},
|
||||
{title: "InferTypeNode#2", input: `type T = a extends infer b extends c ? d : e`},
|
||||
{title: "ParenthesizedTypeNode", input: `type T = (U)`},
|
||||
{title: "ThisTypeNode", input: `type T = this`},
|
||||
{title: "TypeOperatorNode#1", input: `type T = keyof U`},
|
||||
{title: "TypeOperatorNode#2", input: `type T = readonly U[]`},
|
||||
{title: "TypeOperatorNode#3", input: `type T = unique symbol`},
|
||||
{title: "IndexedAccessTypeNode", input: `type T = a[b]`},
|
||||
{title: "MappedTypeNode#1", input: `type T = { [a in b]: c }`},
|
||||
{title: "MappedTypeNode#2", input: `type T = { [a in b as c]: d }`},
|
||||
{title: "MappedTypeNode#3", input: `type T = { readonly [a in b]: c }`},
|
||||
{title: "MappedTypeNode#4", input: `type T = { +readonly [a in b]: c }`},
|
||||
{title: "MappedTypeNode#5", input: `type T = { -readonly [a in b]: c }`},
|
||||
{title: "MappedTypeNode#6", input: `type T = { [a in b]?: c }`},
|
||||
{title: "MappedTypeNode#7", input: `type T = { [a in b]+?: c }`},
|
||||
{title: "MappedTypeNode#8", input: `type T = { [a in b]-?: c }`},
|
||||
{title: "MappedTypeNode#9", input: `type T = { [a in b]: c; d }`},
|
||||
{title: "LiteralTypeNode#1", input: `type T = null`},
|
||||
{title: "LiteralTypeNode#2", input: `type T = true`},
|
||||
{title: "LiteralTypeNode#3", input: `type T = false`},
|
||||
{title: "LiteralTypeNode#4", input: `type T = ""`},
|
||||
{title: "LiteralTypeNode#5", input: "type T = ''"},
|
||||
{title: "LiteralTypeNode#6", input: "type T = ``"},
|
||||
{title: "LiteralTypeNode#7", input: `type T = 0`},
|
||||
{title: "LiteralTypeNode#8", input: `type T = 0n`},
|
||||
{title: "LiteralTypeNode#9", input: `type T = -0`},
|
||||
{title: "LiteralTypeNode#10", input: `type T = -0n`},
|
||||
{title: "TemplateTypeNode#1", input: "type T = `a${b}c`"},
|
||||
{title: "TemplateTypeNode#2", input: "type T = `a${b}c${d}e`"},
|
||||
{title: "ImportTypeNode#1", input: `type T = import(a)`},
|
||||
{title: "ImportTypeNode#2", input: `type T = import(a).b`},
|
||||
{title: "ImportTypeNode#3", input: `type T = import(a).b<U>`},
|
||||
{title: "ImportTypeNode#4", input: `type T = typeof import(a)`},
|
||||
{title: "ImportTypeNode#5", input: `type T = typeof import(a).b`},
|
||||
{title: "ImportTypeNode#6", input: `type T = import(a, { with: { } })`},
|
||||
{title: "ImportTypeNode#6", input: `type T = import(a, { with: { b: "c" } })`},
|
||||
{title: "ImportTypeNode#7", input: `type T = import(a, { with: { "b": "c" } })`},
|
||||
{title: "PropertySignature#1", input: "interface I {a}"},
|
||||
{title: "PropertySignature#2", input: "interface I {readonly a}"},
|
||||
{title: "PropertySignature#3", input: "interface I {\"a\"}"},
|
||||
{title: "PropertySignature#4", input: "interface I {'a'}"},
|
||||
{title: "PropertySignature#5", input: "interface I {0}"},
|
||||
{title: "PropertySignature#6", input: "interface I {0n}"},
|
||||
{title: "PropertySignature#7", input: "interface I {[a]}"},
|
||||
{title: "PropertySignature#8", input: "interface I {a?}"},
|
||||
{title: "PropertySignature#9", input: "interface I {a: b}"},
|
||||
{title: "MethodSignature#1", input: "interface I {a()}"},
|
||||
{title: "MethodSignature#2", input: "interface I {\"a\"()}"},
|
||||
{title: "MethodSignature#3", input: "interface I {'a'()}"},
|
||||
{title: "MethodSignature#4", input: "interface I {0()}"},
|
||||
{title: "MethodSignature#5", input: "interface I {0n()}"},
|
||||
{title: "MethodSignature#6", input: "interface I {[a]()}"},
|
||||
{title: "MethodSignature#7", input: "interface I {a?()}"},
|
||||
{title: "MethodSignature#8", input: "interface I {a<T>()}"},
|
||||
{title: "MethodSignature#9", input: "interface I {a(): b}"},
|
||||
{title: "MethodSignature#10", input: "interface I {a(b): c}"},
|
||||
{title: "CallSignature#1", input: "interface I {()}"},
|
||||
{title: "CallSignature#2", input: "interface I {():a}"},
|
||||
{title: "CallSignature#3", input: "interface I {(p)}"},
|
||||
{title: "CallSignature#4", input: "interface I {<T>()}"},
|
||||
{title: "ConstructSignature#1", input: "interface I {new ()}"},
|
||||
{title: "ConstructSignature#2", input: "interface I {new ():a}"},
|
||||
{title: "ConstructSignature#3", input: "interface I {new (p)}"},
|
||||
{title: "ConstructSignature#4", input: "interface I {new <T>()}"},
|
||||
{title: "IndexSignatureDeclaration#1", input: "interface I {[a]}"},
|
||||
{title: "IndexSignatureDeclaration#2", input: "interface I {[a: b]}"},
|
||||
{title: "IndexSignatureDeclaration#3", input: "interface I {[a: b]: c}"},
|
||||
{title: "PropertyDeclaration#1", input: "class C {a}"},
|
||||
{title: "PropertyDeclaration#2", input: "class C {readonly a}"},
|
||||
{title: "PropertyDeclaration#3", input: "class C {static a}"},
|
||||
{title: "PropertyDeclaration#4", input: "class C {accessor a}"},
|
||||
{title: "PropertyDeclaration#5", input: "class C {\"a\"}"},
|
||||
{title: "PropertyDeclaration#6", input: "class C {'a'}"},
|
||||
{title: "PropertyDeclaration#7", input: "class C {0}"},
|
||||
{title: "PropertyDeclaration#8", input: "class C {0n}"},
|
||||
{title: "PropertyDeclaration#9", input: "class C {[a]}"},
|
||||
{title: "PropertyDeclaration#10", input: "class C {#a}"},
|
||||
{title: "PropertyDeclaration#11", input: "class C {a?}"},
|
||||
{title: "PropertyDeclaration#12", input: "class C {a!}"},
|
||||
{title: "PropertyDeclaration#13", input: "class C {a: b}"},
|
||||
{title: "PropertyDeclaration#14", input: "class C {a = b}"},
|
||||
{title: "PropertyDeclaration#15", input: "class C {@a b}"},
|
||||
{title: "MethodDeclaration#1", input: "class C {a()}"},
|
||||
{title: "MethodDeclaration#2", input: "class C {\"a\"()}"},
|
||||
{title: "MethodDeclaration#3", input: "class C {'a'()}"},
|
||||
{title: "MethodDeclaration#4", input: "class C {0()}"},
|
||||
{title: "MethodDeclaration#5", input: "class C {0n()}"},
|
||||
{title: "MethodDeclaration#6", input: "class C {[a]()}"},
|
||||
{title: "MethodDeclaration#7", input: "class C {#a()}"},
|
||||
{title: "MethodDeclaration#8", input: "class C {a?()}"},
|
||||
{title: "MethodDeclaration#9", input: "class C {a<T>()}"},
|
||||
{title: "MethodDeclaration#10", input: "class C {a(): b}"},
|
||||
{title: "MethodDeclaration#11", input: "class C {a(b): c}"},
|
||||
{title: "MethodDeclaration#12", input: "class C {a() {} }"},
|
||||
{title: "MethodDeclaration#13", input: "class C {@a b() {} }"},
|
||||
{title: "MethodDeclaration#14", input: "class C {static a() {} }"},
|
||||
{title: "MethodDeclaration#15", input: "class C {async a() {} }"},
|
||||
{title: "GetAccessorDeclaration#1", input: "class C {get a()}"},
|
||||
{title: "GetAccessorDeclaration#2", input: "class C {get \"a\"()}"},
|
||||
{title: "GetAccessorDeclaration#3", input: "class C {get 'a'()}"},
|
||||
{title: "GetAccessorDeclaration#4", input: "class C {get 0()}"},
|
||||
{title: "GetAccessorDeclaration#5", input: "class C {get 0n()}"},
|
||||
{title: "GetAccessorDeclaration#6", input: "class C {get [a]()}"},
|
||||
{title: "GetAccessorDeclaration#7", input: "class C {get #a()}"},
|
||||
{title: "GetAccessorDeclaration#8", input: "class C {get a(): b}"},
|
||||
{title: "GetAccessorDeclaration#9", input: "class C {get a(b): c}"},
|
||||
{title: "GetAccessorDeclaration#10", input: "class C {get a() {} }"},
|
||||
{title: "GetAccessorDeclaration#11", input: "class C {@a get b() {} }"},
|
||||
{title: "GetAccessorDeclaration#12", input: "class C {static get a() {} }"},
|
||||
{title: "SetAccessorDeclaration#1", input: "class C {set a()}"},
|
||||
{title: "SetAccessorDeclaration#2", input: "class C {set \"a\"()}"},
|
||||
{title: "SetAccessorDeclaration#3", input: "class C {set 'a'()}"},
|
||||
{title: "SetAccessorDeclaration#4", input: "class C {set 0()}"},
|
||||
{title: "SetAccessorDeclaration#5", input: "class C {set 0n()}"},
|
||||
{title: "SetAccessorDeclaration#6", input: "class C {set [a]()}"},
|
||||
{title: "SetAccessorDeclaration#7", input: "class C {set #a()}"},
|
||||
{title: "SetAccessorDeclaration#8", input: "class C {set a(): b}"},
|
||||
{title: "SetAccessorDeclaration#9", input: "class C {set a(b): c}"},
|
||||
{title: "SetAccessorDeclaration#10", input: "class C {set a() {} }"},
|
||||
{title: "SetAccessorDeclaration#11", input: "class C {@a set b() {} }"},
|
||||
{title: "SetAccessorDeclaration#12", input: "class C {static set a() {} }"},
|
||||
{title: "ConstructorDeclaration#1", input: "class C {constructor()}"},
|
||||
{title: "ConstructorDeclaration#2", input: "class C {constructor(): b}"},
|
||||
{title: "ConstructorDeclaration#3", input: "class C {constructor(b): c}"},
|
||||
{title: "ConstructorDeclaration#4", input: "class C {constructor() {} }"},
|
||||
{title: "ConstructorDeclaration#5", input: "class C {@a constructor() {} }"},
|
||||
{title: "ConstructorDeclaration#6", input: "class C {private constructor() {} }"},
|
||||
{title: "ClassStaticBlockDeclaration", input: "class C {static { }}"},
|
||||
{title: "SemicolonClassElement#1", input: "class C {;}"},
|
||||
{title: "ParameterDeclaration#1", input: "function f(a)"},
|
||||
{title: "ParameterDeclaration#2", input: "function f(a: b)"},
|
||||
{title: "ParameterDeclaration#3", input: "function f(a = b)"},
|
||||
{title: "ParameterDeclaration#4", input: "function f(a?)"},
|
||||
{title: "ParameterDeclaration#5", input: "function f(...a)"},
|
||||
{title: "ParameterDeclaration#6", input: "function f(this)"},
|
||||
{title: "ParameterDeclaration#7", input: "function f(a,)"},
|
||||
{title: "ObjectBindingPattern#1", input: "function f({})"},
|
||||
{title: "ObjectBindingPattern#2", input: "function f({a})"},
|
||||
{title: "ObjectBindingPattern#3", input: "function f({a = b})"},
|
||||
{title: "ObjectBindingPattern#4", input: "function f({a: b})"},
|
||||
{title: "ObjectBindingPattern#5", input: "function f({a: b = c})"},
|
||||
{title: "ObjectBindingPattern#6", input: "function f({\"a\": b})"},
|
||||
{title: "ObjectBindingPattern#7", input: "function f({'a': b})"},
|
||||
{title: "ObjectBindingPattern#8", input: "function f({0: b})"},
|
||||
{title: "ObjectBindingPattern#9", input: "function f({[a]: b})"},
|
||||
{title: "ObjectBindingPattern#10", input: "function f({...a})"},
|
||||
{title: "ObjectBindingPattern#11", input: "function f({a: {}})"},
|
||||
{title: "ObjectBindingPattern#12", input: "function f({a: []})"},
|
||||
{title: "ArrayBindingPattern#1", input: "function f([])"},
|
||||
{title: "ArrayBindingPattern#2", input: "function f([,])"},
|
||||
{title: "ArrayBindingPattern#3", input: "function f([a])"},
|
||||
{title: "ArrayBindingPattern#4", input: "function f([a, b])"},
|
||||
{title: "ArrayBindingPattern#5", input: "function f([a, , b])"},
|
||||
{title: "ArrayBindingPattern#6", input: "function f([a = b])"},
|
||||
{title: "ArrayBindingPattern#7", input: "function f([...a])"},
|
||||
{title: "ArrayBindingPattern#8", input: "function f([{}])"},
|
||||
{title: "ArrayBindingPattern#9", input: "function f([[]])"},
|
||||
{title: "TypeParameterDeclaration#1", input: "function f<T>();"},
|
||||
{title: "TypeParameterDeclaration#2", input: "function f<in T>();"},
|
||||
{title: "TypeParameterDeclaration#3", input: "function f<T extends U>();"},
|
||||
{title: "TypeParameterDeclaration#4", input: "function f<T = U>();"},
|
||||
{title: "TypeParameterDeclaration#5", input: "function f<T extends U = V>();"},
|
||||
{title: "TypeParameterDeclaration#6", input: "function f<T, U>();"},
|
||||
{title: "TypeParameterDeclaration#7", input: "function f<T,>();"},
|
||||
{title: "JsxElement1", input: "<a></a>"},
|
||||
{title: "JsxElement2", input: "<this></this>"},
|
||||
{title: "JsxElement3", input: "<a:b></a:b>"},
|
||||
{title: "JsxElement4", input: "<a.b></a.b>"},
|
||||
{title: "JsxElement5", input: "<a<b>></a>"},
|
||||
{title: "JsxElement6", input: "<a b></a>"},
|
||||
{title: "JsxElement7", input: "<a>b</a>"},
|
||||
{title: "JsxElement8", input: "<a>{b}</a>"},
|
||||
{title: "JsxElement9", input: "<a><b></b></a>"},
|
||||
{title: "JsxElement10", input: "<a><b /></a>"},
|
||||
{title: "JsxElement11", input: "<a><></></a>"},
|
||||
{title: "JsxSelfClosingElement1", input: "<a />"},
|
||||
{title: "JsxSelfClosingElement2", input: "<this />"},
|
||||
{title: "JsxSelfClosingElement3", input: "<a:b />"},
|
||||
{title: "JsxSelfClosingElement4", input: "<a.b />"},
|
||||
{title: "JsxSelfClosingElement5", input: "<a<b> />"},
|
||||
{title: "JsxSelfClosingElement6", input: "<a b/>"},
|
||||
{title: "JsxFragment1", input: "<></>"},
|
||||
{title: "JsxFragment2", input: "<>b</>"},
|
||||
{title: "JsxFragment3", input: "<>{b}</>"},
|
||||
{title: "JsxFragment4", input: "<><b></b></>"},
|
||||
{title: "JsxFragment5", input: "<><b /></>"},
|
||||
{title: "JsxFragment6", input: "<><></></>"},
|
||||
{title: "JsxAttribute1", input: "<a b/>"},
|
||||
{title: "JsxAttribute2", input: "<a b:c/>"},
|
||||
{title: "JsxAttribute3", input: "<a b=\"c\"/>"},
|
||||
{title: "JsxAttribute4", input: "<a b='c'/>"},
|
||||
{title: "JsxAttribute5", input: "<a b={c}/>"},
|
||||
{title: "JsxAttribute6", input: "<a b=<c></c>/>"},
|
||||
{title: "JsxAttribute7", input: "<a b=<c />/>"},
|
||||
{title: "JsxAttribute8", input: "<a b=<></>/>"},
|
||||
{title: "JsxSpreadAttribute", input: "<a {...b}/>"},
|
||||
}
|
||||
for _, rec := range data {
|
||||
t.Run("Clone "+rec.title, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
factory := &ast.NodeFactory{}
|
||||
file := parsetestutil.ParseTypeScript(rec.input, false).AsNode()
|
||||
clone := factory.DeepCloneNode(file.AsNode()).AsNode()
|
||||
|
||||
work := []NodeComparisonWorkItem{{file, clone}}
|
||||
|
||||
for len(work) > 0 {
|
||||
nextWork := []NodeComparisonWorkItem{}
|
||||
for _, item := range work {
|
||||
assert.Assert(t, item.original != item.copy)
|
||||
originalChildren := getChildren(item.original)
|
||||
copyChildren := getChildren(item.copy)
|
||||
assert.Equal(t, len(originalChildren), len(copyChildren))
|
||||
for i, child := range originalChildren {
|
||||
nextWork = append(nextWork, NodeComparisonWorkItem{child, copyChildren[i]})
|
||||
}
|
||||
}
|
||||
work = nextWork
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
362
tools/tsgo/internal/ast/diagnostic.go
Normal file
362
tools/tsgo/internal/ast/diagnostic.go
Normal file
@@ -0,0 +1,362 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/collections"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/diagnostics"
|
||||
"github.com/microsoft/typescript-go/internal/locale"
|
||||
)
|
||||
|
||||
// RepopulateDiagnosticKind indicates the kind of repopulation for a diagnostic chain entry.
|
||||
type RepopulateDiagnosticKind int
|
||||
|
||||
const (
|
||||
RepopulateModeMismatch RepopulateDiagnosticKind = 1
|
||||
RepopulateModuleNotFound RepopulateDiagnosticKind = 2
|
||||
)
|
||||
|
||||
// RepopulateDiagnosticInfo stores information needed to recompute a diagnostic chain entry
|
||||
// during incremental builds when the program state may have changed.
|
||||
type RepopulateDiagnosticInfo struct {
|
||||
Kind RepopulateDiagnosticKind
|
||||
ModuleReference string
|
||||
Mode core.ResolutionMode
|
||||
PackageName string
|
||||
}
|
||||
|
||||
// Diagnostic
|
||||
|
||||
type Diagnostic struct {
|
||||
file *SourceFile
|
||||
loc core.TextRange
|
||||
code int32
|
||||
category diagnostics.Category
|
||||
// Original message; may be nil.
|
||||
message *diagnostics.Message
|
||||
messageKey diagnostics.Key
|
||||
messageArgs []string
|
||||
messageChain []*Diagnostic
|
||||
relatedInformation []*Diagnostic
|
||||
reportsUnnecessary bool
|
||||
reportsDeprecated bool
|
||||
skippedOnNoEmit bool
|
||||
repopulateInfo *RepopulateDiagnosticInfo
|
||||
}
|
||||
|
||||
func (d *Diagnostic) File() *SourceFile { return d.file }
|
||||
func (d *Diagnostic) Pos() int { return d.loc.Pos() }
|
||||
func (d *Diagnostic) End() int { return d.loc.End() }
|
||||
func (d *Diagnostic) Len() int { return d.loc.Len() }
|
||||
func (d *Diagnostic) Loc() core.TextRange { return d.loc }
|
||||
func (d *Diagnostic) Code() int32 { return d.code }
|
||||
func (d *Diagnostic) Category() diagnostics.Category { return d.category }
|
||||
func (d *Diagnostic) MessageKey() diagnostics.Key { return d.messageKey }
|
||||
func (d *Diagnostic) MessageArgs() []string { return d.messageArgs }
|
||||
func (d *Diagnostic) MessageChain() []*Diagnostic { return d.messageChain }
|
||||
func (d *Diagnostic) RelatedInformation() []*Diagnostic { return d.relatedInformation }
|
||||
func (d *Diagnostic) ReportsUnnecessary() bool { return d.reportsUnnecessary }
|
||||
func (d *Diagnostic) ReportsDeprecated() bool { return d.reportsDeprecated }
|
||||
func (d *Diagnostic) SkippedOnNoEmit() bool { return d.skippedOnNoEmit }
|
||||
func (d *Diagnostic) RepopulateInfo() *RepopulateDiagnosticInfo { return d.repopulateInfo }
|
||||
|
||||
func (d *Diagnostic) SetFile(file *SourceFile) { d.file = file }
|
||||
func (d *Diagnostic) SetLocation(loc core.TextRange) { d.loc = loc }
|
||||
func (d *Diagnostic) SetCategory(category diagnostics.Category) { d.category = category }
|
||||
func (d *Diagnostic) SetSkippedOnNoEmit() { d.skippedOnNoEmit = true }
|
||||
func (d *Diagnostic) SetRepopulateInfo(info *RepopulateDiagnosticInfo) { d.repopulateInfo = info }
|
||||
|
||||
func (d *Diagnostic) SetMessageChain(messageChain []*Diagnostic) *Diagnostic {
|
||||
d.messageChain = messageChain
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Diagnostic) AddMessageChain(messageChain *Diagnostic) *Diagnostic {
|
||||
if messageChain != nil {
|
||||
d.messageChain = append(d.messageChain, messageChain)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Diagnostic) SetRelatedInfo(relatedInformation []*Diagnostic) *Diagnostic {
|
||||
d.relatedInformation = relatedInformation
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Diagnostic) AddRelatedInfo(relatedInformation *Diagnostic) *Diagnostic {
|
||||
if relatedInformation != nil {
|
||||
d.relatedInformation = append(d.relatedInformation, relatedInformation)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Diagnostic) Clone() *Diagnostic {
|
||||
result := *d
|
||||
return &result
|
||||
}
|
||||
|
||||
func (d *Diagnostic) Localize(locale locale.Locale) string {
|
||||
return diagnostics.Localize(locale, d.message, d.messageKey, d.messageArgs...)
|
||||
}
|
||||
|
||||
// For debugging only.
|
||||
func (d *Diagnostic) String() string {
|
||||
return diagnostics.Localize(locale.Default, d.message, d.messageKey, d.messageArgs...)
|
||||
}
|
||||
|
||||
func NewDiagnosticFromSerialized(
|
||||
file *SourceFile,
|
||||
loc core.TextRange,
|
||||
code int32,
|
||||
category diagnostics.Category,
|
||||
messageKey diagnostics.Key,
|
||||
messageArgs []string,
|
||||
messageChain []*Diagnostic,
|
||||
relatedInformation []*Diagnostic,
|
||||
reportsUnnecessary bool,
|
||||
reportsDeprecated bool,
|
||||
skippedOnNoEmit bool,
|
||||
) *Diagnostic {
|
||||
return &Diagnostic{
|
||||
file: file,
|
||||
loc: loc,
|
||||
code: code,
|
||||
category: category,
|
||||
messageKey: messageKey,
|
||||
messageArgs: messageArgs,
|
||||
messageChain: messageChain,
|
||||
relatedInformation: relatedInformation,
|
||||
reportsUnnecessary: reportsUnnecessary,
|
||||
reportsDeprecated: reportsDeprecated,
|
||||
skippedOnNoEmit: skippedOnNoEmit,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDiagnostic(file *SourceFile, loc core.TextRange, message *diagnostics.Message, args ...any) *Diagnostic {
|
||||
return &Diagnostic{
|
||||
file: file,
|
||||
loc: loc,
|
||||
code: message.Code(),
|
||||
category: message.Category(),
|
||||
message: message,
|
||||
messageKey: message.Key(),
|
||||
messageArgs: diagnostics.StringifyArgs(args),
|
||||
reportsUnnecessary: message.ReportsUnnecessary(),
|
||||
reportsDeprecated: message.ReportsDeprecated(),
|
||||
}
|
||||
}
|
||||
|
||||
func NewDiagnosticChain(chain *Diagnostic, message *diagnostics.Message, args ...any) *Diagnostic {
|
||||
if chain != nil {
|
||||
return NewDiagnostic(chain.file, chain.loc, message, args...).AddMessageChain(chain).SetRelatedInfo(chain.relatedInformation)
|
||||
}
|
||||
return NewDiagnostic(nil, core.TextRange{}, message, args...)
|
||||
}
|
||||
|
||||
func NewCompilerDiagnostic(message *diagnostics.Message, args ...any) *Diagnostic {
|
||||
return NewDiagnostic(nil, core.UndefinedTextRange(), message, args...)
|
||||
}
|
||||
|
||||
type DiagnosticsCollection struct {
|
||||
mu sync.Mutex
|
||||
count int
|
||||
fileDiagnostics map[string][]*Diagnostic
|
||||
fileDiagnosticsSorted collections.Set[string]
|
||||
nonFileDiagnostics []*Diagnostic
|
||||
nonFileDiagnosticsSorted bool
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) Add(diagnostic *Diagnostic) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.count++
|
||||
|
||||
if diagnostic.File() != nil {
|
||||
fileName := diagnostic.File().FileName()
|
||||
if c.fileDiagnostics == nil {
|
||||
c.fileDiagnostics = make(map[string][]*Diagnostic)
|
||||
}
|
||||
c.fileDiagnostics[fileName] = append(c.fileDiagnostics[fileName], diagnostic)
|
||||
c.fileDiagnosticsSorted.Delete(fileName)
|
||||
} else {
|
||||
c.nonFileDiagnostics = append(c.nonFileDiagnostics, diagnostic)
|
||||
c.nonFileDiagnosticsSorted = false
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) Lookup(diagnostic *Diagnostic) *Diagnostic {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
var diagnostics []*Diagnostic
|
||||
if diagnostic.File() != nil {
|
||||
diagnostics = c.getDiagnosticsForFileLocked(diagnostic.File().FileName())
|
||||
} else {
|
||||
diagnostics = c.getGlobalDiagnosticsLocked()
|
||||
}
|
||||
if i, ok := slices.BinarySearchFunc(diagnostics, diagnostic, CompareDiagnostics); ok {
|
||||
return diagnostics[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) GetGlobalDiagnostics() []*Diagnostic {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
return c.getGlobalDiagnosticsLocked()
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) getGlobalDiagnosticsLocked() []*Diagnostic {
|
||||
if !c.nonFileDiagnosticsSorted {
|
||||
slices.SortStableFunc(c.nonFileDiagnostics, CompareDiagnostics)
|
||||
c.nonFileDiagnosticsSorted = true
|
||||
}
|
||||
return slices.Clone(c.nonFileDiagnostics)
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) GetDiagnosticsForFile(fileName string) []*Diagnostic {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
return c.getDiagnosticsForFileLocked(fileName)
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) getDiagnosticsForFileLocked(fileName string) []*Diagnostic {
|
||||
if !c.fileDiagnosticsSorted.Has(fileName) {
|
||||
slices.SortStableFunc(c.fileDiagnostics[fileName], CompareDiagnostics)
|
||||
c.fileDiagnosticsSorted.Add(fileName)
|
||||
}
|
||||
return slices.Clone(c.fileDiagnostics[fileName])
|
||||
}
|
||||
|
||||
func (c *DiagnosticsCollection) GetDiagnostics() []*Diagnostic {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
diagnostics := make([]*Diagnostic, 0, c.count)
|
||||
diagnostics = append(diagnostics, c.nonFileDiagnostics...)
|
||||
for _, diags := range c.fileDiagnostics {
|
||||
diagnostics = append(diagnostics, diags...)
|
||||
}
|
||||
slices.SortFunc(diagnostics, CompareDiagnostics)
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
func getDiagnosticPath(d *Diagnostic) string {
|
||||
if d.File() != nil {
|
||||
return d.File().FileName()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func EqualDiagnostics(d1, d2 *Diagnostic) bool {
|
||||
if d1 == d2 {
|
||||
return true
|
||||
}
|
||||
return EqualDiagnosticsNoRelatedInfo(d1, d2) &&
|
||||
slices.EqualFunc(d1.RelatedInformation(), d2.RelatedInformation(), EqualDiagnostics)
|
||||
}
|
||||
|
||||
func EqualDiagnosticsNoRelatedInfo(d1, d2 *Diagnostic) bool {
|
||||
if d1 == d2 {
|
||||
return true
|
||||
}
|
||||
return getDiagnosticPath(d1) == getDiagnosticPath(d2) &&
|
||||
d1.Loc() == d2.Loc() &&
|
||||
d1.Code() == d2.Code() &&
|
||||
slices.Equal(d1.MessageArgs(), d2.MessageArgs()) &&
|
||||
slices.EqualFunc(d1.MessageChain(), d2.MessageChain(), equalMessageChain)
|
||||
}
|
||||
|
||||
func equalMessageChain(c1, c2 *Diagnostic) bool {
|
||||
if c1 == c2 {
|
||||
return true
|
||||
}
|
||||
return c1.Code() == c2.Code() &&
|
||||
slices.Equal(c1.MessageArgs(), c2.MessageArgs()) &&
|
||||
slices.EqualFunc(c1.MessageChain(), c2.MessageChain(), equalMessageChain)
|
||||
}
|
||||
|
||||
func compareMessageChainSize(c1, c2 []*Diagnostic) int {
|
||||
c := len(c2) - len(c1)
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
for i := range c1 {
|
||||
c = compareMessageChainSize(c1[i].MessageChain(), c2[i].MessageChain())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func compareMessageChainContent(c1, c2 []*Diagnostic) int {
|
||||
for i := range c1 {
|
||||
c := slices.Compare(c1[i].MessageArgs(), c2[i].MessageArgs())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
if c1[i].MessageChain() != nil {
|
||||
c = compareMessageChainContent(c1[i].MessageChain(), c2[i].MessageChain())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func compareRelatedInfo(r1, r2 []*Diagnostic) int {
|
||||
c := len(r2) - len(r1)
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
for i := range r1 {
|
||||
c = CompareDiagnostics(r1[i], r2[i])
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func CompareDiagnostics(d1, d2 *Diagnostic) int {
|
||||
if d1 == d2 {
|
||||
return 0
|
||||
}
|
||||
c := strings.Compare(getDiagnosticPath(d1), getDiagnosticPath(d2))
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = d1.Loc().Pos() - d2.Loc().Pos()
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = d1.Loc().End() - d2.Loc().End()
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = int(d1.Code()) - int(d2.Code())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = slices.Compare(d1.MessageArgs(), d2.MessageArgs())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = compareMessageChainSize(d1.MessageChain(), d2.MessageChain())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
c = compareMessageChainContent(d1.MessageChain(), d2.MessageChain())
|
||||
if c != 0 {
|
||||
return c
|
||||
}
|
||||
return compareRelatedInfo(d1.RelatedInformation(), d2.RelatedInformation())
|
||||
}
|
||||
75
tools/tsgo/internal/ast/flow.go
Normal file
75
tools/tsgo/internal/ast/flow.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package ast
|
||||
|
||||
// FlowFlags
|
||||
|
||||
type FlowFlags uint32
|
||||
|
||||
const (
|
||||
FlowFlagsUnreachable FlowFlags = 1 << 0 // Unreachable code
|
||||
FlowFlagsStart FlowFlags = 1 << 1 // Start of flow graph
|
||||
FlowFlagsBranchLabel FlowFlags = 1 << 2 // Non-looping junction
|
||||
FlowFlagsLoopLabel FlowFlags = 1 << 3 // Looping junction
|
||||
FlowFlagsAssignment FlowFlags = 1 << 4 // Assignment
|
||||
FlowFlagsTrueCondition FlowFlags = 1 << 5 // Condition known to be true
|
||||
FlowFlagsFalseCondition FlowFlags = 1 << 6 // Condition known to be false
|
||||
FlowFlagsSwitchClause FlowFlags = 1 << 7 // Switch statement clause
|
||||
FlowFlagsArrayMutation FlowFlags = 1 << 8 // Potential array mutation
|
||||
FlowFlagsCall FlowFlags = 1 << 9 // Potential assertion call
|
||||
FlowFlagsReduceLabel FlowFlags = 1 << 10 // Temporarily reduce antecedents of label
|
||||
FlowFlagsReferenced FlowFlags = 1 << 11 // Referenced as antecedent once
|
||||
FlowFlagsShared FlowFlags = 1 << 12 // Referenced as antecedent more than once
|
||||
FlowFlagsLabel = FlowFlagsBranchLabel | FlowFlagsLoopLabel
|
||||
FlowFlagsCondition = FlowFlagsTrueCondition | FlowFlagsFalseCondition
|
||||
)
|
||||
|
||||
// FlowNode
|
||||
|
||||
type FlowNode struct {
|
||||
Flags FlowFlags
|
||||
Node *Node // Associated AST node
|
||||
Antecedent *FlowNode // Antecedent for all but FlowLabel
|
||||
Antecedents *FlowList // Linked list of antecedents for FlowLabel
|
||||
}
|
||||
|
||||
type FlowList struct {
|
||||
Flow *FlowNode
|
||||
Next *FlowList
|
||||
}
|
||||
|
||||
type FlowLabel = FlowNode
|
||||
|
||||
// FlowSwitchClauseData (synthetic AST node for FlowFlagsSwitchClause)
|
||||
|
||||
type FlowSwitchClauseData struct {
|
||||
NodeBase
|
||||
SwitchStatement *Node
|
||||
ClauseStart int32 // Start index of case/default clause range
|
||||
ClauseEnd int32 // End index of case/default clause range
|
||||
}
|
||||
|
||||
func NewFlowSwitchClauseData(switchStatement *Node, clauseStart int, clauseEnd int) *Node {
|
||||
node := &FlowSwitchClauseData{}
|
||||
node.SwitchStatement = switchStatement
|
||||
node.ClauseStart = int32(clauseStart)
|
||||
node.ClauseEnd = int32(clauseEnd)
|
||||
return newNode(KindUnknown, node, NodeFactoryHooks{})
|
||||
}
|
||||
|
||||
func (node *FlowSwitchClauseData) IsEmpty() bool {
|
||||
return node.ClauseStart == node.ClauseEnd
|
||||
}
|
||||
|
||||
// FlowReduceLabelData (synthetic AST node for FlowFlagsReduceLabel)
|
||||
|
||||
type FlowReduceLabelData struct {
|
||||
NodeBase
|
||||
Target *FlowLabel // Target label
|
||||
Antecedents *FlowList // Temporary antecedent list
|
||||
}
|
||||
|
||||
func NewFlowReduceLabelData(target *FlowLabel, antecedents *FlowList) *Node {
|
||||
node := &FlowReduceLabelData{}
|
||||
node.Target = target
|
||||
node.Antecedents = antecedents
|
||||
return newNode(KindUnknown, node, NodeFactoryHooks{})
|
||||
}
|
||||
37
tools/tsgo/internal/ast/functionflags.go
Normal file
37
tools/tsgo/internal/ast/functionflags.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package ast
|
||||
|
||||
type FunctionFlags uint32
|
||||
|
||||
const (
|
||||
FunctionFlagsNormal FunctionFlags = 0
|
||||
FunctionFlagsGenerator FunctionFlags = 1 << 0
|
||||
FunctionFlagsAsync FunctionFlags = 1 << 1
|
||||
FunctionFlagsInvalid FunctionFlags = 1 << 2
|
||||
FunctionFlagsAsyncGenerator FunctionFlags = FunctionFlagsAsync | FunctionFlagsGenerator
|
||||
)
|
||||
|
||||
func GetFunctionFlags(node *Node) FunctionFlags {
|
||||
if node == nil {
|
||||
return FunctionFlagsInvalid
|
||||
}
|
||||
data := node.BodyData()
|
||||
if data == nil {
|
||||
return FunctionFlagsInvalid
|
||||
}
|
||||
flags := FunctionFlagsNormal
|
||||
switch node.Kind {
|
||||
case KindFunctionDeclaration, KindFunctionExpression, KindMethodDeclaration:
|
||||
if data.AsteriskToken != nil {
|
||||
flags |= FunctionFlagsGenerator
|
||||
}
|
||||
fallthrough
|
||||
case KindArrowFunction:
|
||||
if HasSyntacticModifier(node, ModifierFlagsAsync) {
|
||||
flags |= FunctionFlagsAsync
|
||||
}
|
||||
}
|
||||
if data.Body == nil {
|
||||
flags |= FunctionFlagsInvalid
|
||||
}
|
||||
return flags
|
||||
}
|
||||
6
tools/tsgo/internal/ast/ids.go
Normal file
6
tools/tsgo/internal/ast/ids.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package ast
|
||||
|
||||
type (
|
||||
NodeId uint64
|
||||
SymbolId uint64
|
||||
)
|
||||
463
tools/tsgo/internal/ast/kind_generated.go
Normal file
463
tools/tsgo/internal/ast/kind_generated.go
Normal file
@@ -0,0 +1,463 @@
|
||||
// Code generated by _scripts/generate-go-ast.ts. DO NOT EDIT.
|
||||
|
||||
package ast
|
||||
|
||||
//go:generate go tool golang.org/x/tools/cmd/stringer -type=Kind -output=kind_stringer_generated.go
|
||||
//go:generate npx dprint fmt kind_stringer_generated.go
|
||||
|
||||
type Kind int16
|
||||
|
||||
const (
|
||||
KindUnknown Kind = iota
|
||||
KindEndOfFile
|
||||
KindSingleLineCommentTrivia
|
||||
KindMultiLineCommentTrivia
|
||||
KindNewLineTrivia
|
||||
KindWhitespaceTrivia
|
||||
KindConflictMarkerTrivia
|
||||
KindNonTextFileMarkerTrivia
|
||||
KindNumericLiteral
|
||||
KindBigIntLiteral
|
||||
KindStringLiteral
|
||||
KindJsxText
|
||||
KindJsxTextAllWhiteSpaces
|
||||
KindRegularExpressionLiteral
|
||||
KindNoSubstitutionTemplateLiteral
|
||||
// Pseudo-literals
|
||||
KindTemplateHead
|
||||
KindTemplateMiddle
|
||||
KindTemplateTail
|
||||
// Punctuation
|
||||
KindOpenBraceToken
|
||||
KindCloseBraceToken
|
||||
KindOpenParenToken
|
||||
KindCloseParenToken
|
||||
KindOpenBracketToken
|
||||
KindCloseBracketToken
|
||||
KindDotToken
|
||||
KindDotDotDotToken
|
||||
KindSemicolonToken
|
||||
KindCommaToken
|
||||
KindQuestionDotToken
|
||||
KindLessThanToken
|
||||
KindLessThanSlashToken
|
||||
KindGreaterThanToken
|
||||
KindLessThanEqualsToken
|
||||
KindGreaterThanEqualsToken
|
||||
KindEqualsEqualsToken
|
||||
KindExclamationEqualsToken
|
||||
KindEqualsEqualsEqualsToken
|
||||
KindExclamationEqualsEqualsToken
|
||||
KindEqualsGreaterThanToken
|
||||
KindPlusToken
|
||||
KindMinusToken
|
||||
KindAsteriskToken
|
||||
KindAsteriskAsteriskToken
|
||||
KindSlashToken
|
||||
KindPercentToken
|
||||
KindPlusPlusToken
|
||||
KindMinusMinusToken
|
||||
KindLessThanLessThanToken
|
||||
KindGreaterThanGreaterThanToken
|
||||
KindGreaterThanGreaterThanGreaterThanToken
|
||||
KindAmpersandToken
|
||||
KindBarToken
|
||||
KindCaretToken
|
||||
KindExclamationToken
|
||||
KindTildeToken
|
||||
KindAmpersandAmpersandToken
|
||||
KindBarBarToken
|
||||
KindQuestionToken
|
||||
KindColonToken
|
||||
KindAtToken
|
||||
KindQuestionQuestionToken
|
||||
// Only the JSDoc scanner produces BacktickToken. The normal scanner produces NoSubstitutionTemplateLiteral and related kinds.
|
||||
KindBacktickToken
|
||||
// Only the JSDoc scanner produces HashToken. The normal scanner produces PrivateIdentifier.
|
||||
KindHashToken
|
||||
// Assignments
|
||||
KindEqualsToken
|
||||
KindPlusEqualsToken
|
||||
KindMinusEqualsToken
|
||||
KindAsteriskEqualsToken
|
||||
KindAsteriskAsteriskEqualsToken
|
||||
KindSlashEqualsToken
|
||||
KindPercentEqualsToken
|
||||
KindLessThanLessThanEqualsToken
|
||||
KindGreaterThanGreaterThanEqualsToken
|
||||
KindGreaterThanGreaterThanGreaterThanEqualsToken
|
||||
KindAmpersandEqualsToken
|
||||
KindBarEqualsToken
|
||||
KindBarBarEqualsToken
|
||||
KindAmpersandAmpersandEqualsToken
|
||||
KindQuestionQuestionEqualsToken
|
||||
KindCaretEqualsToken
|
||||
// Identifiers and PrivateIdentifier
|
||||
KindIdentifier
|
||||
KindPrivateIdentifier
|
||||
KindJSDocCommentTextToken
|
||||
// Reserved words
|
||||
KindBreakKeyword
|
||||
KindCaseKeyword
|
||||
KindCatchKeyword
|
||||
KindClassKeyword
|
||||
KindConstKeyword
|
||||
KindContinueKeyword
|
||||
KindDebuggerKeyword
|
||||
KindDefaultKeyword
|
||||
KindDeleteKeyword
|
||||
KindDoKeyword
|
||||
KindElseKeyword
|
||||
KindEnumKeyword
|
||||
KindExportKeyword
|
||||
KindExtendsKeyword
|
||||
KindFalseKeyword
|
||||
KindFinallyKeyword
|
||||
KindForKeyword
|
||||
KindFunctionKeyword
|
||||
KindIfKeyword
|
||||
KindImportKeyword
|
||||
KindInKeyword
|
||||
KindInstanceOfKeyword
|
||||
KindNewKeyword
|
||||
KindNullKeyword
|
||||
KindReturnKeyword
|
||||
KindSuperKeyword
|
||||
KindSwitchKeyword
|
||||
KindThisKeyword
|
||||
KindThrowKeyword
|
||||
KindTrueKeyword
|
||||
KindTryKeyword
|
||||
KindTypeOfKeyword
|
||||
KindVarKeyword
|
||||
KindVoidKeyword
|
||||
KindWhileKeyword
|
||||
KindWithKeyword
|
||||
// Strict mode reserved words
|
||||
KindImplementsKeyword
|
||||
KindInterfaceKeyword
|
||||
KindLetKeyword
|
||||
KindPackageKeyword
|
||||
KindPrivateKeyword
|
||||
KindProtectedKeyword
|
||||
KindPublicKeyword
|
||||
KindStaticKeyword
|
||||
KindYieldKeyword
|
||||
// Contextual keywords
|
||||
KindAbstractKeyword
|
||||
KindAccessorKeyword
|
||||
KindAsKeyword
|
||||
KindAssertsKeyword
|
||||
KindAssertKeyword
|
||||
KindAnyKeyword
|
||||
KindAsyncKeyword
|
||||
KindAwaitKeyword
|
||||
KindBooleanKeyword
|
||||
KindConstructorKeyword
|
||||
KindDeclareKeyword
|
||||
KindGetKeyword
|
||||
KindImmediateKeyword
|
||||
KindInferKeyword
|
||||
KindIntrinsicKeyword
|
||||
KindIsKeyword
|
||||
KindKeyOfKeyword
|
||||
KindModuleKeyword
|
||||
KindNamespaceKeyword
|
||||
KindNeverKeyword
|
||||
KindOutKeyword
|
||||
KindReadonlyKeyword
|
||||
KindRequireKeyword
|
||||
KindNumberKeyword
|
||||
KindObjectKeyword
|
||||
KindSatisfiesKeyword
|
||||
KindSetKeyword
|
||||
KindStringKeyword
|
||||
KindSymbolKeyword
|
||||
KindTypeKeyword
|
||||
KindUndefinedKeyword
|
||||
KindUniqueKeyword
|
||||
KindUnknownKeyword
|
||||
KindUsingKeyword
|
||||
KindFromKeyword
|
||||
KindGlobalKeyword
|
||||
KindBigIntKeyword
|
||||
KindOverrideKeyword
|
||||
KindOfKeyword
|
||||
KindDeferKeyword // LastKeyword and LastToken and LastContextualKeyword
|
||||
// Parse tree nodes
|
||||
// Names
|
||||
KindQualifiedName
|
||||
KindComputedPropertyName
|
||||
// Signature elements
|
||||
KindTypeParameter
|
||||
KindParameter
|
||||
KindDecorator
|
||||
// TypeMember
|
||||
KindPropertySignature
|
||||
KindPropertyDeclaration
|
||||
KindMethodSignature
|
||||
KindMethodDeclaration
|
||||
KindClassStaticBlockDeclaration
|
||||
KindConstructor
|
||||
KindGetAccessor
|
||||
KindSetAccessor
|
||||
KindCallSignature
|
||||
KindConstructSignature
|
||||
KindIndexSignature
|
||||
// Type
|
||||
KindTypePredicate
|
||||
KindTypeReference
|
||||
KindFunctionType
|
||||
KindConstructorType
|
||||
KindTypeQuery
|
||||
KindTypeLiteral
|
||||
KindArrayType
|
||||
KindTupleType
|
||||
KindOptionalType
|
||||
KindRestType
|
||||
KindUnionType
|
||||
KindIntersectionType
|
||||
KindConditionalType
|
||||
KindInferType
|
||||
KindParenthesizedType
|
||||
KindThisType
|
||||
KindTypeOperator
|
||||
KindIndexedAccessType
|
||||
KindMappedType
|
||||
KindLiteralType
|
||||
KindNamedTupleMember
|
||||
KindTemplateLiteralType
|
||||
KindTemplateLiteralTypeSpan
|
||||
KindImportType
|
||||
// Binding patterns
|
||||
KindObjectBindingPattern
|
||||
KindArrayBindingPattern
|
||||
KindBindingElement
|
||||
// Expression
|
||||
KindArrayLiteralExpression
|
||||
KindObjectLiteralExpression
|
||||
KindPropertyAccessExpression
|
||||
KindElementAccessExpression
|
||||
KindCallExpression
|
||||
KindNewExpression
|
||||
KindTaggedTemplateExpression
|
||||
KindTypeAssertionExpression
|
||||
KindParenthesizedExpression
|
||||
KindFunctionExpression
|
||||
KindArrowFunction
|
||||
KindDeleteExpression
|
||||
KindTypeOfExpression
|
||||
KindVoidExpression
|
||||
KindAwaitExpression
|
||||
KindPrefixUnaryExpression
|
||||
KindPostfixUnaryExpression
|
||||
KindBinaryExpression
|
||||
KindConditionalExpression
|
||||
KindTemplateExpression
|
||||
KindYieldExpression
|
||||
KindSpreadElement
|
||||
KindClassExpression
|
||||
KindOmittedExpression
|
||||
KindExpressionWithTypeArguments
|
||||
KindAsExpression
|
||||
KindNonNullExpression
|
||||
KindMetaProperty
|
||||
KindSyntheticExpression
|
||||
KindSatisfiesExpression
|
||||
// Misc
|
||||
KindTemplateSpan
|
||||
KindSemicolonClassElement
|
||||
// Element
|
||||
KindBlock
|
||||
KindEmptyStatement
|
||||
KindVariableStatement
|
||||
KindExpressionStatement
|
||||
KindIfStatement
|
||||
KindDoStatement
|
||||
KindWhileStatement
|
||||
KindForStatement
|
||||
KindForInStatement
|
||||
KindForOfStatement
|
||||
KindContinueStatement
|
||||
KindBreakStatement
|
||||
KindReturnStatement
|
||||
KindWithStatement
|
||||
KindSwitchStatement
|
||||
KindLabeledStatement
|
||||
KindThrowStatement
|
||||
KindTryStatement
|
||||
KindDebuggerStatement
|
||||
KindVariableDeclaration
|
||||
KindVariableDeclarationList
|
||||
KindFunctionDeclaration
|
||||
KindClassDeclaration
|
||||
KindInterfaceDeclaration
|
||||
KindTypeAliasDeclaration
|
||||
KindEnumDeclaration
|
||||
KindModuleDeclaration
|
||||
KindModuleBlock
|
||||
KindCaseBlock
|
||||
KindNamespaceExportDeclaration
|
||||
KindImportEqualsDeclaration
|
||||
KindImportDeclaration
|
||||
KindImportClause
|
||||
KindNamespaceImport
|
||||
KindNamedImports
|
||||
KindImportSpecifier
|
||||
KindExportAssignment
|
||||
KindExportDeclaration
|
||||
KindNamedExports
|
||||
KindNamespaceExport
|
||||
KindExportSpecifier
|
||||
KindMissingDeclaration
|
||||
// Module references
|
||||
KindExternalModuleReference
|
||||
// JSX
|
||||
KindJsxElement
|
||||
KindJsxSelfClosingElement
|
||||
KindJsxOpeningElement
|
||||
KindJsxClosingElement
|
||||
KindJsxFragment
|
||||
KindJsxOpeningFragment
|
||||
KindJsxClosingFragment
|
||||
KindJsxAttribute
|
||||
KindJsxAttributes
|
||||
KindJsxSpreadAttribute
|
||||
KindJsxExpression
|
||||
KindJsxNamespacedName
|
||||
// Clauses
|
||||
KindCaseClause
|
||||
KindDefaultClause
|
||||
KindHeritageClause
|
||||
KindCatchClause
|
||||
// Import attributes
|
||||
KindImportAttributes
|
||||
KindImportAttribute
|
||||
// Property assignments
|
||||
KindPropertyAssignment
|
||||
KindShorthandPropertyAssignment
|
||||
KindSpreadAssignment
|
||||
// Enum
|
||||
KindEnumMember
|
||||
// Top-level nodes
|
||||
KindSourceFile
|
||||
// JSDoc nodes
|
||||
KindJSDocTypeExpression
|
||||
KindJSDocNameReference
|
||||
KindJSDocAllType // The * type
|
||||
KindJSDocNullableType
|
||||
KindJSDocNonNullableType
|
||||
KindJSDocOptionalType
|
||||
KindJSDocVariadicType
|
||||
KindJSDoc
|
||||
KindJSDocText
|
||||
KindJSDocTypeLiteral
|
||||
KindJSDocSignature
|
||||
KindJSDocLink
|
||||
KindJSDocLinkCode
|
||||
KindJSDocLinkPlain
|
||||
KindJSDocUnknownTag
|
||||
KindJSDocAugmentsTag
|
||||
KindJSDocImplementsTag
|
||||
KindJSDocDeprecatedTag
|
||||
KindJSDocPublicTag
|
||||
KindJSDocPrivateTag
|
||||
KindJSDocProtectedTag
|
||||
KindJSDocReadonlyTag
|
||||
KindJSDocOverrideTag
|
||||
KindJSDocCallbackTag
|
||||
KindJSDocOverloadTag
|
||||
KindJSDocParameterTag
|
||||
KindJSDocReturnTag
|
||||
KindJSDocThisTag
|
||||
KindJSDocTypeTag
|
||||
KindJSDocTemplateTag
|
||||
KindJSDocTypedefTag
|
||||
KindJSDocSeeTag
|
||||
KindJSDocPropertyTag
|
||||
KindJSDocThrowsTag
|
||||
KindJSDocSatisfiesTag
|
||||
KindJSDocImportTag
|
||||
// Synthesized list
|
||||
KindSyntaxList
|
||||
// Reparsed JS nodes
|
||||
KindJSTypeAliasDeclaration
|
||||
KindJSImportDeclaration
|
||||
// Transformation nodes
|
||||
KindNotEmittedStatement
|
||||
KindPartiallyEmittedExpression
|
||||
KindSyntheticReferenceExpression
|
||||
KindNotEmittedTypeElement
|
||||
KindCount
|
||||
KindFirstAssignment = KindEqualsToken
|
||||
KindLastAssignment = KindCaretEqualsToken
|
||||
KindFirstCompoundAssignment = KindPlusEqualsToken
|
||||
KindLastCompoundAssignment = KindCaretEqualsToken
|
||||
KindFirstReservedWord = KindBreakKeyword
|
||||
KindLastReservedWord = KindWithKeyword
|
||||
KindFirstKeyword = KindBreakKeyword
|
||||
KindLastKeyword = KindDeferKeyword
|
||||
KindFirstFutureReservedWord = KindImplementsKeyword
|
||||
KindLastFutureReservedWord = KindYieldKeyword
|
||||
KindFirstTypeNode = KindTypePredicate
|
||||
KindLastTypeNode = KindImportType
|
||||
KindFirstPunctuation = KindOpenBraceToken
|
||||
KindLastPunctuation = KindCaretEqualsToken
|
||||
KindFirstToken = KindUnknown
|
||||
KindLastToken = KindLastKeyword
|
||||
KindFirstLiteralToken = KindNumericLiteral
|
||||
KindLastLiteralToken = KindNoSubstitutionTemplateLiteral
|
||||
KindFirstTemplateToken = KindNoSubstitutionTemplateLiteral
|
||||
KindLastTemplateToken = KindTemplateTail
|
||||
KindFirstBinaryOperator = KindLessThanToken
|
||||
KindLastBinaryOperator = KindCaretEqualsToken
|
||||
KindFirstStatement = KindVariableStatement
|
||||
KindLastStatement = KindDebuggerStatement
|
||||
KindFirstNode = KindQualifiedName
|
||||
KindFirstJSDocNode = KindJSDocTypeExpression
|
||||
KindLastJSDocNode = KindJSDocImportTag
|
||||
KindFirstJSDocTagNode = KindJSDocUnknownTag
|
||||
KindLastJSDocTagNode = KindJSDocImportTag
|
||||
KindFirstContextualKeyword = KindAbstractKeyword
|
||||
KindLastContextualKeyword = KindDeferKeyword
|
||||
KindLastUnaryOperator = KindTildeToken
|
||||
KindFirstTriviaToken = KindSingleLineCommentTrivia
|
||||
KindLastTriviaToken = KindConflictMarkerTrivia
|
||||
)
|
||||
|
||||
type (
|
||||
TriviaSyntaxKind = Kind // KindSingleLineCommentTrivia | KindMultiLineCommentTrivia | KindNewLineTrivia | KindWhitespaceTrivia | KindConflictMarkerTrivia
|
||||
LiteralSyntaxKind = Kind // KindNumericLiteral | KindBigIntLiteral | KindStringLiteral | KindJsxText | KindJsxTextAllWhiteSpaces | KindRegularExpressionLiteral | KindNoSubstitutionTemplateLiteral
|
||||
PseudoLiteralSyntaxKind = Kind // KindTemplateHead | KindTemplateMiddle | KindTemplateTail
|
||||
PunctuationSyntaxKind = Kind // KindOpenBraceToken | KindCloseBraceToken | KindOpenParenToken | KindCloseParenToken | KindOpenBracketToken | KindCloseBracketToken | KindDotToken | KindDotDotDotToken | KindSemicolonToken | KindCommaToken | KindQuestionDotToken | KindLessThanToken | KindLessThanSlashToken | KindGreaterThanToken | KindLessThanEqualsToken | KindGreaterThanEqualsToken | KindEqualsEqualsToken | KindExclamationEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindEqualsGreaterThanToken | KindPlusToken | KindMinusToken | KindAsteriskToken | KindAsteriskAsteriskToken | KindSlashToken | KindPercentToken | KindPlusPlusToken | KindMinusMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindExclamationToken | KindTildeToken | KindAmpersandAmpersandToken | KindBarBarToken | KindQuestionToken | KindColonToken | KindAtToken | KindQuestionQuestionToken | KindBacktickToken | KindHashToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskEqualsToken | KindAsteriskAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken | KindCaretEqualsToken
|
||||
KeywordSyntaxKind = Kind // KindBreakKeyword | KindCaseKeyword | KindCatchKeyword | KindClassKeyword | KindConstKeyword | KindContinueKeyword | KindDebuggerKeyword | KindDefaultKeyword | KindDeleteKeyword | KindDoKeyword | KindElseKeyword | KindEnumKeyword | KindExportKeyword | KindExtendsKeyword | KindFalseKeyword | KindFinallyKeyword | KindForKeyword | KindFunctionKeyword | KindIfKeyword | KindImportKeyword | KindInKeyword | KindInstanceOfKeyword | KindNewKeyword | KindNullKeyword | KindReturnKeyword | KindSuperKeyword | KindSwitchKeyword | KindThisKeyword | KindThrowKeyword | KindTrueKeyword | KindTryKeyword | KindTypeOfKeyword | KindVarKeyword | KindVoidKeyword | KindWhileKeyword | KindWithKeyword | KindImplementsKeyword | KindInterfaceKeyword | KindLetKeyword | KindPackageKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindStaticKeyword | KindYieldKeyword | KindAbstractKeyword | KindAccessorKeyword | KindAsKeyword | KindAssertsKeyword | KindAssertKeyword | KindAnyKeyword | KindAsyncKeyword | KindAwaitKeyword | KindBooleanKeyword | KindConstructorKeyword | KindDeclareKeyword | KindGetKeyword | KindImmediateKeyword | KindInferKeyword | KindIntrinsicKeyword | KindIsKeyword | KindKeyOfKeyword | KindModuleKeyword | KindNamespaceKeyword | KindNeverKeyword | KindOutKeyword | KindReadonlyKeyword | KindRequireKeyword | KindNumberKeyword | KindObjectKeyword | KindSatisfiesKeyword | KindSetKeyword | KindStringKeyword | KindSymbolKeyword | KindTypeKeyword | KindUndefinedKeyword | KindUniqueKeyword | KindUnknownKeyword | KindUsingKeyword | KindFromKeyword | KindGlobalKeyword | KindBigIntKeyword | KindOverrideKeyword | KindOfKeyword | KindDeferKeyword
|
||||
ModifierSyntaxKind = Kind // KindAbstractKeyword | KindAccessorKeyword | KindAsyncKeyword | KindConstKeyword | KindDeclareKeyword | KindDefaultKeyword | KindExportKeyword | KindInKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindReadonlyKeyword | KindOutKeyword | KindOverrideKeyword | KindStaticKeyword
|
||||
KeywordTypeSyntaxKind = Kind // KindAnyKeyword | KindBigIntKeyword | KindBooleanKeyword | KindIntrinsicKeyword | KindNeverKeyword | KindNumberKeyword | KindObjectKeyword | KindStringKeyword | KindSymbolKeyword | KindUndefinedKeyword | KindUnknownKeyword | KindVoidKeyword
|
||||
KeywordExpressionSyntaxKind = Kind // KindNullKeyword | KindTrueKeyword | KindFalseKeyword | KindThisKeyword | KindSuperKeyword | KindImportKeyword
|
||||
TokenSyntaxKind = Kind // KindUnknown | KindEndOfFile | KindSingleLineCommentTrivia | KindMultiLineCommentTrivia | KindNewLineTrivia | KindWhitespaceTrivia | KindConflictMarkerTrivia | KindNonTextFileMarkerTrivia | KindNumericLiteral | KindBigIntLiteral | KindStringLiteral | KindJsxText | KindJsxTextAllWhiteSpaces | KindRegularExpressionLiteral | KindNoSubstitutionTemplateLiteral | KindTemplateHead | KindTemplateMiddle | KindTemplateTail | KindOpenBraceToken | KindCloseBraceToken | KindOpenParenToken | KindCloseParenToken | KindOpenBracketToken | KindCloseBracketToken | KindDotToken | KindDotDotDotToken | KindSemicolonToken | KindCommaToken | KindQuestionDotToken | KindLessThanToken | KindLessThanSlashToken | KindGreaterThanToken | KindLessThanEqualsToken | KindGreaterThanEqualsToken | KindEqualsEqualsToken | KindExclamationEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindEqualsGreaterThanToken | KindPlusToken | KindMinusToken | KindAsteriskToken | KindAsteriskAsteriskToken | KindSlashToken | KindPercentToken | KindPlusPlusToken | KindMinusMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindExclamationToken | KindTildeToken | KindAmpersandAmpersandToken | KindBarBarToken | KindQuestionToken | KindColonToken | KindAtToken | KindQuestionQuestionToken | KindBacktickToken | KindHashToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskEqualsToken | KindAsteriskAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken | KindCaretEqualsToken | KindIdentifier | KindPrivateIdentifier | KindJSDocCommentTextToken | KindBreakKeyword | KindCaseKeyword | KindCatchKeyword | KindClassKeyword | KindConstKeyword | KindContinueKeyword | KindDebuggerKeyword | KindDefaultKeyword | KindDeleteKeyword | KindDoKeyword | KindElseKeyword | KindEnumKeyword | KindExportKeyword | KindExtendsKeyword | KindFalseKeyword | KindFinallyKeyword | KindForKeyword | KindFunctionKeyword | KindIfKeyword | KindImportKeyword | KindInKeyword | KindInstanceOfKeyword | KindNewKeyword | KindNullKeyword | KindReturnKeyword | KindSuperKeyword | KindSwitchKeyword | KindThisKeyword | KindThrowKeyword | KindTrueKeyword | KindTryKeyword | KindTypeOfKeyword | KindVarKeyword | KindVoidKeyword | KindWhileKeyword | KindWithKeyword | KindImplementsKeyword | KindInterfaceKeyword | KindLetKeyword | KindPackageKeyword | KindPrivateKeyword | KindProtectedKeyword | KindPublicKeyword | KindStaticKeyword | KindYieldKeyword | KindAbstractKeyword | KindAccessorKeyword | KindAsKeyword | KindAssertsKeyword | KindAssertKeyword | KindAnyKeyword | KindAsyncKeyword | KindAwaitKeyword | KindBooleanKeyword | KindConstructorKeyword | KindDeclareKeyword | KindGetKeyword | KindImmediateKeyword | KindInferKeyword | KindIntrinsicKeyword | KindIsKeyword | KindKeyOfKeyword | KindModuleKeyword | KindNamespaceKeyword | KindNeverKeyword | KindOutKeyword | KindReadonlyKeyword | KindRequireKeyword | KindNumberKeyword | KindObjectKeyword | KindSatisfiesKeyword | KindSetKeyword | KindStringKeyword | KindSymbolKeyword | KindTypeKeyword | KindUndefinedKeyword | KindUniqueKeyword | KindUnknownKeyword | KindUsingKeyword | KindFromKeyword | KindGlobalKeyword | KindBigIntKeyword | KindOverrideKeyword | KindOfKeyword | KindDeferKeyword
|
||||
JsxTokenSyntaxKind = Kind // KindLessThanSlashToken | KindEndOfFile | KindConflictMarkerTrivia | KindJsxText | KindJsxTextAllWhiteSpaces | KindOpenBraceToken | KindLessThanToken
|
||||
JSDocNodeSyntaxKind = Kind // KindJSDocTypeExpression | KindJSDocNameReference | KindJSDocAllType | KindJSDocNullableType | KindJSDocNonNullableType | KindJSDocOptionalType | KindJSDocVariadicType | KindJSDoc | KindJSDocText | KindJSDocTypeLiteral | KindJSDocSignature | KindJSDocLink | KindJSDocLinkCode | KindJSDocLinkPlain | KindJSDocUnknownTag | KindJSDocAugmentsTag | KindJSDocImplementsTag | KindJSDocDeprecatedTag | KindJSDocPublicTag | KindJSDocPrivateTag | KindJSDocProtectedTag | KindJSDocReadonlyTag | KindJSDocOverrideTag | KindJSDocCallbackTag | KindJSDocOverloadTag | KindJSDocParameterTag | KindJSDocReturnTag | KindJSDocThisTag | KindJSDocTypeTag | KindJSDocTemplateTag | KindJSDocTypedefTag | KindJSDocSeeTag | KindJSDocPropertyTag | KindJSDocThrowsTag | KindJSDocSatisfiesTag | KindJSDocImportTag
|
||||
ImportPhaseModifierSyntaxKind = Kind // KindTypeKeyword | KindDeferKeyword
|
||||
PostfixUnaryOperator = Kind // KindPlusPlusToken | KindMinusMinusToken
|
||||
PrefixUnaryOperator = Kind // KindPlusToken | KindMinusToken | KindTildeToken | KindExclamationToken | KindPlusPlusToken | KindMinusMinusToken
|
||||
AssignmentOperator = Kind // KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskAsteriskEqualsToken | KindAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindCaretEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken
|
||||
BinaryOperator = Kind // KindQuestionQuestionToken | KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindAmpersandAmpersandToken | KindBarBarToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskAsteriskEqualsToken | KindAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindCaretEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken | KindCommaToken
|
||||
ExponentiationOperator = Kind // KindAsteriskAsteriskToken
|
||||
MultiplicativeOperator = Kind // KindAsteriskToken | KindSlashToken | KindPercentToken
|
||||
MultiplicativeOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken
|
||||
AdditiveOperator = Kind // KindPlusToken | KindMinusToken
|
||||
AdditiveOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken
|
||||
ShiftOperator = Kind // KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken
|
||||
ShiftOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken
|
||||
RelationalOperator = Kind // KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword
|
||||
RelationalOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword
|
||||
EqualityOperator = Kind // KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken
|
||||
EqualityOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken
|
||||
BitwiseOperator = Kind // KindAmpersandToken | KindBarToken | KindCaretToken
|
||||
BitwiseOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken | KindAmpersandToken | KindBarToken | KindCaretToken
|
||||
LogicalOperator = Kind // KindAmpersandAmpersandToken | KindBarBarToken
|
||||
LogicalOperatorOrHigher = Kind // KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindAmpersandAmpersandToken | KindBarBarToken
|
||||
CompoundAssignmentOperator = Kind // KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskAsteriskEqualsToken | KindAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindCaretEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken
|
||||
AssignmentOperatorOrHigher = Kind // KindQuestionQuestionToken | KindAsteriskAsteriskToken | KindAsteriskToken | KindSlashToken | KindPercentToken | KindPlusToken | KindMinusToken | KindLessThanLessThanToken | KindGreaterThanGreaterThanToken | KindGreaterThanGreaterThanGreaterThanToken | KindLessThanToken | KindLessThanEqualsToken | KindGreaterThanToken | KindGreaterThanEqualsToken | KindInstanceOfKeyword | KindInKeyword | KindEqualsEqualsToken | KindEqualsEqualsEqualsToken | KindExclamationEqualsEqualsToken | KindExclamationEqualsToken | KindAmpersandToken | KindBarToken | KindCaretToken | KindAmpersandAmpersandToken | KindBarBarToken | KindEqualsToken | KindPlusEqualsToken | KindMinusEqualsToken | KindAsteriskAsteriskEqualsToken | KindAsteriskEqualsToken | KindSlashEqualsToken | KindPercentEqualsToken | KindAmpersandEqualsToken | KindBarEqualsToken | KindCaretEqualsToken | KindLessThanLessThanEqualsToken | KindGreaterThanGreaterThanGreaterThanEqualsToken | KindGreaterThanGreaterThanEqualsToken | KindBarBarEqualsToken | KindAmpersandAmpersandEqualsToken | KindQuestionQuestionEqualsToken
|
||||
LogicalOrCoalescingAssignmentOperator = Kind // KindAmpersandAmpersandEqualsToken | KindBarBarEqualsToken | KindQuestionQuestionEqualsToken
|
||||
)
|
||||
375
tools/tsgo/internal/ast/kind_stringer_generated.go
Normal file
375
tools/tsgo/internal/ast/kind_stringer_generated.go
Normal file
File diff suppressed because one or more lines are too long
53
tools/tsgo/internal/ast/modifierflags.go
Normal file
53
tools/tsgo/internal/ast/modifierflags.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package ast
|
||||
|
||||
type ModifierFlags uint32
|
||||
|
||||
const (
|
||||
ModifierFlagsNone ModifierFlags = 0
|
||||
// Syntactic/JSDoc modifiers
|
||||
ModifierFlagsPublic ModifierFlags = 1 << 0 // Property/Method
|
||||
ModifierFlagsPrivate ModifierFlags = 1 << 1 // Property/Method
|
||||
ModifierFlagsProtected ModifierFlags = 1 << 2 // Property/Method
|
||||
ModifierFlagsReadonly ModifierFlags = 1 << 3 // Property/Method
|
||||
ModifierFlagsOverride ModifierFlags = 1 << 4 // Override method
|
||||
// Syntactic-only modifiers
|
||||
ModifierFlagsExport ModifierFlags = 1 << 5 // Declarations
|
||||
ModifierFlagsAbstract ModifierFlags = 1 << 6 // Class/Method/ConstructSignature
|
||||
ModifierFlagsAmbient ModifierFlags = 1 << 7 // Declarations (declare keyword)
|
||||
ModifierFlagsStatic ModifierFlags = 1 << 8 // Property/Method
|
||||
ModifierFlagsAccessor ModifierFlags = 1 << 9 // Property
|
||||
ModifierFlagsAsync ModifierFlags = 1 << 10 // Property/Method/Function
|
||||
ModifierFlagsDefault ModifierFlags = 1 << 11 // Function/Class (export default declaration)
|
||||
ModifierFlagsConst ModifierFlags = 1 << 12 // Const enum
|
||||
ModifierFlagsIn ModifierFlags = 1 << 13 // Contravariance modifier
|
||||
ModifierFlagsOut ModifierFlags = 1 << 14 // Covariance modifier
|
||||
ModifierFlagsDecorator ModifierFlags = 1 << 15 // Contains a decorator
|
||||
// JSDoc-only modifiers
|
||||
ModifierFlagsDeprecated ModifierFlags = 1 << 16 // Deprecated tag
|
||||
// Cache-only JSDoc-modifiers. Should match order of Syntactic/JSDoc modifiers, above.
|
||||
ModifierFlagsJSDocPublic ModifierFlags = 1 << 23 // if this value changes, `selectEffectiveModifierFlags` must change accordingly
|
||||
ModifierFlagsJSDocPrivate ModifierFlags = 1 << 24
|
||||
ModifierFlagsJSDocProtected ModifierFlags = 1 << 25
|
||||
ModifierFlagsJSDocReadonly ModifierFlags = 1 << 26
|
||||
ModifierFlagsJSDocOverride ModifierFlags = 1 << 27
|
||||
ModifierFlagsHasComputedJSDocModifiers ModifierFlags = 1 << 28 // Indicates the computed modifier flags include modifiers from JSDoc.
|
||||
ModifierFlagsHasComputedFlags ModifierFlags = 1 << 29 // Modifier flags have been computed
|
||||
|
||||
ModifierFlagsSyntacticOrJSDocModifiers = ModifierFlagsPublic | ModifierFlagsPrivate | ModifierFlagsProtected | ModifierFlagsReadonly | ModifierFlagsOverride
|
||||
ModifierFlagsSyntacticOnlyModifiers = ModifierFlagsExport | ModifierFlagsAmbient | ModifierFlagsAbstract | ModifierFlagsStatic | ModifierFlagsAccessor | ModifierFlagsAsync | ModifierFlagsDefault | ModifierFlagsConst | ModifierFlagsIn | ModifierFlagsOut | ModifierFlagsDecorator
|
||||
ModifierFlagsSyntacticModifiers = ModifierFlagsSyntacticOrJSDocModifiers | ModifierFlagsSyntacticOnlyModifiers
|
||||
ModifierFlagsJSDocCacheOnlyModifiers = ModifierFlagsJSDocPublic | ModifierFlagsJSDocPrivate | ModifierFlagsJSDocProtected | ModifierFlagsJSDocReadonly | ModifierFlagsJSDocOverride
|
||||
ModifierFlagsJSDocOnlyModifiers = ModifierFlagsDeprecated
|
||||
ModifierFlagsNonCacheOnlyModifiers = ModifierFlagsSyntacticOrJSDocModifiers | ModifierFlagsSyntacticOnlyModifiers | ModifierFlagsJSDocOnlyModifiers
|
||||
|
||||
ModifierFlagsAccessibilityModifier = ModifierFlagsPublic | ModifierFlagsPrivate | ModifierFlagsProtected
|
||||
// Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property.
|
||||
ModifierFlagsParameterPropertyModifier = ModifierFlagsAccessibilityModifier | ModifierFlagsReadonly | ModifierFlagsOverride
|
||||
ModifierFlagsNonPublicAccessibilityModifier = ModifierFlagsPrivate | ModifierFlagsProtected
|
||||
|
||||
ModifierFlagsTypeScriptModifier = ModifierFlagsAmbient | ModifierFlagsPublic | ModifierFlagsPrivate | ModifierFlagsProtected | ModifierFlagsReadonly | ModifierFlagsAbstract | ModifierFlagsConst | ModifierFlagsOverride | ModifierFlagsIn | ModifierFlagsOut
|
||||
ModifierFlagsExportDefault = ModifierFlagsExport | ModifierFlagsDefault
|
||||
ModifierFlagsAll = ModifierFlagsExport | ModifierFlagsAmbient | ModifierFlagsPublic | ModifierFlagsPrivate | ModifierFlagsProtected | ModifierFlagsStatic | ModifierFlagsReadonly | ModifierFlagsAbstract | ModifierFlagsAccessor | ModifierFlagsAsync | ModifierFlagsDefault | ModifierFlagsConst | ModifierFlagsDeprecated | ModifierFlagsOverride | ModifierFlagsIn | ModifierFlagsOut | ModifierFlagsDecorator
|
||||
ModifierFlagsModifier = ModifierFlagsAll & ^ModifierFlagsDecorator
|
||||
ModifierFlagsJavaScript = ModifierFlagsExport | ModifierFlagsStatic | ModifierFlagsAccessor | ModifierFlagsAsync | ModifierFlagsDefault
|
||||
)
|
||||
73
tools/tsgo/internal/ast/nodeflags.go
Normal file
73
tools/tsgo/internal/ast/nodeflags.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package ast
|
||||
|
||||
type NodeFlags uint32
|
||||
|
||||
const (
|
||||
NodeFlagsNone NodeFlags = 0
|
||||
NodeFlagsLet NodeFlags = 1 << 0 // Variable declaration
|
||||
NodeFlagsConst NodeFlags = 1 << 1 // Variable declaration
|
||||
NodeFlagsUsing NodeFlags = 1 << 2 // Variable declaration
|
||||
NodeFlagsReparsed NodeFlags = 1 << 3 // Node was synthesized during parsing
|
||||
NodeFlagsSynthesized NodeFlags = 1 << 4 // Node was synthesized during transformation
|
||||
NodeFlagsOptionalChain NodeFlags = 1 << 5 // Chained MemberExpression rooted to a pseudo-OptionalExpression
|
||||
NodeFlagsExportContext NodeFlags = 1 << 6 // Export context (initialized by binding)
|
||||
NodeFlagsContainsThis NodeFlags = 1 << 7 // Interface contains references to "this"
|
||||
NodeFlagsHasImplicitReturn NodeFlags = 1 << 8 // If function implicitly returns on one of codepaths (initialized by binding)
|
||||
NodeFlagsHasExplicitReturn NodeFlags = 1 << 9 // If function has explicit reachable return on one of codepaths (initialized by binding)
|
||||
NodeFlagsDisallowInContext NodeFlags = 1 << 10 // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
NodeFlagsYieldContext NodeFlags = 1 << 11 // If node was parsed in the 'yield' context created when parsing a generator
|
||||
NodeFlagsDecoratorContext NodeFlags = 1 << 12 // If node was parsed as part of a decorator
|
||||
NodeFlagsAwaitContext NodeFlags = 1 << 13 // If node was parsed in the 'await' context created when parsing an async function
|
||||
NodeFlagsDisallowConditionalTypesContext NodeFlags = 1 << 14 // If node was parsed in a context where conditional types are not allowed
|
||||
NodeFlagsThisNodeHasError NodeFlags = 1 << 15 // If the parser encountered an error when parsing the code that created this node
|
||||
NodeFlagsJavaScriptFile NodeFlags = 1 << 16 // If node was parsed in a JavaScript
|
||||
NodeFlagsThisNodeOrAnySubNodesHasError NodeFlags = 1 << 17 // If this node or any of its children had an error
|
||||
NodeFlagsHasAsyncFunctions NodeFlags = 1 << 18 // If the file has async functions (initialized by binding)
|
||||
// NodeFlagsHasAggregatedChildData is deprecated. Use `subtreeFacts` instead.
|
||||
|
||||
// These flags will be set when the parser encounters a dynamic import expression or 'import.meta' to avoid
|
||||
// walking the tree if the flags are not set. However, these flags are just a approximation
|
||||
// (hence why it's named "PossiblyContainsDynamicImport") because once set, the flags never get cleared.
|
||||
// During editing, if a dynamic import is removed, incremental parsing will *NOT* clear this flag.
|
||||
// This means that the tree will always be traversed during module resolution, or when looking for external module indicators.
|
||||
// However, the removal operation should not occur often and in the case of the
|
||||
// removal, it is likely that users will add the import anyway.
|
||||
// The advantage of this approach is its simplicity. For the case of batch compilation,
|
||||
// we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used.
|
||||
NodeFlagsPossiblyContainsDynamicImport NodeFlags = 1 << 19
|
||||
NodeFlagsPossiblyContainsImportMeta NodeFlags = 1 << 20
|
||||
|
||||
NodeFlagsHasJSDoc NodeFlags = 1 << 21 // If node has preceding JSDoc comment(s)
|
||||
NodeFlagsJSDoc NodeFlags = 1 << 22 // If node was parsed inside jsdoc
|
||||
NodeFlagsAmbient NodeFlags = 1 << 23 // If node was inside an ambient context -- a declaration file, or inside something with the `declare` modifier.
|
||||
NodeFlagsInWithStatement NodeFlags = 1 << 24 // If any ancestor of node was the `statement` of a WithStatement (not the `expression`)
|
||||
NodeFlagsJsonFile NodeFlags = 1 << 25 // If node was parsed in a Json
|
||||
NodeFlagsPossiblyContainsDeprecatedTag NodeFlags = 1 << 26 // Set during parse if comment text contains '@deprecated'; must confirm via JSDoc lookup
|
||||
NodeFlagsUnreachable NodeFlags = 1 << 27 // If node is unreachable according to the binder
|
||||
NodeFlagsReparserTransformedLiteral NodeFlags = 1 << 28 // If node was transformed during parsing, making its' naive text source not match the AST
|
||||
|
||||
NodeFlagsBlockScoped = NodeFlagsLet | NodeFlagsConst | NodeFlagsUsing
|
||||
NodeFlagsConstant = NodeFlagsConst | NodeFlagsUsing
|
||||
NodeFlagsAwaitUsing = NodeFlagsConst | NodeFlagsUsing // Variable declaration (NOTE: on a single node these flags would otherwise be mutually exclusive)
|
||||
|
||||
NodeFlagsReachabilityCheckFlags = NodeFlagsHasImplicitReturn | NodeFlagsHasExplicitReturn
|
||||
NodeFlagsReachabilityAndEmitFlags = NodeFlagsReachabilityCheckFlags | NodeFlagsHasAsyncFunctions
|
||||
|
||||
// Parsing context flags
|
||||
NodeFlagsContextFlags NodeFlags = NodeFlagsDisallowInContext | NodeFlagsDisallowConditionalTypesContext | NodeFlagsYieldContext | NodeFlagsDecoratorContext | NodeFlagsAwaitContext | NodeFlagsJavaScriptFile | NodeFlagsInWithStatement | NodeFlagsAmbient
|
||||
|
||||
// Exclude these flags when parsing a Type
|
||||
NodeFlagsTypeExcludesFlags NodeFlags = NodeFlagsYieldContext | NodeFlagsAwaitContext
|
||||
|
||||
// Represents all flags that are potentially set once and
|
||||
// never cleared on SourceFiles which get re-used in between incremental parses.
|
||||
// See the comment above on `PossiblyContainsDynamicImport` and `PossiblyContainsImportMeta`.
|
||||
NodeFlagsPermanentlySetIncrementalFlags NodeFlags = NodeFlagsPossiblyContainsDynamicImport | NodeFlagsPossiblyContainsImportMeta
|
||||
|
||||
// The following flags repurpose other NodeFlags as different meanings for Identifier nodes
|
||||
NodeFlagsIdentifierHasExtendedUnicodeEscape NodeFlags = NodeFlagsContainsThis // Indicates whether the identifier contains an extended unicode escape sequence
|
||||
NodeFlagsIdentifierIsInJSDocNamespace NodeFlags = NodeFlagsHasAsyncFunctions // Indicates the identifier is the innermost name of a JSDoc namespace declaration
|
||||
|
||||
// The following flag repurposes other NodeFlags for ModuleDeclaration nodes
|
||||
NodeFlagsNestedNamespace NodeFlags = NodeFlagsOptionalChain // If ModuleDeclaration is a nested namespace (e.g. inner part of A.B.C)
|
||||
)
|
||||
149
tools/tsgo/internal/ast/parseoptions.go
Normal file
149
tools/tsgo/internal/ast/parseoptions.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/tspath"
|
||||
)
|
||||
|
||||
type SourceFileParseOptions struct {
|
||||
FileName string
|
||||
Path tspath.Path
|
||||
ExternalModuleIndicatorOptions ExternalModuleIndicatorOptions
|
||||
}
|
||||
|
||||
type ExternalModuleIndicatorOptions struct {
|
||||
JSX bool
|
||||
Force bool
|
||||
}
|
||||
|
||||
func GetExternalModuleIndicatorOptions(fileName string, options *core.CompilerOptions, metadata SourceFileMetaData) ExternalModuleIndicatorOptions {
|
||||
if tspath.IsDeclarationFileName(fileName) {
|
||||
return ExternalModuleIndicatorOptions{}
|
||||
}
|
||||
|
||||
switch options.GetEmitModuleDetectionKind() {
|
||||
case core.ModuleDetectionKindForce:
|
||||
// All non-declaration files are modules, declaration files still do the usual isFileProbablyExternalModule
|
||||
return ExternalModuleIndicatorOptions{Force: true}
|
||||
case core.ModuleDetectionKindLegacy:
|
||||
// Files are modules if they have imports, exports, or import.meta
|
||||
return ExternalModuleIndicatorOptions{}
|
||||
case core.ModuleDetectionKindAuto:
|
||||
// If module is nodenext or node16, all esm format files are modules
|
||||
// If jsx is react-jsx or react-jsxdev then jsx tags force module-ness
|
||||
// otherwise, the presence of import or export statments (or import.meta) implies module-ness
|
||||
return ExternalModuleIndicatorOptions{
|
||||
JSX: options.Jsx == core.JsxEmitReactJSX || options.Jsx == core.JsxEmitReactJSXDev,
|
||||
Force: isFileForcedToBeModuleByFormat(fileName, options, metadata),
|
||||
}
|
||||
default:
|
||||
return ExternalModuleIndicatorOptions{}
|
||||
}
|
||||
}
|
||||
|
||||
var isFileForcedToBeModuleByFormatExtensions = []string{tspath.ExtensionCjs, tspath.ExtensionCts, tspath.ExtensionMjs, tspath.ExtensionMts}
|
||||
|
||||
func isFileForcedToBeModuleByFormat(fileName string, options *core.CompilerOptions, metadata SourceFileMetaData) bool {
|
||||
// Excludes declaration files - they still require an explicit `export {}` or the like
|
||||
// for back compat purposes. The only non-declaration files _not_ forced to be a module are `.js` files
|
||||
// that aren't esm-mode (meaning not in a `type: module` scope).
|
||||
if GetImpliedNodeFormatForEmitWorker(fileName, options.GetEmitModuleKind(), metadata) == core.ModuleKindESNext || tspath.FileExtensionIsOneOf(fileName, isFileForcedToBeModuleByFormatExtensions) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func SetExternalModuleIndicator(file *SourceFile, opts ExternalModuleIndicatorOptions) {
|
||||
file.ExternalModuleIndicator = getExternalModuleIndicator(file, opts)
|
||||
}
|
||||
|
||||
func getExternalModuleIndicator(file *SourceFile, opts ExternalModuleIndicatorOptions) *Node {
|
||||
if file.ScriptKind == core.ScriptKindJSON {
|
||||
return nil
|
||||
}
|
||||
|
||||
if node := isFileProbablyExternalModule(file); node != nil {
|
||||
return node
|
||||
}
|
||||
|
||||
if file.IsDeclarationFile {
|
||||
return nil
|
||||
}
|
||||
|
||||
if opts.JSX {
|
||||
if node := isFileModuleFromUsingJSXTag(file); node != nil {
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
if opts.Force {
|
||||
return file.AsNode()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isFileProbablyExternalModule(sourceFile *SourceFile) *Node {
|
||||
for _, statement := range sourceFile.Statements.Nodes {
|
||||
if isAnExternalModuleIndicatorNode(statement) {
|
||||
return statement
|
||||
}
|
||||
}
|
||||
return getImportMetaIfNecessary(sourceFile)
|
||||
}
|
||||
|
||||
func isAnExternalModuleIndicatorNode(node *Node) bool {
|
||||
return HasSyntacticModifier(node, ModifierFlagsExport) ||
|
||||
IsImportEqualsDeclaration(node) && IsExternalModuleReference(node.AsImportEqualsDeclaration().ModuleReference) ||
|
||||
IsImportDeclaration(node) || IsExportAssignment(node) || IsExportDeclaration(node)
|
||||
}
|
||||
|
||||
func getImportMetaIfNecessary(sourceFile *SourceFile) *Node {
|
||||
if sourceFile.AsNode().Flags&NodeFlagsPossiblyContainsImportMeta != 0 {
|
||||
return findChildNode(sourceFile.AsNode(), IsImportMeta)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func findChildNode(root *Node, check func(*Node) bool) *Node {
|
||||
var result *Node
|
||||
var visit func(*Node) bool
|
||||
visit = func(node *Node) bool {
|
||||
if check(node) {
|
||||
result = node
|
||||
return true
|
||||
}
|
||||
return node.ForEachChild(visit)
|
||||
}
|
||||
visit(root)
|
||||
return result
|
||||
}
|
||||
|
||||
func isFileModuleFromUsingJSXTag(file *SourceFile) *Node {
|
||||
return walkTreeForJSXTags(file.AsNode())
|
||||
}
|
||||
|
||||
// This is a somewhat unavoidable full tree walk to locate a JSX tag - `import.meta` requires the same,
|
||||
// but we avoid that walk (or parts of it) if at all possible using the `PossiblyContainsImportMeta` node flag.
|
||||
// Unfortunately, there's no `NodeFlag` space to do the same for JSX.
|
||||
func walkTreeForJSXTags(node *Node) *Node {
|
||||
var found *Node
|
||||
|
||||
var visitor func(node *Node) bool
|
||||
visitor = func(node *Node) bool {
|
||||
if found != nil {
|
||||
return true
|
||||
}
|
||||
if node.SubtreeFacts()&SubtreeContainsJsx == 0 {
|
||||
return false
|
||||
}
|
||||
if IsJsxOpeningLikeElement(node) || IsJsxFragment(node) {
|
||||
found = node
|
||||
return true
|
||||
}
|
||||
return node.ForEachChild(visitor)
|
||||
}
|
||||
visitor(node)
|
||||
|
||||
return found
|
||||
}
|
||||
111
tools/tsgo/internal/ast/positionmap.go
Normal file
111
tools/tsgo/internal/ast/positionmap.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/stringutil"
|
||||
)
|
||||
|
||||
// PositionMap provides bidirectional mapping between UTF-8 byte offsets (used by Go)
|
||||
// and UTF-16 code unit offsets (used by JavaScript/TypeScript).
|
||||
//
|
||||
// For ASCII-only text, the two are identical. For text containing non-ASCII characters,
|
||||
// the offsets diverge because multi-byte UTF-8 sequences map to different numbers of
|
||||
// UTF-16 code units:
|
||||
// - U+0000..U+007F: 1 byte in UTF-8, 1 code unit in UTF-16
|
||||
// - U+0080..U+07FF: 2 bytes in UTF-8, 1 code unit in UTF-16
|
||||
// - U+0800..U+FFFF: 3 bytes in UTF-8, 1 code unit in UTF-16
|
||||
// - U+10000..U+10FFFF: 4 bytes in UTF-8, 2 code units in UTF-16 (surrogate pair)
|
||||
type PositionMap struct {
|
||||
// asciiOnly is true if the text contains only ASCII characters,
|
||||
// meaning UTF-8 byte offsets and UTF-16 code unit offsets are identical.
|
||||
asciiOnly bool
|
||||
// For each multi-byte character, we store:
|
||||
// - the UTF-8 byte offset of the character
|
||||
// - the cumulative delta (utf8Offset - utf16Offset) at that character
|
||||
// This allows O(log n) conversion in either direction.
|
||||
//
|
||||
// entries[i].utf8Pos is the byte offset of the i-th multi-byte character.
|
||||
// entries[i].delta is the total (utf8 - utf16) difference accumulated
|
||||
// through and including the i-th multi-byte character.
|
||||
entries []positionMapEntry
|
||||
}
|
||||
|
||||
type positionMapEntry struct {
|
||||
utf8Pos int // UTF-8 byte offset AFTER this multi-byte character
|
||||
delta int // cumulative (utf8 - utf16) offset difference after this character
|
||||
}
|
||||
|
||||
// ComputePositionMap builds a PositionMap for the given text.
|
||||
func ComputePositionMap(text string) *PositionMap {
|
||||
pm := &PositionMap{}
|
||||
delta := 0
|
||||
for i := 0; i < len(text); {
|
||||
b := text[i]
|
||||
if b < utf8.RuneSelf {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
r, size := stringutil.DecodeJSStringRune(text[i:])
|
||||
utf16Size := 1
|
||||
if r >= 0x10000 {
|
||||
utf16Size = 2
|
||||
}
|
||||
delta += size - utf16Size
|
||||
pm.entries = append(pm.entries, positionMapEntry{utf8Pos: i + size, delta: delta})
|
||||
i += size
|
||||
}
|
||||
pm.asciiOnly = len(pm.entries) == 0
|
||||
return pm
|
||||
}
|
||||
|
||||
// IsAsciiOnly returns true if the text is ASCII-only,
|
||||
// meaning UTF-8 and UTF-16 offsets are identical.
|
||||
func (pm *PositionMap) IsAsciiOnly() bool {
|
||||
return pm.asciiOnly
|
||||
}
|
||||
|
||||
// UTF8ToUTF16 converts a UTF-8 byte offset to a UTF-16 code unit offset.
|
||||
func (pm *PositionMap) UTF8ToUTF16(utf8Offset int) int {
|
||||
if pm.asciiOnly {
|
||||
return utf8Offset
|
||||
}
|
||||
// Binary search: find the last entry where utf8Pos <= utf8Offset
|
||||
lo, hi := 0, len(pm.entries)
|
||||
for lo < hi {
|
||||
mid := lo + (hi-lo)/2
|
||||
if pm.entries[mid].utf8Pos <= utf8Offset {
|
||||
lo = mid + 1
|
||||
} else {
|
||||
hi = mid
|
||||
}
|
||||
}
|
||||
if lo == 0 {
|
||||
// Before any multi-byte character
|
||||
return utf8Offset
|
||||
}
|
||||
return utf8Offset - pm.entries[lo-1].delta
|
||||
}
|
||||
|
||||
// UTF16ToUTF8 converts a UTF-16 code unit offset to a UTF-8 byte offset.
|
||||
func (pm *PositionMap) UTF16ToUTF8(utf16Offset int) int {
|
||||
if pm.asciiOnly {
|
||||
return utf16Offset
|
||||
}
|
||||
// We need the last entry where (utf8Pos - delta) <= utf16Offset.
|
||||
// (utf8Pos - delta) is the UTF-16 offset of that entry's character.
|
||||
lo, hi := 0, len(pm.entries)
|
||||
for lo < hi {
|
||||
mid := lo + (hi-lo)/2
|
||||
utf16Pos := pm.entries[mid].utf8Pos - pm.entries[mid].delta
|
||||
if utf16Pos <= utf16Offset {
|
||||
lo = mid + 1
|
||||
} else {
|
||||
hi = mid
|
||||
}
|
||||
}
|
||||
if lo == 0 {
|
||||
return utf16Offset
|
||||
}
|
||||
return utf16Offset + pm.entries[lo-1].delta
|
||||
}
|
||||
225
tools/tsgo/internal/ast/positionmap_test.go
Normal file
225
tools/tsgo/internal/ast/positionmap_test.go
Normal file
@@ -0,0 +1,225 @@
|
||||
package ast_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/stringutil"
|
||||
)
|
||||
|
||||
func TestPositionMapASCII(t *testing.T) {
|
||||
t.Parallel()
|
||||
text := "const x = 1;"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
if !pm.IsAsciiOnly() {
|
||||
t.Fatal("expected ASCII-only")
|
||||
}
|
||||
for i := 0; i <= len(text); i++ {
|
||||
if got := pm.UTF8ToUTF16(i); got != i {
|
||||
t.Errorf("UTF8ToUTF16(%d) = %d, want %d", i, got, i)
|
||||
}
|
||||
if got := pm.UTF16ToUTF8(i); got != i {
|
||||
t.Errorf("UTF16ToUTF8(%d) = %d, want %d", i, got, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapTwoByte(t *testing.T) {
|
||||
t.Parallel()
|
||||
// "café" — é (U+00E9) is 2 bytes UTF-8, 1 code unit UTF-16
|
||||
text := "const café = 1;\nconst x = 2;"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
if pm.IsAsciiOnly() {
|
||||
t.Fatal("expected non-ASCII")
|
||||
}
|
||||
|
||||
// Everything before é (byte offset 9) should be identity
|
||||
for i := range 10 {
|
||||
if got := pm.UTF8ToUTF16(i); got != i {
|
||||
t.Errorf("before é: UTF8ToUTF16(%d) = %d, want %d", i, got, i)
|
||||
}
|
||||
}
|
||||
|
||||
// é starts at UTF-8 byte 9, UTF-16 offset 9: same
|
||||
if got := pm.UTF8ToUTF16(9); got != 9 {
|
||||
t.Errorf("at é: UTF8ToUTF16(9) = %d, want 9", got)
|
||||
}
|
||||
|
||||
// After é (byte 11 in UTF-8 = code unit 10 in UTF-16), delta is 1
|
||||
// ' ' after café: UTF-8 byte 11, UTF-16 offset 10
|
||||
if got := pm.UTF8ToUTF16(11); got != 10 {
|
||||
t.Errorf("after é: UTF8ToUTF16(11) = %d, want 10", got)
|
||||
}
|
||||
|
||||
// 'x' on second line: UTF-8 byte 23, UTF-16 offset 22
|
||||
xUTF8 := strings.LastIndex(text, "x")
|
||||
if got := pm.UTF8ToUTF16(xUTF8); got != xUTF8-1 {
|
||||
t.Errorf("at x: UTF8ToUTF16(%d) = %d, want %d", xUTF8, got, xUTF8-1)
|
||||
}
|
||||
|
||||
// Reverse: UTF-16 offset 22 should map to UTF-8 byte 23
|
||||
xUTF16 := xUTF8 - 1
|
||||
if got := pm.UTF16ToUTF8(xUTF16); got != xUTF8 {
|
||||
t.Errorf("reverse at x: UTF16ToUTF8(%d) = %d, want %d", xUTF16, got, xUTF8)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapFourByte(t *testing.T) {
|
||||
t.Parallel()
|
||||
// 🎉 (U+1F389) is 4 bytes UTF-8, 2 code units UTF-16
|
||||
text := `const a = "🎉";` + "\nconst b = 2;"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
if pm.IsAsciiOnly() {
|
||||
t.Fatal("expected non-ASCII")
|
||||
}
|
||||
|
||||
// 🎉 starts at byte 11 (after `const a = "`)
|
||||
// UTF-8: bytes 11-14 (4 bytes), UTF-16: units 11-12 (2 code units)
|
||||
// After 🎉: UTF-8 byte 15, UTF-16 offset 13. Delta = 2.
|
||||
|
||||
// 'b' on second line
|
||||
bUTF8 := strings.LastIndex(text, "b")
|
||||
bUTF16 := bUTF8 - 2 // delta of 2 from emoji
|
||||
if got := pm.UTF8ToUTF16(bUTF8); got != bUTF16 {
|
||||
t.Errorf("at b: UTF8ToUTF16(%d) = %d, want %d", bUTF8, got, bUTF16)
|
||||
}
|
||||
if got := pm.UTF16ToUTF8(bUTF16); got != bUTF8 {
|
||||
t.Errorf("reverse at b: UTF16ToUTF8(%d) = %d, want %d", bUTF16, got, bUTF8)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapMultipleNonASCII(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Mix of 2-byte and 4-byte characters
|
||||
// "à" (U+00E0) = 2 bytes UTF-8, 1 code unit UTF-16 (delta +1)
|
||||
// "🎉" (U+1F389) = 4 bytes UTF-8, 2 code units UTF-16 (delta +2)
|
||||
text := "à🎉x"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
|
||||
// à: UTF-8 [0,2), UTF-16 [0,1)
|
||||
// 🎉: UTF-8 [2,6), UTF-16 [1,3)
|
||||
// x: UTF-8 [6,7), UTF-16 [3,4)
|
||||
tests := []struct {
|
||||
utf8 int
|
||||
utf16 int
|
||||
}{
|
||||
{0, 0},
|
||||
{2, 1}, // start of 🎉
|
||||
{6, 3}, // x
|
||||
{7, 4}, // end
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := pm.UTF8ToUTF16(tt.utf8); got != tt.utf16 {
|
||||
t.Errorf("UTF8ToUTF16(%d) = %d, want %d", tt.utf8, got, tt.utf16)
|
||||
}
|
||||
if got := pm.UTF16ToUTF8(tt.utf16); got != tt.utf8 {
|
||||
t.Errorf("UTF16ToUTF8(%d) = %d, want %d", tt.utf16, got, tt.utf8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapLoneSurrogateSentinel(t *testing.T) {
|
||||
t.Parallel()
|
||||
text := "a" + stringutil.EncodeJSStringRune(0xD800) + "b"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
if pm.IsAsciiOnly() {
|
||||
t.Fatal("expected non-ASCII")
|
||||
}
|
||||
|
||||
if got := pm.UTF8ToUTF16(len(text)); got != 3 {
|
||||
t.Errorf("UTF8ToUTF16(%d) = %d, want 3", len(text), got)
|
||||
}
|
||||
if got := pm.UTF16ToUTF8(2); got != len(text)-1 {
|
||||
t.Errorf("UTF16ToUTF8(2) = %d, want %d", got, len(text)-1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPositionMapRoundtrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
text := "let café = \"🎉\"; // naïve"
|
||||
pm := ast.ComputePositionMap(text)
|
||||
|
||||
// Convert every valid UTF-16 position to UTF-8 and back
|
||||
utf16Len := pm.UTF8ToUTF16(len(text))
|
||||
for i := 0; i <= utf16Len; i++ {
|
||||
utf8Pos := pm.UTF16ToUTF8(i)
|
||||
back := pm.UTF8ToUTF16(utf8Pos)
|
||||
if back != i {
|
||||
t.Errorf("roundtrip UTF16->UTF8->UTF16: %d -> %d -> %d", i, utf8Pos, back)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkComputePositionMap_ASCII(b *testing.B) {
|
||||
// ~10KB of ASCII TypeScript-like code
|
||||
line := "const variable = someFunction(argument1, argument2);\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
ast.ComputePositionMap(text)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkComputePositionMap_NonASCII(b *testing.B) {
|
||||
// Mix of ASCII and non-ASCII (comments with unicode)
|
||||
line := "const café = \"héllo wörld 🎉\";\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
ast.ComputePositionMap(text)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUTF8ToUTF16_ASCII(b *testing.B) {
|
||||
line := "const variable = someFunction(argument1, argument2);\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
pm := ast.ComputePositionMap(text)
|
||||
positions := []int{0, 100, 500, 1000, 5000, len(text) - 1}
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
for _, p := range positions {
|
||||
pm.UTF8ToUTF16(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUTF8ToUTF16_NonASCII(b *testing.B) {
|
||||
line := "const café = \"héllo wörld 🎉\";\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
pm := ast.ComputePositionMap(text)
|
||||
positions := []int{0, 100, 500, 1000, 5000, len(text) - 1}
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
for _, p := range positions {
|
||||
pm.UTF8ToUTF16(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUTF16ToUTF8_NonASCII(b *testing.B) {
|
||||
line := "const café = \"héllo wörld 🎉\";\n"
|
||||
text := strings.Repeat(line, 200)
|
||||
pm := ast.ComputePositionMap(text)
|
||||
utf16Len := pm.UTF8ToUTF16(len(text))
|
||||
positions := []int{0, 100, 500, 1000, 3000, utf16Len - 1}
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
for _, p := range positions {
|
||||
pm.UTF16ToUTF8(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkComputePositionMap_CheckerTS(b *testing.B) {
|
||||
data, err := os.ReadFile("../../_submodules/TypeScript/src/compiler/checker.ts")
|
||||
if err != nil {
|
||||
b.Skip("checker.ts not available:", err)
|
||||
}
|
||||
text := string(data)
|
||||
b.ResetTimer()
|
||||
for range b.N {
|
||||
ast.ComputePositionMap(text)
|
||||
}
|
||||
}
|
||||
717
tools/tsgo/internal/ast/precedence.go
Normal file
717
tools/tsgo/internal/ast/precedence.go
Normal file
@@ -0,0 +1,717 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type OperatorPrecedence int
|
||||
|
||||
const (
|
||||
// Expression:
|
||||
// AssignmentExpression
|
||||
// Expression `,` AssignmentExpression
|
||||
OperatorPrecedenceComma OperatorPrecedence = iota
|
||||
// NOTE: `Spread` is higher than `Comma` due to how it is parsed in |ElementList|
|
||||
// SpreadElement:
|
||||
// `...` AssignmentExpression
|
||||
OperatorPrecedenceSpread
|
||||
// AssignmentExpression:
|
||||
// ConditionalExpression
|
||||
// YieldExpression
|
||||
// ArrowFunction
|
||||
// AsyncArrowFunction
|
||||
// LeftHandSideExpression `=` AssignmentExpression
|
||||
// LeftHandSideExpression AssignmentOperator AssignmentExpression
|
||||
//
|
||||
// NOTE: AssignmentExpression is broken down into several precedences due to the requirements
|
||||
// of the parenthesizer rules.
|
||||
// AssignmentExpression: YieldExpression
|
||||
// YieldExpression:
|
||||
// `yield`
|
||||
// `yield` AssignmentExpression
|
||||
// `yield` `*` AssignmentExpression
|
||||
OperatorPrecedenceYield
|
||||
// AssignmentExpression: LeftHandSideExpression `=` AssignmentExpression
|
||||
// AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression
|
||||
// AssignmentOperator: one of
|
||||
// `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `|=` `**=`
|
||||
OperatorPrecedenceAssignment
|
||||
// NOTE: `Conditional` is considered higher than `Assignment` here, but in reality they have
|
||||
// the same precedence.
|
||||
// AssignmentExpression: ConditionalExpression
|
||||
// ConditionalExpression:
|
||||
// ShortCircuitExpression
|
||||
// ShortCircuitExpression `?` AssignmentExpression `:` AssignmentExpression
|
||||
OperatorPrecedenceConditional
|
||||
// LogicalORExpression:
|
||||
// LogicalANDExpression
|
||||
// LogicalORExpression `||` LogicalANDExpression
|
||||
OperatorPrecedenceLogicalOR
|
||||
// LogicalANDExpression:
|
||||
// BitwiseORExpression
|
||||
// LogicalANDExprerssion `&&` BitwiseORExpression
|
||||
OperatorPrecedenceLogicalAND
|
||||
// BitwiseORExpression:
|
||||
// BitwiseXORExpression
|
||||
// BitwiseORExpression `|` BitwiseXORExpression
|
||||
OperatorPrecedenceBitwiseOR
|
||||
// BitwiseXORExpression:
|
||||
// BitwiseANDExpression
|
||||
// BitwiseXORExpression `^` BitwiseANDExpression
|
||||
OperatorPrecedenceBitwiseXOR
|
||||
// BitwiseANDExpression:
|
||||
// EqualityExpression
|
||||
// BitwiseANDExpression `&` EqualityExpression
|
||||
OperatorPrecedenceBitwiseAND
|
||||
// EqualityExpression:
|
||||
// RelationalExpression
|
||||
// EqualityExpression `==` RelationalExpression
|
||||
// EqualityExpression `!=` RelationalExpression
|
||||
// EqualityExpression `===` RelationalExpression
|
||||
// EqualityExpression `!==` RelationalExpression
|
||||
OperatorPrecedenceEquality
|
||||
// RelationalExpression:
|
||||
// ShiftExpression
|
||||
// RelationalExpression `<` ShiftExpression
|
||||
// RelationalExpression `>` ShiftExpression
|
||||
// RelationalExpression `<=` ShiftExpression
|
||||
// RelationalExpression `>=` ShiftExpression
|
||||
// RelationalExpression `instanceof` ShiftExpression
|
||||
// RelationalExpression `in` ShiftExpression
|
||||
// [+TypeScript] RelationalExpression `as` Type
|
||||
OperatorPrecedenceRelational
|
||||
// ShiftExpression:
|
||||
// AdditiveExpression
|
||||
// ShiftExpression `<<` AdditiveExpression
|
||||
// ShiftExpression `>>` AdditiveExpression
|
||||
// ShiftExpression `>>>` AdditiveExpression
|
||||
OperatorPrecedenceShift
|
||||
// AdditiveExpression:
|
||||
// MultiplicativeExpression
|
||||
// AdditiveExpression `+` MultiplicativeExpression
|
||||
// AdditiveExpression `-` MultiplicativeExpression
|
||||
OperatorPrecedenceAdditive
|
||||
// MultiplicativeExpression:
|
||||
// ExponentiationExpression
|
||||
// MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
|
||||
// MultiplicativeOperator: one of `*`, `/`, `%`
|
||||
OperatorPrecedenceMultiplicative
|
||||
// ExponentiationExpression:
|
||||
// UnaryExpression
|
||||
// UpdateExpression `**` ExponentiationExpression
|
||||
OperatorPrecedenceExponentiation
|
||||
// UnaryExpression:
|
||||
// UpdateExpression
|
||||
// `delete` UnaryExpression
|
||||
// `void` UnaryExpression
|
||||
// `typeof` UnaryExpression
|
||||
// `+` UnaryExpression
|
||||
// `-` UnaryExpression
|
||||
// `~` UnaryExpression
|
||||
// `!` UnaryExpression
|
||||
// AwaitExpression
|
||||
// UpdateExpression: // TODO: Do we need to investigate the precedence here?
|
||||
// `++` UnaryExpression
|
||||
// `--` UnaryExpression
|
||||
OperatorPrecedenceUnary
|
||||
// UpdateExpression:
|
||||
// LeftHandSideExpression
|
||||
// LeftHandSideExpression `++`
|
||||
// LeftHandSideExpression `--`
|
||||
OperatorPrecedenceUpdate
|
||||
// LeftHandSideExpression:
|
||||
// NewExpression
|
||||
// NewExpression:
|
||||
// MemberExpression
|
||||
// `new` NewExpression
|
||||
OperatorPrecedenceLeftHandSide
|
||||
// LeftHandSideExpression:
|
||||
// OptionalExpression
|
||||
// OptionalExpression:
|
||||
// MemberExpression OptionalChain
|
||||
// CallExpression OptionalChain
|
||||
// OptionalExpression OptionalChain
|
||||
OperatorPrecedenceOptionalChain
|
||||
// LeftHandSideExpression:
|
||||
// CallExpression
|
||||
// CallExpression:
|
||||
// CoverCallExpressionAndAsyncArrowHead
|
||||
// SuperCall
|
||||
// ImportCall
|
||||
// CallExpression Arguments
|
||||
// CallExpression `[` Expression `]`
|
||||
// CallExpression `.` IdentifierName
|
||||
// CallExpression TemplateLiteral
|
||||
// MemberExpression:
|
||||
// PrimaryExpression
|
||||
// MemberExpression `[` Expression `]`
|
||||
// MemberExpression `.` IdentifierName
|
||||
// MemberExpression TemplateLiteral
|
||||
// SuperProperty
|
||||
// MetaProperty
|
||||
// `new` MemberExpression Arguments
|
||||
OperatorPrecedenceMember
|
||||
// TODO: JSXElement?
|
||||
// PrimaryExpression:
|
||||
// `this`
|
||||
// IdentifierReference
|
||||
// Literal
|
||||
// ArrayLiteral
|
||||
// ObjectLiteral
|
||||
// FunctionExpression
|
||||
// ClassExpression
|
||||
// GeneratorExpression
|
||||
// AsyncFunctionExpression
|
||||
// AsyncGeneratorExpression
|
||||
// RegularExpressionLiteral
|
||||
// TemplateLiteral
|
||||
OperatorPrecedencePrimary
|
||||
// PrimaryExpression:
|
||||
// CoverParenthesizedExpressionAndArrowParameterList
|
||||
OperatorPrecedenceParentheses
|
||||
OperatorPrecedenceLowest = OperatorPrecedenceComma
|
||||
OperatorPrecedenceHighest = OperatorPrecedenceParentheses
|
||||
OperatorPrecedenceDisallowComma = OperatorPrecedenceYield
|
||||
// ShortCircuitExpression:
|
||||
// LogicalORExpression
|
||||
// CoalesceExpression
|
||||
// CoalesceExpression:
|
||||
// CoalesceExpressionHead `??` BitwiseORExpression
|
||||
// CoalesceExpressionHead:
|
||||
// CoalesceExpression
|
||||
// BitwiseORExpression
|
||||
OperatorPrecedenceCoalesce = OperatorPrecedenceLogicalOR
|
||||
// -1 is lower than all other precedences. Returning it will cause binary expression
|
||||
// parsing to stop.
|
||||
OperatorPrecedenceInvalid OperatorPrecedence = -1
|
||||
)
|
||||
|
||||
func getOperator(expression *Expression) Kind {
|
||||
switch expression.Kind {
|
||||
case KindBinaryExpression:
|
||||
return expression.AsBinaryExpression().OperatorToken.Kind
|
||||
case KindPrefixUnaryExpression:
|
||||
return expression.AsPrefixUnaryExpression().Operator
|
||||
case KindPostfixUnaryExpression:
|
||||
return expression.AsPostfixUnaryExpression().Operator
|
||||
default:
|
||||
return expression.Kind
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the precedence of an expression
|
||||
func GetExpressionPrecedence(expression *Expression) OperatorPrecedence {
|
||||
operator := getOperator(expression)
|
||||
var flags OperatorPrecedenceFlags
|
||||
if expression.Kind == KindNewExpression && expression.ArgumentList() == nil {
|
||||
flags = OperatorPrecedenceFlagsNewWithoutArguments
|
||||
} else if IsOptionalChain(expression) {
|
||||
flags = OperatorPrecedenceFlagsOptionalChain
|
||||
}
|
||||
return GetOperatorPrecedence(expression.Kind, operator, flags)
|
||||
}
|
||||
|
||||
type OperatorPrecedenceFlags int
|
||||
|
||||
const (
|
||||
OperatorPrecedenceFlagsNone OperatorPrecedenceFlags = 0
|
||||
OperatorPrecedenceFlagsNewWithoutArguments OperatorPrecedenceFlags = 1 << 0
|
||||
OperatorPrecedenceFlagsOptionalChain OperatorPrecedenceFlags = 1 << 1
|
||||
)
|
||||
|
||||
// Gets the precedence of an operator
|
||||
func GetOperatorPrecedence(nodeKind Kind, operatorKind Kind, flags OperatorPrecedenceFlags) OperatorPrecedence {
|
||||
switch nodeKind {
|
||||
case KindSpreadElement:
|
||||
return OperatorPrecedenceSpread
|
||||
case KindYieldExpression:
|
||||
return OperatorPrecedenceYield
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindArrowFunction:
|
||||
return OperatorPrecedenceAssignment
|
||||
case KindConditionalExpression:
|
||||
return OperatorPrecedenceConditional
|
||||
case KindBinaryExpression:
|
||||
switch operatorKind {
|
||||
case KindCommaToken:
|
||||
return OperatorPrecedenceComma
|
||||
|
||||
case KindEqualsToken,
|
||||
KindPlusEqualsToken,
|
||||
KindMinusEqualsToken,
|
||||
KindAsteriskAsteriskEqualsToken,
|
||||
KindAsteriskEqualsToken,
|
||||
KindSlashEqualsToken,
|
||||
KindPercentEqualsToken,
|
||||
KindLessThanLessThanEqualsToken,
|
||||
KindGreaterThanGreaterThanEqualsToken,
|
||||
KindGreaterThanGreaterThanGreaterThanEqualsToken,
|
||||
KindAmpersandEqualsToken,
|
||||
KindCaretEqualsToken,
|
||||
KindBarEqualsToken,
|
||||
KindBarBarEqualsToken,
|
||||
KindAmpersandAmpersandEqualsToken,
|
||||
KindQuestionQuestionEqualsToken:
|
||||
return OperatorPrecedenceAssignment
|
||||
|
||||
default:
|
||||
return GetBinaryOperatorPrecedence(operatorKind)
|
||||
}
|
||||
// TODO: Should prefix `++` and `--` be moved to the `Update` precedence?
|
||||
case KindTypeAssertionExpression,
|
||||
KindNonNullExpression,
|
||||
KindPrefixUnaryExpression,
|
||||
KindTypeOfExpression,
|
||||
KindVoidExpression,
|
||||
KindDeleteExpression,
|
||||
KindAwaitExpression:
|
||||
return OperatorPrecedenceUnary
|
||||
|
||||
case KindPostfixUnaryExpression:
|
||||
return OperatorPrecedenceUpdate
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindPropertyAccessExpression, KindElementAccessExpression:
|
||||
if flags&OperatorPrecedenceFlagsOptionalChain != 0 {
|
||||
return OperatorPrecedenceOptionalChain
|
||||
}
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
case KindCallExpression:
|
||||
if flags&OperatorPrecedenceFlagsOptionalChain != 0 {
|
||||
return OperatorPrecedenceOptionalChain
|
||||
}
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindNewExpression:
|
||||
if flags&OperatorPrecedenceFlagsNewWithoutArguments != 0 {
|
||||
return OperatorPrecedenceLeftHandSide
|
||||
}
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to better align with ParenthesizerRules. consider backporting
|
||||
case KindTaggedTemplateExpression, KindMetaProperty, KindExpressionWithTypeArguments:
|
||||
return OperatorPrecedenceMember
|
||||
|
||||
case KindAsExpression,
|
||||
KindSatisfiesExpression:
|
||||
return OperatorPrecedenceRelational
|
||||
|
||||
case KindThisKeyword,
|
||||
KindSuperKeyword,
|
||||
KindImportKeyword,
|
||||
KindIdentifier,
|
||||
KindPrivateIdentifier,
|
||||
KindNullKeyword,
|
||||
KindTrueKeyword,
|
||||
KindFalseKeyword,
|
||||
KindNumericLiteral,
|
||||
KindBigIntLiteral,
|
||||
KindStringLiteral,
|
||||
KindArrayLiteralExpression,
|
||||
KindObjectLiteralExpression,
|
||||
KindFunctionExpression,
|
||||
KindClassExpression,
|
||||
KindRegularExpressionLiteral,
|
||||
KindNoSubstitutionTemplateLiteral,
|
||||
KindTemplateExpression,
|
||||
KindOmittedExpression,
|
||||
KindJsxElement,
|
||||
KindJsxSelfClosingElement,
|
||||
KindJsxFragment,
|
||||
KindMissingDeclaration:
|
||||
return OperatorPrecedencePrimary
|
||||
|
||||
// !!! By necessity, this differs from the old compiler to support emit. consider backporting
|
||||
case KindParenthesizedExpression:
|
||||
return OperatorPrecedenceParentheses
|
||||
|
||||
default:
|
||||
return OperatorPrecedenceInvalid
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the precedence of a binary operator
|
||||
func GetBinaryOperatorPrecedence(operatorKind Kind) OperatorPrecedence {
|
||||
switch operatorKind {
|
||||
case KindQuestionQuestionToken:
|
||||
return OperatorPrecedenceCoalesce
|
||||
case KindBarBarToken:
|
||||
return OperatorPrecedenceLogicalOR
|
||||
case KindAmpersandAmpersandToken:
|
||||
return OperatorPrecedenceLogicalAND
|
||||
case KindBarToken:
|
||||
return OperatorPrecedenceBitwiseOR
|
||||
case KindCaretToken:
|
||||
return OperatorPrecedenceBitwiseXOR
|
||||
case KindAmpersandToken:
|
||||
return OperatorPrecedenceBitwiseAND
|
||||
case KindEqualsEqualsToken, KindExclamationEqualsToken, KindEqualsEqualsEqualsToken, KindExclamationEqualsEqualsToken:
|
||||
return OperatorPrecedenceEquality
|
||||
case KindLessThanToken, KindGreaterThanToken, KindLessThanEqualsToken, KindGreaterThanEqualsToken,
|
||||
KindInstanceOfKeyword, KindInKeyword, KindAsKeyword, KindSatisfiesKeyword:
|
||||
return OperatorPrecedenceRelational
|
||||
case KindLessThanLessThanToken, KindGreaterThanGreaterThanToken, KindGreaterThanGreaterThanGreaterThanToken:
|
||||
return OperatorPrecedenceShift
|
||||
case KindPlusToken, KindMinusToken:
|
||||
return OperatorPrecedenceAdditive
|
||||
case KindAsteriskToken, KindSlashToken, KindPercentToken:
|
||||
return OperatorPrecedenceMultiplicative
|
||||
case KindAsteriskAsteriskToken:
|
||||
return OperatorPrecedenceExponentiation
|
||||
}
|
||||
// -1 is lower than all other precedences. Returning it will cause binary expression
|
||||
// parsing to stop.
|
||||
return OperatorPrecedenceInvalid
|
||||
}
|
||||
|
||||
// Gets the leftmost expression of an expression, e.g. `a` in `a.b`, `a[b]`, `a++`, `a+b`, `a?b:c`, `a as B`, etc.
|
||||
func GetLeftmostExpression(node *Expression, stopAtCallExpressions bool) *Expression {
|
||||
for {
|
||||
switch node.Kind {
|
||||
case KindPostfixUnaryExpression:
|
||||
node = node.AsPostfixUnaryExpression().Operand
|
||||
continue
|
||||
case KindBinaryExpression:
|
||||
node = node.AsBinaryExpression().Left
|
||||
continue
|
||||
case KindConditionalExpression:
|
||||
node = node.AsConditionalExpression().Condition
|
||||
continue
|
||||
case KindTaggedTemplateExpression:
|
||||
node = node.AsTaggedTemplateExpression().Tag
|
||||
continue
|
||||
case KindCallExpression:
|
||||
if stopAtCallExpressions {
|
||||
return node
|
||||
}
|
||||
fallthrough
|
||||
case KindAsExpression,
|
||||
KindElementAccessExpression,
|
||||
KindPropertyAccessExpression,
|
||||
KindNonNullExpression,
|
||||
KindPartiallyEmittedExpression,
|
||||
KindSatisfiesExpression:
|
||||
node = node.Expression()
|
||||
continue
|
||||
}
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
type TypePrecedence int32
|
||||
|
||||
const (
|
||||
// Conditional precedence (lowest)
|
||||
//
|
||||
// Type[Extends]:
|
||||
// ConditionalTypeNode[?Extends]
|
||||
//
|
||||
// ConditionalTypeNode[Extends]:
|
||||
// [~Extends] UnionTypeNode `extends` Type[+Extends] `?` Type[~Extends] `:` Type[~Extends]
|
||||
//
|
||||
TypePrecedenceConditional TypePrecedence = iota
|
||||
|
||||
// JSDoc precedence (optional and variadic types)
|
||||
//
|
||||
// JSDocType:
|
||||
// `...`? Type `=`?
|
||||
TypePrecedenceJSDoc
|
||||
|
||||
// Function precedence
|
||||
//
|
||||
// Type[Extends]:
|
||||
// ConditionalTypeNode[?Extends]
|
||||
// FunctionTypeNode[?Extends]
|
||||
// ConstructorTypeNode[?Extends]
|
||||
//
|
||||
// ConditionalTypeNode[Extends]:
|
||||
// UnionTypeNode
|
||||
//
|
||||
// FunctionTypeNode[Extends]:
|
||||
// TypeParameters? ArrowParameters `=>` Type[?Extends]
|
||||
//
|
||||
// ConstructorTypeNode[Extends]:
|
||||
// `abstract`? TypeParameters? ArrowParameters `=>` Type[?Extends]
|
||||
//
|
||||
TypePrecedenceFunction
|
||||
|
||||
// Union precedence
|
||||
//
|
||||
// UnionTypeNode:
|
||||
// `|`? UnionTypeNoBar
|
||||
//
|
||||
// UnionTypeNoBar:
|
||||
// IntersectionTypeNode
|
||||
// UnionTypeNoBar `|` IntersectionTypeNode
|
||||
//
|
||||
TypePrecedenceUnion
|
||||
|
||||
// Intersection precedence
|
||||
//
|
||||
// IntersectionTypeNode:
|
||||
// `&`? IntersectionTypeNoAmpersand
|
||||
//
|
||||
// IntersectionTypeNoAmpersand:
|
||||
// TypeOperatorNode
|
||||
// IntersectionTypeNoAmpersand `&` TypeOperatorNode
|
||||
//
|
||||
TypePrecedenceIntersection
|
||||
|
||||
// TypeOperatorNode precedence
|
||||
//
|
||||
// TypeOperatorNode:
|
||||
// PostfixType
|
||||
// InferTypeNode
|
||||
// `keyof` TypeOperatorNode
|
||||
// `unique` TypeOperatorNode
|
||||
// `readonly` PostfixType
|
||||
//
|
||||
// InferTypeNode:
|
||||
// `infer` BindingIdentifier
|
||||
// `infer` BindingIdentifier `extends` Type[+Extends]
|
||||
//
|
||||
TypePrecedenceTypeOperator
|
||||
|
||||
// Postfix precedence
|
||||
//
|
||||
// PostfixType:
|
||||
// NonArrayType
|
||||
// OptionalTypeNode
|
||||
// ArrayTypeNode
|
||||
// IndexedAccessTypeNode
|
||||
//
|
||||
// OptionalTypeNode:
|
||||
// PostfixType `?`
|
||||
//
|
||||
// ArrayTypeNode:
|
||||
// PostfixType `[` `]`
|
||||
//
|
||||
// IndexedAccessTypeNode:
|
||||
// PostfixType `[` Type[~Extends] `]`
|
||||
//
|
||||
TypePrecedencePostfix
|
||||
|
||||
// NonArray precedence (highest)
|
||||
//
|
||||
// NonArrayType:
|
||||
// KeywordType
|
||||
// LiteralTypeNode
|
||||
// ThisTypeNode
|
||||
// ImportType
|
||||
// TypeQueryNode
|
||||
// MappedTypeNode
|
||||
// TypeLiteralNode
|
||||
// TupleTypeNode
|
||||
// ParenthesizedTypeNode
|
||||
// TypePredicateNode
|
||||
// TypeReferenceNode
|
||||
// TemplateType
|
||||
//
|
||||
// KeywordType: one of
|
||||
// `any` `unknown` `string` `number` `bigint`
|
||||
// `symbol` `boolean` `undefined` `never` `object`
|
||||
// `intrinsic` `void`
|
||||
//
|
||||
// LiteralTypeNode:
|
||||
// StringLiteral
|
||||
// NoSubstitutionTemplateLiteral
|
||||
// NumericLiteral
|
||||
// BigIntLiteral
|
||||
// `-` NumericLiteral
|
||||
// `-` BigIntLiteral
|
||||
// `true`
|
||||
// `false`
|
||||
// `null`
|
||||
//
|
||||
// ThisTypeNode:
|
||||
// `this`
|
||||
//
|
||||
// ImportType:
|
||||
// `typeof`? `import` `(` Type[~Extends] `,`? `)` ImportTypeQualifier? TypeArguments?
|
||||
// `typeof`? `import` `(` Type[~Extends] `,` ImportTypeAttributes `,`? `)` ImportTypeQualifier? TypeArguments?
|
||||
//
|
||||
// ImportTypeQualifier:
|
||||
// `.` EntityName
|
||||
//
|
||||
// ImportTypeAttributes:
|
||||
// `{` `with` `:` ImportAttributes `,`? `}`
|
||||
//
|
||||
// TypeQueryNode:
|
||||
//
|
||||
// MappedTypeNode:
|
||||
// `{` MappedTypePrefix? MappedTypePropertyName MappedTypeSuffix? `:` Type[~Extends] `;` `}`
|
||||
//
|
||||
// MappedTypePrefix:
|
||||
// `readonly`
|
||||
// `+` `readonly`
|
||||
// `-` `readonly`
|
||||
//
|
||||
// MappedTypePropertyName:
|
||||
// `[` BindingIdentifier `in` Type[~Extends] `]`
|
||||
// `[` BindingIdentifier `in` Type[~Extends] `as` Type[~Extends] `]`
|
||||
//
|
||||
// MappedTypeSuffix:
|
||||
// `?`
|
||||
// `+` `?`
|
||||
// `-` `?`
|
||||
//
|
||||
// TypeLiteralNode:
|
||||
// `{` TypeElementList `}`
|
||||
//
|
||||
// TypeElementList:
|
||||
// [empty]
|
||||
// TypeElementList TypeElement
|
||||
//
|
||||
// TypeElement:
|
||||
// PropertySignatureDeclaration
|
||||
// MethodSignatureDeclaration
|
||||
// IndexSignatureDeclaration
|
||||
// CallSignatureDeclaration
|
||||
// ConstructSignatureDeclaration
|
||||
//
|
||||
// PropertySignatureDeclaration:
|
||||
// PropertyName `?`? TypeAnnotation? `;`
|
||||
//
|
||||
// MethodSignatureDeclaration:
|
||||
// PropertyName `?`? TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;`
|
||||
// `get` PropertyName TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;` // GetAccessorDeclaration
|
||||
// `set` PropertyName TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;` // SetAccessorDeclaration
|
||||
//
|
||||
// IndexSignatureDeclaration:
|
||||
// `[` IdentifierName`]` TypeAnnotation `;`
|
||||
//
|
||||
// CallSignatureDeclaration:
|
||||
// TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;`
|
||||
//
|
||||
// ConstructSignatureDeclaration:
|
||||
// `new` TypeParameters? `(` FormalParameterList `)` TypeAnnotation? `;`
|
||||
//
|
||||
// TupleTypeNode:
|
||||
// `[` `]`
|
||||
// `[` NamedTupleElementTypes `,`? `]`
|
||||
// `[` TupleElementTypes `,`? `]`
|
||||
//
|
||||
// NamedTupleElementTypes:
|
||||
// NamedTupleMember
|
||||
// NamedTupleElementTypes `,` NamedTupleMember
|
||||
//
|
||||
// NamedTupleMember:
|
||||
// IdentifierName `?`? `:` Type[~Extends]
|
||||
// `...` IdentifierName `:` Type[~Extends]
|
||||
//
|
||||
// TupleElementTypes:
|
||||
// TupleElementType
|
||||
// TupleElementTypes `,` TupleElementType
|
||||
//
|
||||
// TupleElementType:
|
||||
// Type[~Extends]
|
||||
// OptionalTypeNode
|
||||
// RestTypeNode
|
||||
//
|
||||
// RestTypeNode:
|
||||
// `...` Type[~Extends]
|
||||
//
|
||||
// ParenthesizedTypeNode:
|
||||
// `(` Type[~Extends] `)`
|
||||
//
|
||||
// TypePredicateNode:
|
||||
// `asserts`? TypePredicateParameterName
|
||||
// `asserts`? TypePredicateParameterName `is` Type[~Extends]
|
||||
//
|
||||
// TypePredicateParameterName:
|
||||
// `this`
|
||||
// IdentifierReference
|
||||
//
|
||||
// TypeReferenceNode:
|
||||
// EntityName TypeArguments?
|
||||
//
|
||||
// TemplateType:
|
||||
// TemplateHead Type[~Extends] TemplateTypeSpans
|
||||
//
|
||||
// TemplateTypeSpans:
|
||||
// TemplateTail
|
||||
// TemplateTypeMiddleList TemplateTail
|
||||
//
|
||||
// TemplateTypeMiddleList:
|
||||
// TemplateMiddle Type[~Extends]
|
||||
// TemplateTypeMiddleList TemplateMiddle Type[~Extends]
|
||||
//
|
||||
// TypeArguments:
|
||||
// `<` TypeArgumentList `,`? `>`
|
||||
//
|
||||
// TypeArgumentList:
|
||||
// Type[~Extends]
|
||||
// TypeArgumentList `,` Type[~Extends]
|
||||
//
|
||||
TypePrecedenceNonArray
|
||||
|
||||
TypePrecedenceLowest = TypePrecedenceConditional
|
||||
TypePrecedenceHighest = TypePrecedenceNonArray
|
||||
)
|
||||
|
||||
// Gets the precedence of a TypeNode
|
||||
func GetTypeNodePrecedence(n *TypeNode) TypePrecedence {
|
||||
switch n.Kind {
|
||||
case KindConditionalType:
|
||||
return TypePrecedenceConditional
|
||||
case KindJSDocOptionalType, KindJSDocVariadicType:
|
||||
return TypePrecedenceJSDoc
|
||||
case KindFunctionType, KindConstructorType:
|
||||
return TypePrecedenceFunction
|
||||
case KindUnionType:
|
||||
return TypePrecedenceUnion
|
||||
case KindIntersectionType:
|
||||
return TypePrecedenceIntersection
|
||||
case KindTypeOperator:
|
||||
return TypePrecedenceTypeOperator
|
||||
case KindInferType:
|
||||
if n.AsInferTypeNode().TypeParameter.AsTypeParameterDeclaration().Constraint != nil {
|
||||
// `infer T extends U` must be treated as FunctionTypeNode precedence as the `extends` clause eagerly consumes
|
||||
// TypeNode
|
||||
return TypePrecedenceFunction
|
||||
}
|
||||
return TypePrecedenceTypeOperator
|
||||
case KindIndexedAccessType, KindArrayType, KindOptionalType:
|
||||
return TypePrecedencePostfix
|
||||
case KindTypeQuery:
|
||||
// TypeQueryNode is actually a NonArrayType, but we treat it as TypeOperatorNode
|
||||
// precedence so that it is parenthesized when used in a PostfixType
|
||||
// context (e.g., `(typeof C)[]` instead of `typeof C[]`)
|
||||
return TypePrecedenceTypeOperator
|
||||
case KindAnyKeyword,
|
||||
KindUnknownKeyword,
|
||||
KindStringKeyword,
|
||||
KindNumberKeyword,
|
||||
KindBigIntKeyword,
|
||||
KindSymbolKeyword,
|
||||
KindBooleanKeyword,
|
||||
KindUndefinedKeyword,
|
||||
KindNeverKeyword,
|
||||
KindObjectKeyword,
|
||||
KindIntrinsicKeyword,
|
||||
KindVoidKeyword,
|
||||
KindJSDocAllType,
|
||||
KindJSDocNullableType,
|
||||
KindJSDocNonNullableType,
|
||||
KindLiteralType,
|
||||
KindTypePredicate,
|
||||
KindTypeReference,
|
||||
KindTypeLiteral,
|
||||
KindTupleType,
|
||||
KindRestType,
|
||||
KindParenthesizedType,
|
||||
KindThisType,
|
||||
KindMappedType,
|
||||
KindNamedTupleMember,
|
||||
KindTemplateLiteralType,
|
||||
KindImportType,
|
||||
// These occur in pseudo-types like `f<T>.C`, where `f` is a generic function and `C` is a local type
|
||||
KindPropertyAccessExpression,
|
||||
KindExpressionWithTypeArguments:
|
||||
return TypePrecedenceNonArray
|
||||
default:
|
||||
panic(fmt.Sprintf("unhandled TypeNode: %v", n.Kind))
|
||||
}
|
||||
}
|
||||
133
tools/tsgo/internal/ast/subtreefacts.go
Normal file
133
tools/tsgo/internal/ast/subtreefacts.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
)
|
||||
|
||||
type SubtreeFacts uint32
|
||||
|
||||
const (
|
||||
// Facts
|
||||
// - Flags used to indicate that a node or subtree contains syntax relevant to a specific transform
|
||||
|
||||
SubtreeContainsTypeScript SubtreeFacts = 1 << iota
|
||||
SubtreeContainsJsx
|
||||
SubtreeContainsESDecorators
|
||||
SubtreeContainsUsing
|
||||
SubtreeContainsClassStaticBlocks
|
||||
SubtreeContainsESClassFields
|
||||
SubtreeContainsLogicalAssignments
|
||||
SubtreeContainsNullishCoalescing
|
||||
SubtreeContainsOptionalChaining
|
||||
SubtreeContainsMissingCatchClauseVariable
|
||||
SubtreeContainsESObjectRestOrSpread // subtree has a `...` somewhere inside it, never cleared
|
||||
SubtreeContainsForAwaitOrAsyncGenerator
|
||||
SubtreeContainsAnyAwait
|
||||
SubtreeContainsExponentiationOperator
|
||||
|
||||
// Markers
|
||||
// - Flags used to indicate that a node or subtree contains a particular kind of syntax.
|
||||
|
||||
SubtreeContainsLexicalThis
|
||||
SubtreeContainsLexicalSuper
|
||||
SubtreeContainsRestOrSpread // marker on any `...` - cleared on binding pattern exit
|
||||
SubtreeContainsObjectRestOrSpread // marker on any `{...x}` - cleared on most scope exits
|
||||
SubtreeContainsAwait
|
||||
SubtreeContainsDynamicImport
|
||||
SubtreeContainsClassFields
|
||||
SubtreeContainsDecorators
|
||||
SubtreeContainsIdentifier
|
||||
SubtreeContainsPrivateIdentifierInExpression
|
||||
SubtreeContainsInvalidTemplateEscape
|
||||
|
||||
SubtreeFactsComputed // NOTE: This should always be last
|
||||
SubtreeFactsNone SubtreeFacts = 0
|
||||
|
||||
// Aliases (unused, for documentation purposes only - correspond to combinations in transformers/estransforms/definitions.go)
|
||||
|
||||
SubtreeContainsESNext = SubtreeContainsESDecorators | SubtreeContainsUsing
|
||||
SubtreeContainsES2022 = SubtreeContainsClassStaticBlocks | SubtreeContainsESClassFields
|
||||
SubtreeContainsES2021 = SubtreeContainsLogicalAssignments
|
||||
SubtreeContainsES2020 = SubtreeContainsNullishCoalescing | SubtreeContainsOptionalChaining
|
||||
SubtreeContainsES2019 = SubtreeContainsMissingCatchClauseVariable
|
||||
SubtreeContainsES2018 = SubtreeContainsESObjectRestOrSpread | SubtreeContainsForAwaitOrAsyncGenerator | SubtreeContainsInvalidTemplateEscape
|
||||
SubtreeContainsES2017 = SubtreeContainsAnyAwait
|
||||
SubtreeContainsES2016 = SubtreeContainsExponentiationOperator
|
||||
|
||||
// Scope Exclusions
|
||||
// - Bitmasks that exclude flags from propagating out of a specific context
|
||||
// into the subtree flags of their container.
|
||||
|
||||
SubtreeExclusionsNode = SubtreeFactsComputed
|
||||
SubtreeExclusionsEraseable = ^SubtreeContainsTypeScript
|
||||
SubtreeExclusionsOuterExpression = SubtreeExclusionsNode
|
||||
SubtreeExclusionsPropertyAccess = SubtreeExclusionsNode
|
||||
SubtreeExclusionsElementAccess = SubtreeExclusionsNode
|
||||
SubtreeExclusionsArrowFunction = SubtreeExclusionsNode | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsFunction = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsConstructor = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsMethod = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsAccessor = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper | SubtreeContainsAwait | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsProperty = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper
|
||||
SubtreeExclusionsClass = SubtreeExclusionsNode
|
||||
SubtreeExclusionsModule = SubtreeExclusionsNode | SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper
|
||||
SubtreeExclusionsObjectLiteral = SubtreeExclusionsNode | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsArrayLiteral = SubtreeExclusionsNode
|
||||
SubtreeExclusionsCall = SubtreeExclusionsNode
|
||||
SubtreeExclusionsNew = SubtreeExclusionsNode
|
||||
SubtreeExclusionsVariableDeclarationList = SubtreeExclusionsNode | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsParameter = SubtreeExclusionsNode
|
||||
SubtreeExclusionsCatchClause = SubtreeExclusionsNode | SubtreeContainsObjectRestOrSpread
|
||||
SubtreeExclusionsBindingPattern = SubtreeExclusionsNode | SubtreeContainsRestOrSpread
|
||||
|
||||
// Masks
|
||||
// - Additional bitmasks
|
||||
|
||||
SubtreeContainsLexicalThisOrSuper = SubtreeContainsLexicalThis | SubtreeContainsLexicalSuper
|
||||
)
|
||||
|
||||
func propagateEraseableSyntaxListSubtreeFacts(children *TypeArgumentList) SubtreeFacts {
|
||||
return core.IfElse(children != nil, SubtreeContainsTypeScript, SubtreeFactsNone)
|
||||
}
|
||||
|
||||
func propagateEraseableSyntaxSubtreeFacts(child *TypeNode) SubtreeFacts {
|
||||
return core.IfElse(child != nil, SubtreeContainsTypeScript, SubtreeFactsNone)
|
||||
}
|
||||
|
||||
func propagateObjectBindingElementSubtreeFacts(child *BindingElementNode) SubtreeFacts {
|
||||
facts := propagateSubtreeFacts(child)
|
||||
if facts&SubtreeContainsRestOrSpread != 0 {
|
||||
facts &^= SubtreeContainsRestOrSpread
|
||||
facts |= SubtreeContainsObjectRestOrSpread | SubtreeContainsESObjectRestOrSpread
|
||||
}
|
||||
return facts
|
||||
}
|
||||
|
||||
func propagateBindingElementSubtreeFacts(child *BindingElementNode) SubtreeFacts {
|
||||
return propagateSubtreeFacts(child) & ^SubtreeContainsRestOrSpread
|
||||
}
|
||||
|
||||
func propagateSubtreeFacts(child *Node) SubtreeFacts {
|
||||
if child == nil {
|
||||
return SubtreeFactsNone
|
||||
}
|
||||
return child.propagateSubtreeFacts()
|
||||
}
|
||||
|
||||
func propagateNodeListSubtreeFacts(children *NodeList, propagate func(*Node) SubtreeFacts) SubtreeFacts {
|
||||
if children == nil {
|
||||
return SubtreeFactsNone
|
||||
}
|
||||
facts := SubtreeFactsNone
|
||||
for _, child := range children.Nodes {
|
||||
facts |= propagate(child)
|
||||
}
|
||||
return facts
|
||||
}
|
||||
|
||||
func propagateModifierListSubtreeFacts(children *ModifierList) SubtreeFacts {
|
||||
if children == nil {
|
||||
return SubtreeFactsNone
|
||||
}
|
||||
return propagateNodeListSubtreeFacts(&children.NodeList, propagateSubtreeFacts)
|
||||
}
|
||||
103
tools/tsgo/internal/ast/symbol.go
Normal file
103
tools/tsgo/internal/ast/symbol.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Symbol
|
||||
|
||||
type Symbol struct {
|
||||
Flags SymbolFlags
|
||||
CheckFlags CheckFlags // Non-zero only in transient symbols created by Checker
|
||||
Name string
|
||||
Declarations []*Node
|
||||
ValueDeclaration *Node
|
||||
Members SymbolTable
|
||||
Exports SymbolTable
|
||||
id atomic.Uint64
|
||||
Parent *Symbol
|
||||
ExportSymbol *Symbol
|
||||
}
|
||||
|
||||
func (s *Symbol) IsExternalModule() bool {
|
||||
return s.Flags&SymbolFlagsModule != 0 && len(s.Name) > 0 && s.Name[0] == '"'
|
||||
}
|
||||
|
||||
func (s *Symbol) IsStatic() bool {
|
||||
if s.ValueDeclaration == nil {
|
||||
return false
|
||||
}
|
||||
modifierFlags := s.ValueDeclaration.ModifierFlags()
|
||||
return modifierFlags&ModifierFlagsStatic != 0
|
||||
}
|
||||
|
||||
// See comment on `declareModuleMember` in `binder.go`.
|
||||
func (s *Symbol) CombinedLocalAndExportSymbolFlags() SymbolFlags {
|
||||
if s.ExportSymbol != nil {
|
||||
return s.Flags | s.ExportSymbol.Flags
|
||||
}
|
||||
return s.Flags
|
||||
}
|
||||
|
||||
// SymbolTable
|
||||
|
||||
type SymbolTable map[string]*Symbol
|
||||
|
||||
const InternalSymbolNamePrefix = "\xFE" // Invalid UTF8 sequence, will never occur as IdentifierName
|
||||
|
||||
const (
|
||||
InternalSymbolNameCall = InternalSymbolNamePrefix + "call" // Call signatures
|
||||
InternalSymbolNameConstructor = InternalSymbolNamePrefix + "constructor" // Constructor implementations
|
||||
InternalSymbolNameNew = InternalSymbolNamePrefix + "new" // Constructor signatures
|
||||
InternalSymbolNameIndex = InternalSymbolNamePrefix + "index" // Index signatures
|
||||
InternalSymbolNameExportStar = InternalSymbolNamePrefix + "export" // Module export * declarations
|
||||
InternalSymbolNameGlobal = InternalSymbolNamePrefix + "global" // Global self-reference
|
||||
InternalSymbolNameMissing = InternalSymbolNamePrefix + "missing" // Indicates missing symbol
|
||||
InternalSymbolNameType = InternalSymbolNamePrefix + "type" // Anonymous type literal symbol
|
||||
InternalSymbolNameObject = InternalSymbolNamePrefix + "object" // Anonymous object literal declaration
|
||||
InternalSymbolNameJSXAttributes = InternalSymbolNamePrefix + "jsxAttributes" // Anonymous JSX attributes object literal declaration
|
||||
InternalSymbolNameClass = InternalSymbolNamePrefix + "class" // Unnamed class expression
|
||||
InternalSymbolNameFunction = InternalSymbolNamePrefix + "function" // Unnamed function expression
|
||||
InternalSymbolNameComputed = InternalSymbolNamePrefix + "computed" // Computed property name declaration with dynamic name
|
||||
InternalSymbolNameAssignmentDeclaration = InternalSymbolNamePrefix + "assignment" // Assignment declarations
|
||||
InternalSymbolNameInstantiationExpression = InternalSymbolNamePrefix + "instantiationExpression" // Instantiation expressions
|
||||
InternalSymbolNameImportAttributes = InternalSymbolNamePrefix + "importAttributes"
|
||||
InternalSymbolNameExportEquals = "export=" // Export assignment symbol
|
||||
InternalSymbolNameDefault = "default" // Default export symbol (technically not wholly internal, but included here for usability)
|
||||
InternalSymbolNameThis = "this"
|
||||
InternalSymbolNameModuleExports = "module.exports"
|
||||
)
|
||||
|
||||
func SymbolName(symbol *Symbol) string {
|
||||
if symbol.ValueDeclaration != nil && IsPrivateIdentifierClassElementDeclaration(symbol.ValueDeclaration) {
|
||||
return symbol.ValueDeclaration.Name().Text()
|
||||
}
|
||||
return symbol.Name
|
||||
}
|
||||
|
||||
// EscapeAllInternalSymbolNames replaces internal symbol name markers ("\xFE") with "__".
|
||||
func EscapeAllInternalSymbolNames(name string) string {
|
||||
return strings.ReplaceAll(name, InternalSymbolNamePrefix, "__")
|
||||
}
|
||||
|
||||
func EscapeInternalSymbolName(name string) string {
|
||||
if rest, ok := strings.CutPrefix(name, InternalSymbolNamePrefix); ok {
|
||||
return "__" + rest
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// EscapeSymbolName converts a binder symbol name into its escaped "__String"
|
||||
// form. Internal names (prefixed with the "\xFE" sentinel) become "__"-prefixed,
|
||||
// and user names that already begin with "__" gain an extra leading underscore
|
||||
// so they can be distinguished from internal names.
|
||||
func EscapeSymbolName(name string) string {
|
||||
if rest, ok := strings.CutPrefix(name, InternalSymbolNamePrefix); ok {
|
||||
return "__" + rest
|
||||
}
|
||||
if len(name) >= 2 && name[0] == '_' && name[1] == '_' {
|
||||
return "_" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
86
tools/tsgo/internal/ast/symbolflags.go
Normal file
86
tools/tsgo/internal/ast/symbolflags.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package ast
|
||||
|
||||
// SymbolFlags
|
||||
|
||||
type SymbolFlags uint32
|
||||
|
||||
const (
|
||||
SymbolFlagsNone SymbolFlags = 0
|
||||
SymbolFlagsFunctionScopedVariable SymbolFlags = 1 << 0 // Variable (var) or parameter
|
||||
SymbolFlagsBlockScopedVariable SymbolFlags = 1 << 1 // A block-scoped variable (let or const)
|
||||
SymbolFlagsProperty SymbolFlags = 1 << 2 // Property or enum member
|
||||
SymbolFlagsEnumMember SymbolFlags = 1 << 3 // Enum member
|
||||
SymbolFlagsFunction SymbolFlags = 1 << 4 // Function
|
||||
SymbolFlagsClass SymbolFlags = 1 << 5 // Class
|
||||
SymbolFlagsInterface SymbolFlags = 1 << 6 // Interface
|
||||
SymbolFlagsConstEnum SymbolFlags = 1 << 7 // Const enum
|
||||
SymbolFlagsRegularEnum SymbolFlags = 1 << 8 // Enum
|
||||
SymbolFlagsValueModule SymbolFlags = 1 << 9 // Instantiated module
|
||||
SymbolFlagsNamespaceModule SymbolFlags = 1 << 10 // Uninstantiated module
|
||||
SymbolFlagsTypeLiteral SymbolFlags = 1 << 11 // Type Literal or mapped type
|
||||
SymbolFlagsObjectLiteral SymbolFlags = 1 << 12 // Object Literal
|
||||
SymbolFlagsMethod SymbolFlags = 1 << 13 // Method
|
||||
SymbolFlagsConstructor SymbolFlags = 1 << 14 // Constructor
|
||||
SymbolFlagsGetAccessor SymbolFlags = 1 << 15 // Get accessor
|
||||
SymbolFlagsSetAccessor SymbolFlags = 1 << 16 // Set accessor
|
||||
SymbolFlagsSignature SymbolFlags = 1 << 17 // Call, construct, or index signature
|
||||
SymbolFlagsTypeParameter SymbolFlags = 1 << 18 // Type parameter
|
||||
SymbolFlagsTypeAlias SymbolFlags = 1 << 19 // Type alias
|
||||
SymbolFlagsExportValue SymbolFlags = 1 << 20 // Exported value marker (see comment in declareModuleMember in binder)
|
||||
SymbolFlagsAlias SymbolFlags = 1 << 21 // An alias for another symbol (see comment in isAliasSymbolDeclaration in checker)
|
||||
SymbolFlagsPrototype SymbolFlags = 1 << 22 // Prototype property (no source representation)
|
||||
SymbolFlagsExportStar SymbolFlags = 1 << 23 // Export * declaration
|
||||
SymbolFlagsOptional SymbolFlags = 1 << 24 // Optional property
|
||||
SymbolFlagsTransient SymbolFlags = 1 << 25 // Transient symbol (created during type check)
|
||||
SymbolFlagsAssignment SymbolFlags = 1 << 26 // Assignment to property on function acting as declaration (eg `func.prop = 1`)
|
||||
SymbolFlagsModuleExports SymbolFlags = 1 << 27 // Symbol for CommonJS `module` of `module.exports`
|
||||
SymbolFlagsConstEnumOnlyModule SymbolFlags = 1 << 28 // Module contains only const enums or other modules with only const enums
|
||||
SymbolFlagsReplaceableByMethod SymbolFlags = 1 << 29
|
||||
SymbolFlagsGlobalLookup SymbolFlags = 1 << 30 // Flag to signal this is a global lookup
|
||||
SymbolFlagsAll SymbolFlags = 1<<30 - 1 // All flags except SymbolFlagsGlobalLookup
|
||||
|
||||
SymbolFlagsEnum = SymbolFlagsRegularEnum | SymbolFlagsConstEnum
|
||||
SymbolFlagsVariable = SymbolFlagsFunctionScopedVariable | SymbolFlagsBlockScopedVariable
|
||||
SymbolFlagsValue = SymbolFlagsVariable | SymbolFlagsProperty | SymbolFlagsEnumMember | SymbolFlagsObjectLiteral | SymbolFlagsFunction | SymbolFlagsClass | SymbolFlagsEnum | SymbolFlagsValueModule | SymbolFlagsMethod | SymbolFlagsGetAccessor | SymbolFlagsSetAccessor
|
||||
SymbolFlagsType = SymbolFlagsClass | SymbolFlagsInterface | SymbolFlagsEnum | SymbolFlagsEnumMember | SymbolFlagsTypeLiteral | SymbolFlagsTypeParameter | SymbolFlagsTypeAlias
|
||||
SymbolFlagsNamespace = SymbolFlagsValueModule | SymbolFlagsNamespaceModule | SymbolFlagsEnum
|
||||
SymbolFlagsModule = SymbolFlagsValueModule | SymbolFlagsNamespaceModule
|
||||
SymbolFlagsAccessor = SymbolFlagsGetAccessor | SymbolFlagsSetAccessor
|
||||
|
||||
// Variables can be redeclared, but can not redeclare a block-scoped declaration with the
|
||||
// same name, or any other value that is not a variable, e.g. ValueModule or Class
|
||||
SymbolFlagsFunctionScopedVariableExcludes = SymbolFlagsValue & ^SymbolFlagsFunctionScopedVariable
|
||||
|
||||
// Block-scoped declarations are not allowed to be re-declared
|
||||
// they can not merge with anything in the value space
|
||||
SymbolFlagsBlockScopedVariableExcludes = SymbolFlagsValue
|
||||
|
||||
SymbolFlagsParameterExcludes = SymbolFlagsValue
|
||||
SymbolFlagsPropertyExcludes = SymbolFlagsValue & ^(SymbolFlagsProperty | SymbolFlagsAccessor)
|
||||
SymbolFlagsEnumMemberExcludes = SymbolFlagsValue | SymbolFlagsType
|
||||
SymbolFlagsFunctionExcludes = SymbolFlagsValue & ^(SymbolFlagsFunction | SymbolFlagsValueModule | SymbolFlagsClass)
|
||||
SymbolFlagsClassExcludes = (SymbolFlagsValue | SymbolFlagsType) & ^(SymbolFlagsValueModule | SymbolFlagsInterface | SymbolFlagsFunction) // class-interface mergability done in checker.ts
|
||||
SymbolFlagsInterfaceExcludes = SymbolFlagsType & ^(SymbolFlagsInterface | SymbolFlagsClass)
|
||||
SymbolFlagsRegularEnumExcludes = (SymbolFlagsValue | SymbolFlagsType) & ^(SymbolFlagsRegularEnum | SymbolFlagsValueModule) // regular enums merge only with regular enums and modules
|
||||
SymbolFlagsConstEnumExcludes = (SymbolFlagsValue | SymbolFlagsType) & ^SymbolFlagsConstEnum // const enums merge only with const enums
|
||||
SymbolFlagsValueModuleExcludes = SymbolFlagsValue & ^(SymbolFlagsFunction | SymbolFlagsClass | SymbolFlagsRegularEnum | SymbolFlagsValueModule)
|
||||
SymbolFlagsNamespaceModuleExcludes = SymbolFlagsNone
|
||||
SymbolFlagsMethodExcludes = SymbolFlagsValue & ^SymbolFlagsMethod
|
||||
SymbolFlagsGetAccessorExcludes = SymbolFlagsValue & ^(SymbolFlagsSetAccessor | SymbolFlagsProperty)
|
||||
SymbolFlagsSetAccessorExcludes = SymbolFlagsValue & ^(SymbolFlagsGetAccessor | SymbolFlagsProperty)
|
||||
SymbolFlagsAccessorExcludes = SymbolFlagsValue & ^SymbolFlagsProperty
|
||||
SymbolFlagsTypeParameterExcludes = SymbolFlagsType & ^SymbolFlagsTypeParameter
|
||||
SymbolFlagsTypeAliasExcludes = SymbolFlagsType
|
||||
SymbolFlagsAliasExcludes = SymbolFlagsAlias
|
||||
SymbolFlagsModuleMember = SymbolFlagsVariable | SymbolFlagsFunction | SymbolFlagsClass | SymbolFlagsInterface | SymbolFlagsEnum | SymbolFlagsModule | SymbolFlagsTypeAlias | SymbolFlagsAlias
|
||||
SymbolFlagsExportHasLocal = SymbolFlagsFunction | SymbolFlagsClass | SymbolFlagsEnum | SymbolFlagsValueModule
|
||||
SymbolFlagsBlockScoped = SymbolFlagsBlockScopedVariable | SymbolFlagsClass | SymbolFlagsEnum
|
||||
SymbolFlagsPropertyOrAccessor = SymbolFlagsProperty | SymbolFlagsAccessor
|
||||
SymbolFlagsClassMember = SymbolFlagsMethod | SymbolFlagsAccessor | SymbolFlagsProperty
|
||||
SymbolFlagsExportSupportsDefaultModifier = SymbolFlagsClass | SymbolFlagsFunction | SymbolFlagsInterface
|
||||
SymbolFlagsExportDoesNotSupportDefaultModifier = ^SymbolFlagsExportSupportsDefaultModifier
|
||||
// The set of things we consider semantically classifiable. Used to speed up the LS during
|
||||
// classification.
|
||||
SymbolFlagsClassifiable = SymbolFlagsClass | SymbolFlagsEnum | SymbolFlagsTypeAlias | SymbolFlagsInterface | SymbolFlagsTypeParameter | SymbolFlagsModule | SymbolFlagsAlias
|
||||
SymbolFlagsLateBindingContainer = SymbolFlagsClass | SymbolFlagsInterface | SymbolFlagsTypeLiteral | SymbolFlagsObjectLiteral | SymbolFlagsFunction
|
||||
)
|
||||
33
tools/tsgo/internal/ast/tokenflags.go
Normal file
33
tools/tsgo/internal/ast/tokenflags.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package ast
|
||||
|
||||
type TokenFlags int32
|
||||
|
||||
const (
|
||||
TokenFlagsNone TokenFlags = 0
|
||||
TokenFlagsPrecedingLineBreak TokenFlags = 1 << 0
|
||||
TokenFlagsPrecedingJSDocComment TokenFlags = 1 << 1
|
||||
TokenFlagsUnterminated TokenFlags = 1 << 2
|
||||
TokenFlagsExtendedUnicodeEscape TokenFlags = 1 << 3 // e.g. `\u{10ffff}`
|
||||
TokenFlagsScientific TokenFlags = 1 << 4 // e.g. `10e2`
|
||||
TokenFlagsOctal TokenFlags = 1 << 5 // e.g. `0777`
|
||||
TokenFlagsHexSpecifier TokenFlags = 1 << 6 // e.g. `0x00000000`
|
||||
TokenFlagsBinarySpecifier TokenFlags = 1 << 7 // e.g. `0b0110010000000000`
|
||||
TokenFlagsOctalSpecifier TokenFlags = 1 << 8 // e.g. `0o777`
|
||||
TokenFlagsContainsSeparator TokenFlags = 1 << 9 // e.g. `0b1100_0101`
|
||||
TokenFlagsUnicodeEscape TokenFlags = 1 << 10 // e.g. `\u00a0`
|
||||
TokenFlagsContainsInvalidEscape TokenFlags = 1 << 11 // e.g. `\uhello`
|
||||
TokenFlagsHexEscape TokenFlags = 1 << 12 // e.g. `\xa0`
|
||||
TokenFlagsContainsLeadingZero TokenFlags = 1 << 13 // e.g. `0888`
|
||||
TokenFlagsContainsInvalidSeparator TokenFlags = 1 << 14 // e.g. `0_1`
|
||||
TokenFlagsPrecedingJSDocLeadingAsterisks TokenFlags = 1 << 15
|
||||
TokenFlagsSingleQuote TokenFlags = 1 << 16 // e.g. `'abc'`
|
||||
TokenFlagsPrecedingJSDocWithDeprecated TokenFlags = 1 << 17 // Preceding JSDoc comment contains @deprecated
|
||||
TokenFlagsPrecedingJSDocWithSeeOrLink TokenFlags = 1 << 18 // Preceding JSDoc comment contains @see or @link
|
||||
TokenFlagsBinaryOrOctalSpecifier TokenFlags = TokenFlagsBinarySpecifier | TokenFlagsOctalSpecifier
|
||||
TokenFlagsWithSpecifier TokenFlags = TokenFlagsHexSpecifier | TokenFlagsBinaryOrOctalSpecifier
|
||||
TokenFlagsStringLiteralFlags TokenFlags = TokenFlagsUnterminated | TokenFlagsHexEscape | TokenFlagsUnicodeEscape | TokenFlagsExtendedUnicodeEscape | TokenFlagsContainsInvalidEscape | TokenFlagsSingleQuote
|
||||
TokenFlagsNumericLiteralFlags TokenFlags = TokenFlagsScientific | TokenFlagsOctal | TokenFlagsContainsLeadingZero | TokenFlagsWithSpecifier | TokenFlagsContainsSeparator | TokenFlagsContainsInvalidSeparator
|
||||
TokenFlagsTemplateLiteralLikeFlags TokenFlags = TokenFlagsUnterminated | TokenFlagsHexEscape | TokenFlagsUnicodeEscape | TokenFlagsExtendedUnicodeEscape | TokenFlagsContainsInvalidEscape
|
||||
TokenFlagsRegularExpressionLiteralFlags TokenFlags = TokenFlagsUnterminated
|
||||
TokenFlagsIsInvalid TokenFlags = TokenFlagsOctal | TokenFlagsContainsLeadingZero | TokenFlagsContainsInvalidSeparator | TokenFlagsContainsInvalidEscape
|
||||
)
|
||||
4565
tools/tsgo/internal/ast/utilities.go
Normal file
4565
tools/tsgo/internal/ast/utilities.go
Normal file
File diff suppressed because it is too large
Load Diff
278
tools/tsgo/internal/ast/visitor.go
Normal file
278
tools/tsgo/internal/ast/visitor.go
Normal file
@@ -0,0 +1,278 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"slices"
|
||||
)
|
||||
|
||||
// NodeVisitor
|
||||
|
||||
type NodeVisitor struct {
|
||||
Visit func(node *Node) *Node // Required. The callback used to visit a node
|
||||
Factory *NodeFactory // Required. The NodeFactory used to produce new nodes when passed to VisitEachChild
|
||||
Hooks NodeVisitorHooks // Hooks to be invoked when visiting a node
|
||||
}
|
||||
|
||||
// These hooks are used to intercept the default behavior of the visitor
|
||||
type NodeVisitorHooks struct {
|
||||
VisitNode func(node *Node, v *NodeVisitor) *Node // Overrides visiting a Node. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitToken func(node *TokenNode, v *NodeVisitor) *Node // Overrides visiting a TokenNode. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitNodes func(nodes *NodeList, v *NodeVisitor) *NodeList // Overrides visiting a NodeList. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitModifiers func(nodes *ModifierList, v *NodeVisitor) *ModifierList // Overrides visiting a ModifierList. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitEmbeddedStatement func(node *Statement, v *NodeVisitor) *Statement // Overrides visiting a Node when it is the embedded statement body of an iteration statement, `if` statement, or `with` statement. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitIterationBody func(node *Statement, v *NodeVisitor) *Statement // Overrides visiting a Node when it is the embedded statement body of an iteration statement. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitParameters func(nodes *ParameterList, v *NodeVisitor) *ParameterList // Overrides visiting a ParameterList. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitFunctionBody func(node *BlockOrExpression, v *NodeVisitor) *BlockOrExpression // Overrides visiting a function body. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
VisitTopLevelStatements func(nodes *StatementList, v *NodeVisitor) *StatementList // Overrides visiting a variable environment. Only invoked by the VisitEachChild method on a given Node subtype.
|
||||
}
|
||||
|
||||
func NewNodeVisitor(visit func(node *Node) *Node, factory *NodeFactory, hooks NodeVisitorHooks) *NodeVisitor {
|
||||
if factory == nil {
|
||||
factory = &NodeFactory{}
|
||||
}
|
||||
return &NodeVisitor{Visit: visit, Factory: factory, Hooks: hooks}
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) VisitSourceFile(node *SourceFile) *SourceFile {
|
||||
return v.VisitNode(node.AsNode()).AsSourceFile()
|
||||
}
|
||||
|
||||
// Visits a Node, possibly returning a new Node in its place.
|
||||
//
|
||||
// - If the input node is nil, then the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, then the output is nil.
|
||||
// - If v.Visit returns a SyntaxList Node, then the output is the only child of the SyntaxList Node.
|
||||
func (v *NodeVisitor) VisitNode(node *Node) *Node {
|
||||
if node == nil || v.Visit == nil {
|
||||
return node
|
||||
}
|
||||
|
||||
if v.Visit != nil {
|
||||
visited := v.Visit(node)
|
||||
if visited != nil && visited.Kind == KindSyntaxList {
|
||||
nodes := visited.AsSyntaxList().Children
|
||||
if len(nodes) != 1 {
|
||||
panic("Expected only a single node to be written to output")
|
||||
}
|
||||
visited = nodes[0]
|
||||
if visited != nil && visited.Kind == KindSyntaxList {
|
||||
panic("The result of visiting and lifting a Node may not be SyntaxList")
|
||||
}
|
||||
}
|
||||
return visited
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
// Visits an embedded Statement (i.e., the single statement body of a loop, `if..else` branch, etc.), possibly returning a new Statement in its place.
|
||||
//
|
||||
// - If the input node is nil, then the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, then the output is nil.
|
||||
// - If v.Visit returns a SyntaxList Node, then the output is either the only child of the SyntaxList Node, or a Block containing the nodes in the list.
|
||||
func (v *NodeVisitor) VisitEmbeddedStatement(node *Statement) *Statement {
|
||||
if node == nil || v.Visit == nil {
|
||||
return node
|
||||
}
|
||||
|
||||
visited := v.Visit(node)
|
||||
if visited == nil {
|
||||
return nil
|
||||
}
|
||||
return v.liftToBlock(visited)
|
||||
}
|
||||
|
||||
// Visits a NodeList, possibly returning a new NodeList in its place.
|
||||
//
|
||||
// - If the input NodeList is nil, the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, the visited Node will be absent in the output.
|
||||
// - If v.Visit returns a different Node than the input, a new NodeList will be generated and returned.
|
||||
// - If v.Visit returns a SyntaxList Node, then the children of that node will be merged into the output and a new NodeList will be returned.
|
||||
// - If this method returns a new NodeList for any reason, it will have the same Loc as the input NodeList.
|
||||
func (v *NodeVisitor) VisitNodes(nodes *NodeList) *NodeList {
|
||||
if nodes == nil || v.Visit == nil {
|
||||
return nodes
|
||||
}
|
||||
|
||||
if result, changed := v.VisitSlice(nodes.Nodes); changed {
|
||||
list := v.Factory.NewNodeList(result)
|
||||
list.Loc = nodes.Loc
|
||||
return list
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
// Visits a ModifierList, possibly returning a new ModifierList in its place.
|
||||
//
|
||||
// - If the input ModifierList is nil, the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, the visited Node will be absent in the output.
|
||||
// - If v.Visit returns a different Node than the input, a new ModifierList will be generated and returned.
|
||||
// - If v.Visit returns a SyntaxList Node, then the children of that node will be merged into the output and a new NodeList will be returned.
|
||||
// - If this method returns a new NodeList for any reason, it will have the same Loc as the input NodeList.
|
||||
func (v *NodeVisitor) VisitModifiers(nodes *ModifierList) *ModifierList {
|
||||
if nodes == nil || v.Visit == nil {
|
||||
return nodes
|
||||
}
|
||||
|
||||
if result, changed := v.VisitSlice(nodes.Nodes); changed {
|
||||
list := v.Factory.NewModifierList(result)
|
||||
list.Loc = nodes.Loc
|
||||
return list
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
// Visits a slice of Nodes, returning the resulting slice and a value indicating whether the slice was changed.
|
||||
//
|
||||
// - If the input slice is nil, the output is nil.
|
||||
// - If v.Visit is nil, then the output is the input.
|
||||
// - If v.Visit returns nil, the visited Node will be absent in the output.
|
||||
// - If v.Visit returns a different Node than the input, a new slice will be generated and returned.
|
||||
// - If v.Visit returns a SyntaxList Node, then the children of that node will be merged into the output and a new slice will be returned.
|
||||
func (v *NodeVisitor) VisitSlice(nodes []*Node) (result []*Node, changed bool) {
|
||||
if nodes == nil || v.Visit == nil {
|
||||
return nodes, false
|
||||
}
|
||||
|
||||
for i := 0; i < len(nodes); i++ {
|
||||
node := nodes[i]
|
||||
if v.Visit == nil {
|
||||
break
|
||||
}
|
||||
|
||||
visited := v.Visit(node)
|
||||
if visited == nil || visited != node {
|
||||
updated := slices.Clone(nodes[:i])
|
||||
|
||||
for {
|
||||
// finish prior loop
|
||||
switch {
|
||||
case visited == nil: // do nothing
|
||||
case visited.Kind == KindSyntaxList:
|
||||
updated = append(updated, visited.AsSyntaxList().Children...)
|
||||
default:
|
||||
updated = append(updated, visited)
|
||||
}
|
||||
|
||||
i++
|
||||
|
||||
// loop over remaining elements
|
||||
if i >= len(nodes) {
|
||||
break
|
||||
}
|
||||
|
||||
if v.Visit != nil {
|
||||
node = nodes[i]
|
||||
visited = v.Visit(node)
|
||||
} else {
|
||||
updated = append(updated, nodes[i:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return updated, true
|
||||
}
|
||||
}
|
||||
|
||||
return nodes, false
|
||||
}
|
||||
|
||||
// Visits each child of a Node, possibly returning a new Node of the same kind in its place.
|
||||
func (v *NodeVisitor) VisitEachChild(node *Node) *Node {
|
||||
if node == nil || v.Visit == nil {
|
||||
return node
|
||||
}
|
||||
|
||||
return node.VisitEachChild(v)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitNode(node *Node) *Node {
|
||||
if v.Hooks.VisitNode != nil {
|
||||
return v.Hooks.VisitNode(node, v)
|
||||
}
|
||||
return v.VisitNode(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitEmbeddedStatement(node *Node) *Node {
|
||||
if v.Hooks.VisitEmbeddedStatement != nil {
|
||||
return v.Hooks.VisitEmbeddedStatement(node, v)
|
||||
}
|
||||
if v.Hooks.VisitNode != nil {
|
||||
return v.liftToBlock(v.Hooks.VisitNode(node, v))
|
||||
}
|
||||
return v.VisitEmbeddedStatement(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitIterationBody(node *Statement) *Statement {
|
||||
if v.Hooks.VisitIterationBody != nil {
|
||||
return v.Hooks.VisitIterationBody(node, v)
|
||||
}
|
||||
return v.visitEmbeddedStatement(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitFunctionBody(node *BlockOrExpression) *BlockOrExpression {
|
||||
if v.Hooks.VisitFunctionBody != nil {
|
||||
return v.Hooks.VisitFunctionBody(node, v)
|
||||
}
|
||||
return v.visitNode(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitToken(node *Node) *Node {
|
||||
if v.Hooks.VisitToken != nil {
|
||||
return v.Hooks.VisitToken(node, v)
|
||||
}
|
||||
return v.VisitNode(node)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitNodes(nodes *NodeList) *NodeList {
|
||||
if v.Hooks.VisitNodes != nil {
|
||||
return v.Hooks.VisitNodes(nodes, v)
|
||||
}
|
||||
return v.VisitNodes(nodes)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitModifiers(nodes *ModifierList) *ModifierList {
|
||||
if v.Hooks.VisitModifiers != nil {
|
||||
return v.Hooks.VisitModifiers(nodes, v)
|
||||
}
|
||||
return v.VisitModifiers(nodes)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitParameters(nodes *ParameterList) *ParameterList {
|
||||
if v.Hooks.VisitParameters != nil {
|
||||
return v.Hooks.VisitParameters(nodes, v)
|
||||
}
|
||||
return v.visitNodes(nodes)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) visitTopLevelStatements(nodes *StatementList) *StatementList {
|
||||
if v.Hooks.VisitTopLevelStatements != nil {
|
||||
return v.Hooks.VisitTopLevelStatements(nodes, v)
|
||||
}
|
||||
return v.visitNodes(nodes)
|
||||
}
|
||||
|
||||
func (v *NodeVisitor) liftToBlock(node *Statement) *Statement {
|
||||
var nodes []*Node
|
||||
if node != nil {
|
||||
if node.Kind == KindSyntaxList {
|
||||
nodes = node.AsSyntaxList().Children
|
||||
} else {
|
||||
nodes = []*Node{node}
|
||||
}
|
||||
}
|
||||
if len(nodes) == 1 {
|
||||
node = nodes[0]
|
||||
} else {
|
||||
node = v.Factory.NewBlock(v.Factory.NewNodeList(nodes), true /*multiLine*/)
|
||||
}
|
||||
if node.Kind == KindSyntaxList {
|
||||
panic("The result of visiting and lifting a Node may not be SyntaxList")
|
||||
}
|
||||
return node
|
||||
}
|
||||
Reference in New Issue
Block a user