// noinspection JSUnusedGlobalSymbols
/*
* Copyright 2025 the original author or authors.
*
* Licensed under the Moderne Source Available License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://docs.moderne.io/licensing/moderne-source-available-license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {SourceFile} from "../tree";
import {
Expression,
J,
JavaVisitor,
MethodCall,
NameTree,
Statement,
Type,
TypedTree,
TypeTree,
VariableDeclarator,
registerJavaExtensionKinds
} from "../java";
import {JavaScriptVisitor} from "./visitor";
export interface JS extends J {
}
export namespace JS {
export const Kind = {
Alias: "org.openrewrite.javascript.tree.JS$Alias",
ArrayBindingPattern: "org.openrewrite.javascript.tree.JS$ArrayBindingPattern",
ArrowFunction: "org.openrewrite.javascript.tree.JS$ArrowFunction",
As: "org.openrewrite.javascript.tree.JS$As",
AssignmentOperation: "org.openrewrite.javascript.tree.JS$AssignmentOperation",
Await: "org.openrewrite.javascript.tree.JS$Await",
Binary: "org.openrewrite.javascript.tree.JS$Binary",
BindingElement: "org.openrewrite.javascript.tree.JS$BindingElement",
CompilationUnit: "org.openrewrite.javascript.tree.JS$CompilationUnit",
ComputedPropertyMethodDeclaration: "org.openrewrite.javascript.tree.JS$ComputedPropertyMethodDeclaration",
ComputedPropertyName: "org.openrewrite.javascript.tree.JS$ComputedPropertyName",
ConditionalType: "org.openrewrite.javascript.tree.JS$ConditionalType",
Delete: "org.openrewrite.javascript.tree.JS$Delete",
Export: "org.openrewrite.javascript.tree.JS$Export",
ExportAssignment: "org.openrewrite.javascript.tree.JS$ExportAssignment",
ExportDeclaration: "org.openrewrite.javascript.tree.JS$ExportDeclaration",
ExportSpecifier: "org.openrewrite.javascript.tree.JS$ExportSpecifier",
ExpressionStatement: "org.openrewrite.javascript.tree.JS$ExpressionStatement",
ExpressionWithTypeArguments: "org.openrewrite.javascript.tree.JS$ExpressionWithTypeArguments",
FunctionType: "org.openrewrite.javascript.tree.JS$FunctionType",
ImportAttribute: "org.openrewrite.javascript.tree.JS$ImportAttribute",
ImportAttributes: "org.openrewrite.javascript.tree.JS$ImportAttributes",
ImportType: "org.openrewrite.javascript.tree.JS$ImportType",
ImportTypeAttributes: "org.openrewrite.javascript.tree.JS$ImportTypeAttributes",
IndexSignatureDeclaration: "org.openrewrite.javascript.tree.JS$IndexSignatureDeclaration",
IndexType: "org.openrewrite.javascript.tree.JS$IndexedAccessType$IndexType",
IndexedAccessType: "org.openrewrite.javascript.tree.JS$IndexedAccessType",
IndexedAccessTypeIndexType: "org.openrewrite.javascript.tree.JS$IndexedAccessType$IndexType",
InferType: "org.openrewrite.javascript.tree.JS$InferType",
Intersection: "org.openrewrite.javascript.tree.JS$Intersection",
FunctionCall: "org.openrewrite.javascript.tree.JS$FunctionCall",
ForInLoop: "org.openrewrite.javascript.tree.JS$ForInLoop",
ForOfLoop: "org.openrewrite.javascript.tree.JS$ForOfLoop",
JsxEmbeddedExpression: "org.openrewrite.javascript.tree.JSX$EmbeddedExpression",
JsxSpreadAttribute: "org.openrewrite.javascript.tree.JSX$SpreadAttribute",
JsxNamespacedName: "org.openrewrite.javascript.tree.JSX$NamespacedName",
JsxTag: "org.openrewrite.javascript.tree.JSX$Tag",
JsxAttribute: "org.openrewrite.javascript.tree.JSX$Attribute",
Import: "org.openrewrite.javascript.tree.JS$Import",
ImportClause: "org.openrewrite.javascript.tree.JS$ImportClause",
ImportSpecifier: "org.openrewrite.javascript.tree.JS$ImportSpecifier",
LiteralType: "org.openrewrite.javascript.tree.JS$LiteralType",
MappedType: "org.openrewrite.javascript.tree.JS$MappedType",
MappedTypeKeysRemapping: "org.openrewrite.javascript.tree.JS$MappedType$KeysRemapping",
MappedTypeParameter: "org.openrewrite.javascript.tree.JS$MappedType$Parameter",
NamedExports: "org.openrewrite.javascript.tree.JS$NamedExports",
NamedImports: "org.openrewrite.javascript.tree.JS$NamedImports",
NamespaceDeclaration: "org.openrewrite.javascript.tree.JS$NamespaceDeclaration",
ObjectBindingPattern: "org.openrewrite.javascript.tree.JS$ObjectBindingPattern",
PropertyAssignment: "org.openrewrite.javascript.tree.JS$PropertyAssignment",
SatisfiesExpression: "org.openrewrite.javascript.tree.JS$SatisfiesExpression",
ScopedVariableDeclarations: "org.openrewrite.javascript.tree.JS$ScopedVariableDeclarations",
Shebang: "org.openrewrite.javascript.tree.JS$Shebang",
Spread: "org.openrewrite.javascript.tree.JS$Spread",
StatementExpression: "org.openrewrite.javascript.tree.JS$StatementExpression",
TaggedTemplateExpression: "org.openrewrite.javascript.tree.JS$TaggedTemplateExpression",
TemplateExpression: "org.openrewrite.javascript.tree.JS$TemplateExpression",
TemplateExpressionSpan: "org.openrewrite.javascript.tree.JS$TemplateExpression$Span",
Tuple: "org.openrewrite.javascript.tree.JS$Tuple",
TypeDeclaration: "org.openrewrite.javascript.tree.JS$TypeDeclaration",
TypeInfo: "org.openrewrite.javascript.tree.JS$TypeInfo",
TypeLiteral: "org.openrewrite.javascript.tree.JS$TypeLiteral",
TypeOf: "org.openrewrite.javascript.tree.JS$TypeOf",
TypeOperator: "org.openrewrite.javascript.tree.JS$TypeOperator",
TypePredicate: "org.openrewrite.javascript.tree.JS$TypePredicate",
TypeQuery: "org.openrewrite.javascript.tree.JS$TypeQuery",
TypeTreeExpression: "org.openrewrite.javascript.tree.JS$TypeTreeExpression",
Union: "org.openrewrite.javascript.tree.JS$Union",
Void: "org.openrewrite.javascript.tree.JS$Void",
WithStatement: "org.openrewrite.javascript.tree.JS$WithStatement",
} as const;
export function isMethodCall(e?: Expression): e is MethodCall {
return J.isMethodCall(e) || e?.kind === JS.Kind.FunctionCall;
}
/**
* Represents the root of a JavaScript AST (compilation unit).
* @example // file.js as AST root
* // statements and EOF marker
*/
export interface CompilationUnit extends JS, SourceFile {
readonly kind: typeof Kind.CompilationUnit;
readonly statements: J.RightPadded[];
readonly eof: J.Space;
}
/**
* In a namespace import, aliases the contents of the namespace.
* @example import * as path from "path"
*/
export interface Alias extends JS, Expression {
readonly kind: typeof Kind.Alias;
readonly propertyName: J.RightPadded;
readonly alias: Expression;
}
/**
* Represents an arrow function expression.
* @example const f = (x: number) => x + 1;
*/
export interface ArrowFunction extends JS, Statement, Expression, TypedTree {
readonly kind: typeof Kind.ArrowFunction;
readonly leadingAnnotations: J.Annotation[];
readonly modifiers: J.Modifier[];
readonly typeParameters?: J.TypeParameters;
readonly lambda: J.Lambda;
readonly returnTypeExpression?: TypeTree;
}
/**
* Represents an "as" expression, used for type assertions or casting.
* @example const x = value as Type;
*/
export interface As extends JS, Expression, TypedTree {
readonly kind: typeof Kind.As;
readonly left: J.RightPadded;
readonly right: Expression;
readonly type?: Type;
}
/**
* Represents the `await` operator in an async function.
* @example const result = await fetchData();
*/
export interface Await extends JS, Expression {
readonly kind: typeof Kind.Await;
readonly expression: Expression;
readonly type?: Type;
}
/**
* Represents a TypeScript conditional type (ternary type).
* @example T extends U ? X : Y
*/
export interface ConditionalType extends JS, Expression, TypeTree {
readonly kind: typeof Kind.ConditionalType;
readonly checkType: Expression;
readonly condition: J.LeftPadded;
readonly type?: Type;
}
/**
* Represents the `delete` operator.
* @example delete obj.prop;
*/
export interface Delete extends JS, Statement, Expression {
readonly kind: typeof Kind.Delete;
readonly expression: Expression;
}
/**
* Represents an expression used as a statement.
* @example obj.method();
*/
export interface ExpressionStatement extends JS, Statement, Expression {
readonly kind: typeof Kind.ExpressionStatement;
readonly expression: Expression;
}
/**
* Represents an expression with type arguments (generic invocation).
* @example myFunc(arg);
*/
export interface ExpressionWithTypeArguments extends JS, Expression, TypeTree {
readonly kind: typeof Kind.ExpressionWithTypeArguments;
readonly clazz: J;
readonly typeArguments?: J.Container;
readonly type?: Type;
}
/**
* Represents a TypeScript function type.
* @example type Fn = (x: number) => string;
*/
export interface FunctionType extends JS, Expression, TypeTree {
readonly kind: typeof Kind.FunctionType;
readonly modifiers: J.Modifier[];
readonly constructorType: J.LeftPadded;
readonly typeParameters?: J.TypeParameters;
readonly parameters: J.Container;
readonly returnType: J.LeftPadded;
}
/**
* Represents the `infer` keyword in conditional types.
* @example T extends (...args: any[]) => infer R ? R : any;
*/
export interface InferType extends JS, Expression, TypeTree {
readonly kind: typeof Kind.InferType;
readonly typeParameter: J.LeftPadded;
readonly type?: Type;
}
/**
* Represents a dynamic import type.
* @example type T = import('module').Foo;
*/
export interface ImportType extends JS, Expression, TypeTree {
readonly kind: typeof Kind.ImportType;
readonly hasTypeof: J.RightPadded;
readonly argumentAndAttributes: J.Container;
readonly qualifier?: J.LeftPadded;
readonly typeArguments?: J.Container;
readonly type?: Type;
}
/**
* Represents an import declaration.
* @example import x from 'module';
*/
export interface Import extends JS, Statement {
readonly kind: typeof Kind.Import;
readonly modifiers: J.Modifier[];
readonly importClause?: ImportClause;
readonly moduleSpecifier?: J.LeftPadded;
readonly attributes?: ImportAttributes;
readonly initializer?: J.LeftPadded;
}
/**
* Represents the clause of an import statement, including default and named bindings.
* @example import {A, B as C} from 'module';
*/
export interface ImportClause extends JS {
readonly kind: typeof Kind.ImportClause;
readonly typeOnly: boolean;
readonly name?: J.RightPadded;
readonly namedBindings?: Expression;
}
/**
* Represents named imports in an import declaration.
* @example import { a, b } from 'fs';
*/
export interface NamedImports extends JS, Expression {
readonly kind: typeof Kind.NamedImports;
readonly elements: J.Container;
readonly type?: Type;
}
/**
* Represents a single specifier in a named import.
* @example import { foo as bar } from 'baz';
*/
export interface ImportSpecifier extends JS, Expression, TypedTree {
readonly kind: typeof Kind.ImportSpecifier;
readonly importType: J.LeftPadded;
readonly specifier: J.Identifier | Alias | J.Empty;
readonly type?: Type;
}
/**
* Represents import assertion attributes.
* @example import data from './data.json' assert { type: 'json' };
*/
export interface ImportAttributes extends JS {
readonly kind: typeof Kind.ImportAttributes;
readonly token: ImportAttributes.Token;
readonly elements: J.Container;
}
export namespace ImportAttributes {
export const enum Token {
With = "With",
Assert = "Assert"
}
}
/**
* Represents attributes for import type declarations.
* @example import type A from './module';
*/
export interface ImportTypeAttributes extends JS {
readonly kind: typeof Kind.ImportTypeAttributes;
readonly token: J.RightPadded;
readonly elements: J.Container;
readonly end: J.Space;
}
/**
* Represents a single import assertion attribute key-value pair.
* @example assert { type: 'json' };
*/
export interface ImportAttribute extends JS, Statement {
readonly kind: typeof Kind.ImportAttribute;
readonly name: Expression;
readonly value: J.LeftPadded;
}
/**
* Represents a binary expression.
* @example a + b;
*/
export interface Binary extends JS, Expression, TypedTree {
readonly kind: typeof Kind.Binary;
readonly left: Expression;
readonly operator: J.LeftPadded;
readonly right: Expression;
readonly type?: Type;
}
export namespace Binary {
export const enum Type {
As = "As",
IdentityEquals = "IdentityEquals",
IdentityNotEquals = "IdentityNotEquals",
In = "In",
QuestionQuestion = "QuestionQuestion",
Comma = "Comma"
}
}
/**
* Represents a literal type in TypeScript.
* @example type T = 'foo';
*/
export interface LiteralType extends JS, Expression, TypeTree {
readonly kind: typeof Kind.LiteralType;
readonly literal: Expression;
type: Type;
}
/**
* Represents a mapped type in TypeScript.
* @example type Readonly = { readonly [P in keyof T]: T[P] };
*/
export interface MappedType extends JS, Expression, TypeTree {
readonly kind: typeof Kind.MappedType;
readonly prefixToken?: J.LeftPadded;
readonly hasReadonly: J.LeftPadded;
readonly keysRemapping: MappedType.KeysRemapping;
readonly suffixToken?: J.LeftPadded;
readonly hasQuestionToken: J.LeftPadded;
readonly valueType: J.Container;
readonly type?: Type;
}
export namespace MappedType {
/**
* Represents key remapping in a mapped type.
* @example { [K in keyof T as Uppercase]: T[K] }
*/
export interface KeysRemapping extends JS, Statement {
readonly kind: typeof Kind.MappedTypeKeysRemapping;
readonly typeParameter: J.RightPadded;
readonly nameType?: J.RightPadded;
}
/**
* Represents a type parameter in a mapped type.
* @example [P in K]
*/
export interface Parameter extends JS, Statement {
readonly kind: typeof Kind.MappedTypeParameter;
readonly name: Expression;
readonly iterateType: J.LeftPadded;
}
}
/**
* Represents object destructuring patterns.
* @example const { a, b } = obj;
*/
export interface ObjectBindingPattern extends JS, Expression, TypedTree, VariableDeclarator {
readonly kind: typeof Kind.ObjectBindingPattern;
readonly leadingAnnotations: J.Annotation[];
readonly modifiers: J.Modifier[];
readonly typeExpression?: TypeTree;
readonly bindings: J.Container;
readonly initializer?: J.LeftPadded;
}
/**
* Represents a property assignment in an object literal.
* @example { key: value }
*/
export interface PropertyAssignment extends JS, Statement, TypedTree {
readonly kind: typeof Kind.PropertyAssignment;
readonly name: J.RightPadded;
readonly assigmentToken: PropertyAssignment.Token;
readonly initializer?: Expression;
}
export namespace PropertyAssignment {
export const enum Token {
Colon = "Colon",
Equals = "Equals",
Empty = "Empty"
}
}
/**
* Represents the `satisfies` operator in TypeScript.
* @example const x = { a: 1 } satisfies Foo;
*/
export interface SatisfiesExpression extends JS, Expression {
readonly kind: typeof Kind.SatisfiesExpression;
readonly expression: J;
readonly satisfiesType: J.LeftPadded;
readonly type?: Type;
}
/**
* Represents scoped variable declarations with keywords like const/let/var.
* @example let x = 10;
*/
export interface ScopedVariableDeclarations extends JS, Statement {
readonly kind: typeof Kind.ScopedVariableDeclarations;
readonly modifiers: J.Modifier[];
readonly variables: J.RightPadded[];
}
/**
* Represents a shebang line at the beginning of a script.
* @example #!/usr/bin/env node
*/
export interface Shebang extends JS, Statement {
readonly kind: typeof Kind.Shebang;
readonly text: string;
}
/**
* Represents the spread syntax (...) applied to an expression.
* Used in array literals, object literals, function call arguments,
* and rest syntax in function parameters and destructuring patterns.
* @example [...arr]
* @example {...obj}
* @example f(...args)
* @example function f(...args) {}
* @example const [first, ...rest] = arr
*/
export interface Spread extends JS, Statement, Expression, TypedTree, VariableDeclarator {
readonly kind: typeof Kind.Spread;
readonly expression: Expression;
readonly type?: Type;
}
/**
* Represents a statement used as an expression. The example shows a function expressions.
* @example const greet = function (name: string) : string { return name; };
*/
export interface StatementExpression extends JS, Statement, Expression {
readonly kind: typeof Kind.StatementExpression;
readonly statement: Statement;
}
/**
* Represents a tagged template literal.
* @example html`${content}
`;
*/
export interface TaggedTemplateExpression extends JS, Statement, Expression {
readonly kind: typeof Kind.TaggedTemplateExpression;
readonly tag?: J.RightPadded;
readonly typeArguments?: J.Container;
readonly templateExpression: Expression;
readonly type?: Type;
}
/**
* Represents a template string expression.
* @example `Hello ${name}`;
*/
export interface TemplateExpression extends JS, Statement, Expression, TypeTree {
readonly kind: typeof Kind.TemplateExpression;
readonly head: J.Literal;
readonly spans: J.RightPadded[];
readonly type?: Type;
}
export namespace TemplateExpression {
/**
* Represents a span in a template expression.
* @example the `${expr}` and tail parts
*/
export interface Span extends JS {
readonly kind: typeof Kind.TemplateExpressionSpan;
readonly expression: J;
readonly tail: J.Literal;
}
}
/**
* Represents a tuple type in TypeScript.
* @example type T = [string, number];
*/
export interface Tuple extends JS, Expression, TypeTree {
readonly kind: typeof Kind.Tuple;
readonly elements: J.Container;
readonly type?: Type;
}
/**
* Represents a type alias declaration.
* @example type Foo = string;
*/
export interface TypeDeclaration extends JS, Statement, TypedTree {
readonly kind: typeof Kind.TypeDeclaration;
readonly modifiers: J.Modifier[];
readonly name: J.LeftPadded;
readonly typeParameters?: J.TypeParameters;
readonly initializer: J.LeftPadded;
readonly type?: Type;
}
/**
* Represents the `typeof` type operator in TypeScript.
* @example type T = typeof x;
*/
export interface TypeOf extends JS, Expression {
readonly kind: typeof Kind.TypeOf;
readonly expression: Expression;
readonly type?: Type;
}
/**
* Represents an expression used as a type tree.
* @example (value)
*/
export interface TypeTreeExpression extends JS, Expression, TypeTree {
readonly kind: typeof Kind.TypeTreeExpression;
readonly expression: Expression;
}
/**
* Represents an assignment operation.
* @example a ||= b;
*/
export interface AssignmentOperation extends JS, Statement, Expression, TypedTree {
readonly kind: typeof Kind.AssignmentOperation;
readonly variable: Expression;
readonly operator: J.LeftPadded;
readonly assignment: Expression;
readonly type?: Type;
}
export namespace AssignmentOperation {
export const enum Type {
QuestionQuestion = "QuestionQuestion",
And = "And",
Or = "Or",
Power = "Power",
Exp = "Exp"
}
}
/**
* Represents an indexed access type in TypeScript.
* @example type A = T['prop'];
*/
export interface IndexedAccessType extends JS, Expression, TypeTree {
readonly kind: typeof Kind.IndexedAccessType;
readonly objectType: TypeTree;
readonly indexType: TypeTree;
readonly type?: Type;
}
export namespace IndexedAccessType {
/**
* Represents the index type in an indexed access.
* @example 'key'
*/
export interface IndexType extends JS {
readonly kind: typeof Kind.IndexedAccessTypeIndexType;
readonly element: J.RightPadded;
readonly type?: Type;
}
}
/**
* Represents a typeof type query in TypeScript.
* @example type T = typeof obj;
*/
export interface TypeQuery extends JS, Expression, TypeTree {
readonly kind: typeof Kind.TypeQuery;
readonly typeExpression: TypeTree;
readonly typeArguments?: J.Container;
readonly type?: Type;
}
/**
* Represents explicit type information.
* @example use in type cast contexts
*/
export interface TypeInfo extends JS, Expression, TypeTree {
readonly kind: typeof Kind.TypeInfo;
readonly typeIdentifier: TypeTree;
}
/**
* Represents TypeScript computed property name.
* @example { [key]: value }
*/
export interface ComputedPropertyName extends JS, Expression, TypedTree, VariableDeclarator {
readonly kind: typeof Kind.ComputedPropertyName;
readonly expression: J.RightPadded;
}
/**
* Represents TypeScript type operator keywords like readonly.
* @example type R = readonly number[];
*/
export interface TypeOperator extends JS, Expression, TypeTree {
readonly kind: typeof Kind.TypeOperator;
readonly operator: TypeOperator.Type;
readonly expression: J.LeftPadded;
}
export namespace TypeOperator {
export const enum Type {
ReadOnly = "ReadOnly",
KeyOf = "KeyOf",
Unique = "Unique"
}
}
/**
* Represents a type predicate in TypeScript.
* @example function isString(x): x is string;
*/
export interface TypePredicate extends JS, Expression, TypeTree {
readonly kind: typeof Kind.TypePredicate;
readonly asserts: J.LeftPadded;
readonly parameterName: J.Identifier;
readonly expression?: J.LeftPadded;
readonly type?: Type;
}
/**
* Represents a union type in TypeScript.
* @example type U = A | B;
*/
export interface Union extends JS, Expression, TypeTree {
readonly kind: typeof Kind.Union;
readonly types: J.RightPadded[];
readonly type?: Type;
}
/**
* Represents an intersection type in TypeScript.
* @example type I = A & B;
*/
export interface Intersection extends JS, Expression, TypeTree {
readonly kind: typeof Kind.Intersection;
readonly types: J.RightPadded[];
readonly type?: Type;
}
/**
* Represents function calls which are not method invocations.
* @example f(5, 0, 4)
* @example f?.(5, 0, 4)
* @example data["key"](5, 0, 4)
* @example (() => { return 3 + 5 })()
*/
export interface FunctionCall extends JS, MethodCall {
readonly kind: typeof Kind.FunctionCall;
readonly function?: J.RightPadded;
readonly typeParameters?: J.Container;
readonly arguments: J.Container;
}
/**
* Represents the `void` operator.
* @example void 0;
*/
export interface Void extends JS, Expression {
readonly kind: typeof Kind.Void;
readonly expression: Expression;
}
/**
* Represents a `with` statement.
* @example with (obj) { console.log(a); }
*/
export interface WithStatement extends JS, Statement {
readonly kind: typeof Kind.WithStatement;
readonly expression: J.ControlParentheses;
readonly body: J.RightPadded;
}
/**
* Represents an index signature in TypeScript interfaces.
* @example interface Foo { [key: string]: any; }
*/
export interface IndexSignatureDeclaration extends JS, Statement, TypedTree {
readonly kind: typeof Kind.IndexSignatureDeclaration;
readonly modifiers: J.Modifier[];
readonly parameters: J.Container;
readonly typeExpression: J.LeftPadded;
readonly type?: Type;
}
/**
* Represents a method declaration in classes or objects.
* @example class A { [Symbol.asyncIterator]() { ... } }
*/
export interface ComputedPropertyMethodDeclaration extends JS, Statement {
readonly kind: typeof Kind.ComputedPropertyMethodDeclaration;
readonly leadingAnnotations: J.Annotation[];
readonly modifiers: J.Modifier[];
readonly typeParameters?: J.TypeParameters;
readonly returnTypeExpression?: TypeTree;
readonly name: ComputedPropertyName;
readonly parameters: J.Container;
readonly body?: J.Block;
readonly methodType?: Type.Method;
}
/**
* Represents a for-of loop.
* @example for (const x of arr) { }
* @example for await (const x of arr) { }
*/
export interface ForOfLoop extends JS {
readonly kind: typeof Kind.ForOfLoop;
readonly await?: J.Space;
readonly loop: J.ForEachLoop;
}
export namespace ForOfLoop {
export type Control = J.ForEachLoop.Control;
}
/**
* Represents a for-in loop.
* @example for (let key in obj) { }
*/
export interface ForInLoop extends JS {
readonly kind: typeof Kind.ForInLoop;
readonly control: ForInLoop.Control;
readonly body: J.RightPadded;
}
export namespace ForInLoop {
export type Control = J.ForEachLoop.Control;
}
/**
* Represents a namespace declaration in TypeScript.
* @example namespace MyNS { }
*/
export interface NamespaceDeclaration extends JS, Statement {
readonly kind: typeof Kind.NamespaceDeclaration;
readonly modifiers: J.Modifier[];
readonly keywordType: J.LeftPadded;
readonly name: J.RightPadded;
readonly body?: J.Block;
}
export namespace NamespaceDeclaration {
export const enum KeywordType {
Namespace = "Namespace",
Module = "Module",
Empty = "Empty"
}
}
/**
* Represents a literal type object in TypeScript.
* @example type T = { a: number };
*/
export interface TypeLiteral extends JS, TypeTree {
readonly kind: typeof Kind.TypeLiteral;
readonly members: J.Block;
readonly type?: Type;
}
/**
* Represents an array destructuring pattern.
* @example const [a, b] = arr;
*/
export interface ArrayBindingPattern extends JS, TypedTree, VariableDeclarator {
readonly kind: typeof Kind.ArrayBindingPattern;
readonly elements: J.Container;
readonly type?: Type;
}
/**
* Represents a named element in a binding pattern.
* @example const { x: alias } = obj;
*/
export interface BindingElement extends JS, Statement, TypeTree {
readonly kind: typeof Kind.BindingElement;
readonly propertyName?: J.RightPadded;
readonly name: TypedTree;
readonly initializer?: J.LeftPadded;
readonly variableType?: Type.Variable;
}
/**
* Represents an export declaration (export ...).
* @example export class X {}
*/
export interface ExportDeclaration extends JS, Statement {
readonly kind: typeof Kind.ExportDeclaration;
readonly modifiers: J.Modifier[];
readonly typeOnly: J.LeftPadded;
readonly exportClause?: Expression;
readonly moduleSpecifier?: J.LeftPadded;
readonly attributes?: ImportAttributes;
}
/**
* Represents an export assignment.
* @example export = foo;
* @example export default foo;
*/
export interface ExportAssignment extends JS, Statement {
readonly kind: typeof Kind.ExportAssignment;
readonly exportEquals: boolean;
readonly expression: J.LeftPadded;
}
/**
* Represents named exports in an export declaration.
* @example export { a, b };
*/
export interface NamedExports extends JS {
readonly kind: typeof Kind.NamedExports;
readonly elements: J.Container;
readonly type?: Type;
}
/**
* Represents a specifier in a named export.
* @example export { foo as bar };
*/
export interface ExportSpecifier extends JS {
readonly kind: typeof Kind.ExportSpecifier;
readonly typeOnly: J.LeftPadded;
readonly specifier: Expression;
readonly type?: Type;
}
}
export namespace JSX {
/**
* Represents a JSX tag. Note that `selfClosing` and `children` are mutually exclusive.
* @example {child}
*/
export type Tag =
(BaseTag & {
readonly selfClosing: J.Space;
readonly children?: undefined;
readonly closingName?: undefined;
readonly afterClosingName?: undefined;
}) |
(BaseTag & {
readonly selfClosing?: undefined;
readonly children: (EmbeddedExpression | Tag | J.Identifier | J.Literal | J.Empty)[];
readonly closingName: J.LeftPadded;
readonly afterClosingName: J.Space;
});
interface BaseTag extends JS, Expression {
readonly kind: typeof JS.Kind.JsxTag;
readonly openName: J.LeftPadded;
readonly typeArguments?: J.Container;
readonly afterName: J.Space;
readonly attributes: J.RightPadded[];
}
/**
* Represents a single JSX attribute.
* @example prop="value"
*/
export interface Attribute extends JS {
readonly kind: typeof JS.Kind.JsxAttribute;
readonly key: J.Identifier | NamespacedName;
readonly value?: J.LeftPadded;
}
/**
* Represents a spread attribute in JSX.
* @example {...props}
*/
export interface SpreadAttribute extends JS {
readonly kind: typeof JS.Kind.JsxSpreadAttribute;
readonly dots: J.Space
readonly expression: J.RightPadded;
}
/**
* Represents a JSX expression container.
* @example {expression}
*/
export interface EmbeddedExpression extends JS, Expression {
readonly kind: typeof JS.Kind.JsxEmbeddedExpression;
readonly expression: J.RightPadded;
}
/**
* Represents a namespaced JSX name.
* @example namespace:Name
*/
export interface NamespacedName extends JS, NameTree {
readonly kind: typeof JS.Kind.JsxNamespacedName;
readonly namespace: J.Identifier;
readonly name: J.LeftPadded;
}
}
const KindValues = new Set(Object.values(JS.Kind));
function javascriptVisitorAdapter(visitor: JavaVisitor
): JavaVisitor
{
const adaptedVisitor = new JavaScriptVisitor
();
// Walk up the prototype chain of the visitor to get all overridden methods
let proto = Object.getPrototypeOf(visitor);
while (proto && proto !== JavaVisitor.prototype) {
Object.getOwnPropertyNames(proto).forEach(name => {
const descriptor = Object.getOwnPropertyDescriptor(proto, name);
if (descriptor && typeof descriptor.value === 'function' && name !== 'constructor') {
// Copy the method, binding it to jsVisitor
(adaptedVisitor as any)[name] = descriptor.value.bind(adaptedVisitor);
}
});
proto = Object.getPrototypeOf(proto);
}
// Also copy any instance properties
Object.keys(visitor).forEach(key => {
if (!(key in adaptedVisitor)) {
(adaptedVisitor as any)[key] = (visitor as any)[key];
}
});
return adaptedVisitor;
}
registerJavaExtensionKinds(Object.values(JS.Kind), javascriptVisitorAdapter);
export function isJavaScript(tree: any): tree is JS {
return KindValues.has(tree["kind"]);
}
export function isExpressionStatement(tree: any): tree is JS.ExpressionStatement {
return tree["kind"] === JS.Kind.ExpressionStatement;
}
TypedTree.registerTypeGetter(JS.Kind.PropertyAssignment, (tree: JS.PropertyAssignment) => TypedTree.getType(tree.initializer));
TypedTree.registerTypeGetter(JS.Kind.FunctionType, (tree: JS.FunctionType) => TypedTree.getType(tree.returnType.element))