From b7be5cdb0a89d20a5178f6b3775bc1bca2c38869 Mon Sep 17 00:00:00 2001 From: Andrii Rodionov Date: Fri, 7 Feb 2025 13:34:21 +0100 Subject: [PATCH 1/3] [Draft] Implemented TS printer --- openrewrite/jest.config.js | 1 + openrewrite/src/java/tree/support_types.ts | 95 +- openrewrite/src/javascript/index.ts | 1 + openrewrite/src/javascript/printer.ts | 1487 +++++++++++++++++ .../src/javascript/tree/support_types.ts | 212 ++- .../test/javascript/parser/class.test.ts | 2 +- openrewrite/test/javascript/testHarness.ts | 185 +- 7 files changed, 1818 insertions(+), 165 deletions(-) create mode 100644 openrewrite/src/javascript/printer.ts diff --git a/openrewrite/jest.config.js b/openrewrite/jest.config.js index bd12b948..9f396cec 100644 --- a/openrewrite/jest.config.js +++ b/openrewrite/jest.config.js @@ -15,4 +15,5 @@ module.exports = { }, testMatch: ['**/__tests__/**/*.+(ts|tsx|js)', '**/?(*.)+(spec|test).+(ts|tsx|js)'], collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/**/*.d.ts'], + env: process.env.NODE_ENV || "dev", }; diff --git a/openrewrite/src/java/tree/support_types.ts b/openrewrite/src/java/tree/support_types.ts index d01d0383..39e1d33e 100644 --- a/openrewrite/src/java/tree/support_types.ts +++ b/openrewrite/src/java/tree/support_types.ts @@ -564,6 +564,8 @@ export namespace Space { BREAK_PREFIX, CASE, CASE_PREFIX, + CASE_CASE_LABELS, + CASE_CASE_LABELS_SUFFIX, CASE_BODY, CASE_EXPRESSION, CASE_SUFFIX, @@ -693,60 +695,61 @@ export namespace Space { YIELD_PREFIX, ERRONEOUS_PREFIX, DECONSTRUCTION_PATTERN_PREFIX, + TRAILING_COMMA_SUFFIX } } export namespace JRightPadded { export enum Location { - ANNOTATION_ARGUMENT, + ANNOTATION_ARGUMENT = Space.Location.ANNOTATION_ARGUMENT_SUFFIX, ARRAY_INDEX, - BLOCK_STATEMENT, - CASE, + BLOCK_STATEMENT = Space.Location.BLOCK_STATEMENT_SUFFIX, + CASE = Space.Location.CASE_SUFFIX, + CASE_CASE_LABELS = Space.Location.CASE_CASE_LABELS_SUFFIX, CASE_BODY, CASE_EXPRESSION, CATCH_ALTERNATIVE, CONTROL_PARENTHESES_TREE, DIMENSION, - ENUM_VALUE, + ENUM_VALUE = Space.Location.ENUM_VALUE_SUFFIX, FOREACH_ITERABLE, FOREACH_VARIABLE, - FOR_BODY, - FOR_CONDITION, - FOR_INIT, - FOR_UPDATE, + FOR_BODY = Space.Location.FOR_BODY_SUFFIX, + FOR_CONDITION = Space.Location.FOR_CONDITION_SUFFIX, + FOR_INIT = Space.Location.FOR_INIT_SUFFIX, + FOR_UPDATE = Space.Location.FOR_UPDATE_SUFFIX, IF_ELSE, IF_THEN, - IMPLEMENTS, + IMPLEMENTS = Space.Location.IMPLEMENTS_SUFFIX, IMPORT, INSTANCEOF, LABEL, - LAMBDA_PARAM, - LANGUAGE_EXTENSION, + LAMBDA_PARAM = Space.Location.LAMBDA_PARAMETER, + LANGUAGE_EXTENSION = Space.Location.LANGUAGE_EXTENSION, MEMBER_REFERENCE_CONTAINING, - METHOD_DECLARATION_PARAMETER, - METHOD_INVOCATION_ARGUMENT, - METHOD_SELECT, - NAMED_VARIABLE, - NEW_ARRAY_INITIALIZER, - NEW_CLASS_ARGUMENTS, - NEW_CLASS_ENCLOSING, + METHOD_DECLARATION_PARAMETER = Space.Location.METHOD_DECLARATION_PARAMETER_SUFFIX, + METHOD_INVOCATION_ARGUMENT = Space.Location.METHOD_INVOCATION_ARGUMENT_SUFFIX, + METHOD_SELECT = Space.Location.METHOD_SELECT_SUFFIX, + NAMED_VARIABLE = Space.Location.NAMED_VARIABLE_SUFFIX, + NEW_ARRAY_INITIALIZER = Space.Location.NEW_ARRAY_INITIALIZER_SUFFIX, + NEW_CLASS_ARGUMENTS = Space.Location.NEW_CLASS_ARGUMENTS_SUFFIX, + NEW_CLASS_ENCLOSING = Space.Location.NEW_CLASS_ENCLOSING_SUFFIX, NULLABLE, PACKAGE, - PARENTHESES, + PARENTHESES = Space.Location.PARENTHESES_SUFFIX, PERMITS, - RECORD_STATE_VECTOR, - STATIC_INIT, + RECORD_STATE_VECTOR = Space.Location.RECORD_STATE_VECTOR_SUFFIX, + STATIC_INIT = Space.Location.STATIC_INIT_SUFFIX, THROWS, TRY_RESOURCE, - TYPE_BOUND, - TYPE_PARAMETER, + TYPE_BOUND = Space.Location.TYPE_BOUND_SUFFIX, + TYPE_PARAMETER = Space.Location.TYPE_PARAMETER_SUFFIX, WHILE_BODY, } export namespace Location { export function afterLocation(location: Location): Space.Location { - // FIXME - return null!; + return location as unknown as Space.Location; } } } @@ -754,12 +757,12 @@ export namespace JRightPadded { export namespace JLeftPadded { export enum Location { ASSERT_DETAIL, - ASSIGNMENT, - ASSIGNMENT_OPERATION_OPERATOR, - BINARY_OPERATOR, + ASSIGNMENT = Space.Location.ASSIGNMENT, + ASSIGNMENT_OPERATION_OPERATOR = Space.Location.ASSIGNMENT_OPERATION_OPERATOR, + BINARY_OPERATOR = Space.Location.BINARY_OPERATOR, CLASS_KIND, - EXTENDS, - FIELD_ACCESS_NAME, + EXTENDS = Space.Location.EXTENDS, + FIELD_ACCESS_NAME = Space.Location.FIELD_ACCESS_NAME, IMPORT_ALIAS_PREFIX, LANGUAGE_EXTENSION, MEMBER_REFERENCE_NAME, @@ -768,16 +771,15 @@ export namespace JLeftPadded { TERNARY_TRUE, TERNARY_FALSE, TRY_FINALLY, - UNARY_OPERATOR, - VARIABLE_INITIALIZER, + UNARY_OPERATOR = Space.Location.UNARY_OPERATOR, + VARIABLE_INITIALIZER = Space.Location.VARIABLE_INITIALIZER, WHILE_CONDITION, WILDCARD_BOUND, } export namespace Location { export function beforeLocation(location: Location): Space.Location { - // FIXME - return null!; + return location as unknown as Space.Location; } } } @@ -802,15 +804,32 @@ export namespace JContainer { DECONSTRUCTION_PATTERN_NESTED, } + export const LocationDetails = { + [Location.LANGUAGE_EXTENSION]: [Space.Location.LANGUAGE_EXTENSION, JRightPadded.Location.LANGUAGE_EXTENSION], + [Location.TYPE_PARAMETERS]: [Space.Location.TYPE_PARAMETERS, JRightPadded.Location.TYPE_PARAMETER], + [Location.RECORD_STATE_VECTOR]: [Space.Location.RECORD_STATE_VECTOR, JRightPadded.Location.RECORD_STATE_VECTOR], + [Location.IMPLEMENTS]: [Space.Location.IMPLEMENTS, JRightPadded.Location.IMPLEMENTS], + [Location.METHOD_DECLARATION_PARAMETERS]: [Space.Location.METHOD_DECLARATION_PARAMETERS, JRightPadded.Location.METHOD_DECLARATION_PARAMETER], + [Location.METHOD_INVOCATION_ARGUMENTS]: [Space.Location.METHOD_INVOCATION_ARGUMENTS, JRightPadded.Location.METHOD_INVOCATION_ARGUMENT], + [Location.TYPE_BOUNDS]: [Space.Location.TYPE_BOUNDS, JRightPadded.Location.TYPE_BOUND], + [Location.ANNOTATION_ARGUMENTS]: [Space.Location.ANNOTATION_ARGUMENTS, JRightPadded.Location.ANNOTATION_ARGUMENT], + [Location.NEW_ARRAY_INITIALIZER]: [Space.Location.NEW_ARRAY_INITIALIZER, JRightPadded.Location.NEW_ARRAY_INITIALIZER], + [Location.NEW_CLASS_ARGUMENTS]: [Space.Location.NEW_CLASS_ARGUMENTS, JRightPadded.Location.NEW_CLASS_ARGUMENTS], + [Location.CASE_CASE_LABELS]: [Space.Location.CASE_CASE_LABELS, JRightPadded.Location.CASE_CASE_LABELS], + [Location.CASE]: [Space.Location.CASE, JRightPadded.Location.CASE], + }; + export namespace Location { export function beforeLocation(location: Location): Space.Location { - // FIXME - return null!; + // @ts-ignore + const [before] = JContainer.LocationDetails[location]; + return before as Space.Location; } export function elementLocation(location: Location): JRightPadded.Location { - // FIXME - return null!; + // @ts-ignore + const [, element] = JContainer.LocationDetails[location]; + return element as JRightPadded.Location; } } } diff --git a/openrewrite/src/javascript/index.ts b/openrewrite/src/javascript/index.ts index 2ad1345d..c15e28ab 100644 --- a/openrewrite/src/javascript/index.ts +++ b/openrewrite/src/javascript/index.ts @@ -3,3 +3,4 @@ export * from './parser'; export * from './projectParser'; export * from './tree'; export * from './visitor'; +export * from './printer'; diff --git a/openrewrite/src/javascript/printer.ts b/openrewrite/src/javascript/printer.ts new file mode 100644 index 00000000..7d5600bf --- /dev/null +++ b/openrewrite/src/javascript/printer.ts @@ -0,0 +1,1487 @@ +import * as ts from 'typescript'; +import * as J from '../java'; + +import { + FieldAccess, + JavaType, + JContainer, + JLeftPadded, + JRightPadded, + Lambda, Literal, + Semicolon, + Space, + TrailingComma, + TypedTree +} from '../java'; +import * as JS from '.'; +import { + Cursor, + ExecutionContext, Marker, + Markers, + ParseError, + ParseExceptionResult, + Parser, + ParserInput, PrintOutputCapture, + randomId, + SourceFile, Tree +} from "../core"; +import {JavaScriptVisitor, JsContainer, JsLeftPadded, JsRightPadded, JsSpace} from "."; + +export class JavaScriptPrinter

extends JavaScriptVisitor> { + + JAVA_SCRIPT_MARKER_WRAPPER: (out: string) => string = (out) => `/*~~${out}${out.length === 0 ? "" : "~~"}>*/`; + + // constructor(cursor: Cursor) { + // super(cursor) + // } + + visit(tree: Tree | null, p: PrintOutputCapture

): J.J | null { + return super.visit(tree, p); + } + + visitJsCompilationUnit(cu: JS.CompilationUnit, p: PrintOutputCapture

): J.J | null { + this.beforeSyntax(cu, Space.Location.COMPILATION_UNIT_PREFIX, p); + + this.visitJsRightPaddedLocal(cu.padding.statements, JsRightPadded.Location.COMPILATION_UNIT_STATEMENTS, "", p); + + this.visitSpace(cu.eof, Space.Location.COMPILATION_UNIT_EOF, p); + this.afterSyntax(cu, p); + return cu; + } + + // visitCompilationUnit(cu: J.CompilationUnit, p: PrintOutputCapture

): J.J | null { + // this.beforeSyntax(cu, Space.Location.COMPILATION_UNIT_PREFIX, p); + // + // //this.visitRightPadded(cu.padding.getStatements(), JRightPadded.Location.LANGUAGE_EXTENSION, "", p); + // + // this.visitSpace(cu.eof, Space.Location.COMPILATION_UNIT_EOF, p); + // this.afterSyntax(cu, p); + // return cu; + // } + + visitLiteral(literal: Literal, p: PrintOutputCapture

): J.J { + this.beforeSyntax(literal, Space.Location.LITERAL_PREFIX, p); + + const unicodeEscapes = literal.unicodeEscapes; + if (!unicodeEscapes) { + p.append(literal.valueSource!); + } else if (literal.valueSource) { + const surrogateIter = unicodeEscapes[Symbol.iterator](); + let surrogate = surrogateIter.next().value ?? null; + let i = 0; + + if (surrogate && surrogate.valueSourceIndex === 0) { + p.append("\\u").append(surrogate.codePoint); + surrogate = surrogateIter.next().value ?? null; + } + + const valueSource = literal.valueSource; + for (let j = 0; j < valueSource.length; j++) { + const c = valueSource[j]; + p.append(c); + + if (surrogate && surrogate.valueSourceIndex === ++i) { + while (surrogate && surrogate.valueSourceIndex === i) { + p.append("\\u").append(surrogate.codePoint); + surrogate = surrogateIter.next().value ?? null; + } + } + } + } + + this.afterSyntax(literal, p); + return literal; + } + + public visitScopedVariableDeclarations(variableDeclarations: JS.ScopedVariableDeclarations, p: PrintOutputCapture

): J.J { + this.beforeSyntax(variableDeclarations, JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_PREFIX, p); + + variableDeclarations.modifiers.forEach(m => this.visitModifier(m, p)); + + const scope = variableDeclarations.padding.scope; + if (scope) { + this.visitSpace(scope.before, JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_SCOPE_PREFIX, p); + + switch (scope.element) { + case JS.ScopedVariableDeclarations.Scope.Let: + p.append("let"); + break; + case JS.ScopedVariableDeclarations.Scope.Const: + p.append("const"); + break; + case JS.ScopedVariableDeclarations.Scope.Var: + p.append("var"); + break; + case JS.ScopedVariableDeclarations.Scope.Using: + p.append("using"); + break; + case JS.ScopedVariableDeclarations.Scope.Import: + p.append("import"); + break; + } + } + + this.visitJsRightPaddedLocal(variableDeclarations.padding.variables, JsRightPadded.Location.SCOPED_VARIABLE_DECLARATIONS_VARIABLES, ",", p); + + this.afterSyntax(variableDeclarations, p); + return variableDeclarations; + } + + visitVariableDeclarations(multiVariable: J.VariableDeclarations, p: PrintOutputCapture

): J.J { + this.beforeSyntax(multiVariable, Space.Location.VARIABLE_DECLARATIONS_PREFIX, p); + this.visitNodes(multiVariable.leadingAnnotations, p); + + multiVariable.modifiers.forEach(it => this.visitModifier(it, p)); + + const variables = multiVariable.padding.variables; + for (let i = 0; i < variables.length; i++) { + const variable = variables[i]; + + this.beforeSyntax(variable.element, Space.Location.VARIABLE_PREFIX, p); + + if (multiVariable.varargs) { + p.append("..."); + } + + this.visit(variable.element.name, p); + this.visitSpace(variable.after, Space.Location.NAMED_VARIABLE_SUFFIX, p); + + if (multiVariable.typeExpression) { + this.visit(multiVariable.typeExpression, p); + } + + if (variable.element.initializer) { + this.visitJLeftPaddedLocal("=", variable.element.padding.initializer, JLeftPadded.Location.VARIABLE_INITIALIZER, p); + } + + this.afterSyntax(variable.element, p); + + if (i < variables.length - 1) { + p.append(","); + } else if (variable.markers.findFirst(Semicolon)) { + p.append(";"); + } + } + + this.afterSyntax(multiVariable, p); + return multiVariable; + } + + visitVariable(variable: J.VariableDeclarations.NamedVariable, p: PrintOutputCapture

): J.J { + this.beforeSyntax(variable, Space.Location.VARIABLE_PREFIX, p); + this.visit(variable.name, p); + + const initializer: JLeftPadded | null = variable.padding.initializer; + this.visitJLeftPaddedLocal("=", initializer, JLeftPadded.Location.VARIABLE_INITIALIZER, p); + + this.afterSyntax(variable, p); + return variable; + } + + visitIdentifier(ident: J.Identifier, p: PrintOutputCapture

): J.J { + this.visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); + this.visitNodes(ident.annotations, p); + this.beforeSyntax(ident, Space.Location.IDENTIFIER_PREFIX, p); + p.append(ident.simpleName); + this.afterSyntax(ident, p); + return ident; + } + + visitFunctionDeclaration(functionDeclaration: JS.FunctionDeclaration, p: PrintOutputCapture

): JS.FunctionDeclaration { + this.beforeSyntax(functionDeclaration, JsSpace.Location.FUNCTION_DECLARATION_PREFIX, p); + + functionDeclaration.modifiers.forEach((m) => this.visitModifier(m, p)); + + this.visitJsLeftPaddedLocal("function", functionDeclaration.padding.asteriskToken, JsLeftPadded.Location.FUNCTION_DECLARATION_ASTERISK_TOKEN, p); + + this.visitJsLeftPaddedLocal(functionDeclaration.asteriskToken ? "*" : "", functionDeclaration.padding.name, JsLeftPadded.Location.FUNCTION_DECLARATION_NAME, p); + + const typeParameters = functionDeclaration.typeParameters; + if (typeParameters !== null) { + this.visitNodes(typeParameters.annotations, p); + this.visitSpace(typeParameters.prefix, Space.Location.TYPE_PARAMETERS, p); + this.visitMarkers(typeParameters.markers, p); + p.append("<"); + this.visitJRightPaddedLocal(typeParameters.padding.typeParameters, JRightPadded.Location.TYPE_PARAMETER, ",", p); + p.append(">"); + } + + this.visitJsContainerLocal("(", functionDeclaration.padding.parameters, JsContainer.Location.FUNCTION_DECLARATION_PARAMETERS, ",", ")", p); + + if (functionDeclaration.returnTypeExpression !== null) { + this.visit(functionDeclaration.returnTypeExpression, p); + } + + if (functionDeclaration.body !== null) { + this.visit(functionDeclaration.body, p); + } + + this.afterSyntax(functionDeclaration, p); + + return functionDeclaration; + } + + visitBlock(block: J.Block, p: PrintOutputCapture

): J.Block { + this.beforeSyntax(block, Space.Location.BLOCK_PREFIX, p); + + if (block.static) { + p.append("static"); + this.visitRightPadded(block.padding.static, JRightPadded.Location.STATIC_INIT, p); + } + + p.append("{"); + this.visitStatements(block.padding.statements, JRightPadded.Location.BLOCK_STATEMENT, p); + this.visitSpace(block.end, Space.Location.BLOCK_END, p); + p.append("}"); + + this.afterSyntax(block, p); + return block; + } + + visitTypeInfo(typeInfo: JS.TypeInfo, p: PrintOutputCapture

): JS.TypeInfo { + this.beforeSyntax(typeInfo, JsSpace.Location.TYPE_INFO_PREFIX, p); + p.append(":"); + this.visit(typeInfo.typeIdentifier, p); + this.afterSyntax(typeInfo, p); + return typeInfo; + } + + visitReturn(return_: J.Return, p: PrintOutputCapture

): J.Return { + this.beforeSyntax(return_, Space.Location.RETURN_PREFIX, p); + p.append("return"); + this.visit(return_.expression, p); + this.afterSyntax(return_, p); + return return_; + } + + public visitModifier(mod: J.Modifier, p: PrintOutputCapture

): J.Modifier { + this.visitNodes(mod.annotations, p); + + let keyword: string; + switch (mod.type) { + case J.Modifier.Type.Default: + keyword = "default"; + break; + case J.Modifier.Type.Public: + keyword = "public"; + break; + case J.Modifier.Type.Protected: + keyword = "protected"; + break; + case J.Modifier.Type.Private: + keyword = "private"; + break; + case J.Modifier.Type.Abstract: + keyword = "abstract"; + break; + case J.Modifier.Type.Async: + keyword = "async"; + break; + case J.Modifier.Type.Static: + keyword = "static"; + break; + case J.Modifier.Type.Final: + keyword = "final"; + break; + case J.Modifier.Type.Native: + keyword = "native"; + break; + case J.Modifier.Type.NonSealed: + keyword = "non-sealed"; + break; + case J.Modifier.Type.Sealed: + keyword = "sealed"; + break; + case J.Modifier.Type.Strictfp: + keyword = "strictfp"; + break; + case J.Modifier.Type.Synchronized: + keyword = "synchronized"; + break; + case J.Modifier.Type.Transient: + keyword = "transient"; + break; + case J.Modifier.Type.Volatile: + keyword = "volatile"; + break; + default: + keyword = mod.keyword ?? ""; + } + + this.beforeSyntax(mod, Space.Location.MODIFIER_PREFIX, p); + p.append(keyword); + this.afterSyntax(mod, p); + return mod; + } + + visitFunctionType(functionType: JS.FunctionType, p: PrintOutputCapture

): JS.FunctionType { + this.beforeSyntax(functionType, JsSpace.Location.FUNCTION_TYPE_PREFIX, p); + functionType.modifiers.forEach(m => this.visitModifier(m, p)); + + if (functionType.constructorType) { + this.visitJsLeftPaddedLocal("new", functionType.padding.constructorType, JsLeftPadded.Location.FUNCTION_TYPE_CONSTRUCTOR_TYPE, p); + } + + const typeParameters = functionType.typeParameters; + if (typeParameters) { + this.visitNodes(typeParameters.annotations, p); + this.visitSpace(typeParameters.prefix, Space.Location.TYPE_PARAMETERS, p); + this.visitMarkers(typeParameters.markers, p); + p.append("<"); + this.visitJRightPaddedLocal(typeParameters.padding.typeParameters, JRightPadded.Location.TYPE_PARAMETER, ",", p); + p.append(">"); + } + + this.visitJsContainerLocal("(", functionType.padding.parameters, JsContainer.Location.FUNCTION_TYPE_PARAMETERS, ",", ")", p); + this.visitJsLeftPaddedLocal("=>", functionType.padding.returnType, JsLeftPadded.Location.FUNCTION_TYPE_RETURN_TYPE, p); + + this.afterSyntax(functionType, p); + return functionType; + } + + visitClassDeclaration(classDecl: J.ClassDeclaration, p: PrintOutputCapture

): J.ClassDeclaration { + let kind = ""; + switch (classDecl.padding.kind.type) { + case J.ClassDeclaration.Kind.Type.Class: + kind = "class"; + break; + case J.ClassDeclaration.Kind.Type.Enum: + kind = "enum"; + break; + case J.ClassDeclaration.Kind.Type.Interface: + kind = "interface"; + break; + case J.ClassDeclaration.Kind.Type.Annotation: + kind = "@interface"; + break; + case J.ClassDeclaration.Kind.Type.Record: + kind = "record"; + break; + } + + this.beforeSyntax(classDecl, Space.Location.CLASS_DECLARATION_PREFIX, p); + this.visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); + this.visitNodes(classDecl.leadingAnnotations, p); + classDecl.modifiers.forEach(m => this.visitModifier(m, p)); + this.visitNodes(classDecl.padding.kind.annotations, p); + this.visitSpace(classDecl.padding.kind.prefix, Space.Location.CLASS_KIND, p); + p.append(kind); + this.visit(classDecl.name, p); + this.visitJContainerLocal("<", classDecl.padding.typeParameters, JContainer.Location.TYPE_PARAMETERS, ",", ">", p); + this.visitJContainerLocal("(", classDecl.padding.primaryConstructor, JContainer.Location.RECORD_STATE_VECTOR, ",", ")", p); + this.visitJLeftPaddedLocal("extends", classDecl.padding.extends, JLeftPadded.Location.EXTENDS, p); + this.visitJContainerLocal(classDecl.padding.kind.type === J.ClassDeclaration.Kind.Type.Interface ? "extends" : "implements", + classDecl.padding.implements, JContainer.Location.IMPLEMENTS, ",", null, p); + this.visit(classDecl.body, p); + this.afterSyntax(classDecl, p); + + return classDecl; + } + + visitMethodDeclaration(method: J.MethodDeclaration, p: PrintOutputCapture

): J.J { + this.beforeSyntax(method, Space.Location.METHOD_DECLARATION_PREFIX, p); + this.visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); + this.visitNodes(method.leadingAnnotations, p); + method.modifiers.forEach(m => this.visitModifier(m, p)); + + this.visit(method.padding.name.identifier, p); + + const typeParameters = method.annotations.typeParameters; + if (typeParameters) { + this.visitNodes(typeParameters.annotations, p); + this.visitSpace(typeParameters.prefix, Space.Location.TYPE_PARAMETERS, p); + this.visitMarkers(typeParameters.markers, p); + p.append("<"); + this.visitJRightPaddedLocal(typeParameters.padding.typeParameters, JRightPadded.Location.TYPE_PARAMETER, ",", p); + p.append(">"); + } + + this.visitJContainerLocal("(", method.padding.parameters, JContainer.Location.METHOD_DECLARATION_PARAMETERS, ",", ")", p); + + if (method.returnTypeExpression) { + this.visit(method.returnTypeExpression, p); + } + + this.visit(method.body, p); + this.afterSyntax(method, p); + return method; + } + + visitJSMethodDeclaration(method: JS.JSMethodDeclaration, p: PrintOutputCapture

): JS.JSMethodDeclaration { + this.beforeSyntax(method, JsSpace.Location.JSMETHOD_DECLARATION_PREFIX, p); + this.visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); + this.visitNodes(method.leadingAnnotations, p); + method.modifiers.forEach(it => this.visitModifier(it, p)); + + this.visit(method.name, p); + + const typeParameters = method.typeParameters; + if (typeParameters) { + this.visitNodes(typeParameters.annotations, p); + this.visitSpace(typeParameters.prefix, Space.Location.TYPE_PARAMETERS, p); + this.visitMarkers(typeParameters.markers, p); + p.append("<"); + this.visitJRightPaddedLocal(typeParameters.padding.typeParameters, JRightPadded.Location.TYPE_PARAMETER, ",", p); + p.append(">"); + } + + this.visitJsContainerLocal("(", method.padding.parameters, JsContainer.Location.JSMETHOD_DECLARATION_PARAMETERS, ",", ")", p); + if (method.returnTypeExpression) { + this.visit(method.returnTypeExpression, p); + } + + this.visit(method.body, p); + this.afterSyntax(method, p); + return method; + } + + visitMethodInvocation(method: J.MethodInvocation, p: PrintOutputCapture

): J.MethodInvocation { + this.beforeSyntax(method, Space.Location.METHOD_INVOCATION_PREFIX, p); + + if (method.name.toString().length === 0) { + this.visitRightPadded(method.padding.select, JRightPadded.Location.METHOD_SELECT, p); + } else { + this.visitJRightPaddedLocal(method.padding.select ? [method.padding.select] : [], JRightPadded.Location.METHOD_SELECT, ".", p); + this.visit(method.name, p); + } + + this.visitJContainerLocal("<", method.padding.typeParameters, JContainer.Location.TYPE_PARAMETERS, ",", ">", p); + this.visitJContainerLocal("(", method.padding.arguments, JContainer.Location.METHOD_INVOCATION_ARGUMENTS, ",", ")", p); + + this.afterSyntax(method, p); + return method; + } + + visitTypeParameter(typeParameter: J.TypeParameter, p: PrintOutputCapture

): J.TypeParameter { + this.beforeSyntax(typeParameter, Space.Location.TYPE_PARAMETERS_PREFIX, p); + this.visitNodes(typeParameter.annotations, p); + typeParameter.modifiers.forEach(m => this.visitModifier(m, p)); + this.visit(typeParameter.name, p); + + const bounds = typeParameter.padding.bounds; + if (bounds) { + this.visitSpace(bounds.before, JContainer.Location.beforeLocation(JContainer.Location.TYPE_BOUNDS), p); + const constraintType = bounds.padding.elements[0]; + + if (!(constraintType.element instanceof J.Empty)) { + p.append("extends"); + this.visitRightPadded(constraintType, JContainer.Location.elementLocation(JContainer.Location.TYPE_BOUNDS), p); + } + + const defaultType = bounds.padding.elements[1]; + if (!(defaultType.element instanceof J.Empty)) { + p.append("="); + this.visitRightPadded(defaultType, JContainer.Location.elementLocation(JContainer.Location.TYPE_BOUNDS), p); + } + } + + this.afterSyntax(typeParameter, p); + return typeParameter; + } + + visitArrowFunction(arrowFunction: JS.ArrowFunction, p: PrintOutputCapture

): J.J { + this.beforeSyntax(arrowFunction, JsSpace.Location.ARROW_FUNCTION_PREFIX, p); + this.visitNodes(arrowFunction.leadingAnnotations, p); + arrowFunction.modifiers.forEach(m => this.visitModifier(m, p)); + + const typeParameters = arrowFunction.typeParameters; + if (typeParameters) { + this.visitNodes(typeParameters.annotations, p); + this.visitSpace(typeParameters.prefix, Space.Location.TYPE_PARAMETERS, p); + this.visitMarkers(typeParameters.markers, p); + p.append("<"); + this.visitJRightPaddedLocal(typeParameters.padding.typeParameters, JRightPadded.Location.TYPE_PARAMETER, ",", p); + p.append(">"); + } + + if (arrowFunction.parameters.parenthesized) { + this.visitSpace(arrowFunction.parameters.prefix, Space.Location.LAMBDA_PARAMETERS_PREFIX, p); + p.append("("); + this.visitJRightPaddedLocal(arrowFunction.parameters.padding.parameters, JRightPadded.Location.LAMBDA_PARAM, ",", p); + p.append(")"); + } else { + this.visitJRightPaddedLocal(arrowFunction.parameters.padding.parameters, JRightPadded.Location.LAMBDA_PARAM, ",", p); + } + + if (arrowFunction.returnTypeExpression) { + this.visit(arrowFunction.returnTypeExpression, p); + } + + this.visitJsLeftPaddedLocal("=>", arrowFunction.padding.body, JsLeftPadded.Location.ARROW_FUNCTION_BODY, p); + + this.afterSyntax(arrowFunction, p); + return arrowFunction; + } + + visitConditionalType(conditionalType: JS.ConditionalType, p: PrintOutputCapture

): J.J { + this.beforeSyntax(conditionalType, JsSpace.Location.CONDITIONAL_TYPE_PREFIX, p); + this.visit(conditionalType.checkType, p); + this.visitJsContainerLocal("extends", conditionalType.padding.condition, JsContainer.Location.CONDITIONAL_TYPE_CONDITION, "", "", p); + this.afterSyntax(conditionalType, p); + return conditionalType; + } + + visitExpressionWithTypeArguments(type: JS.ExpressionWithTypeArguments, p: PrintOutputCapture

): J.J { + this.beforeSyntax(type, JsSpace.Location.EXPRESSION_WITH_TYPE_ARGUMENTS_PREFIX, p); + this.visit(type.clazz, p); + this.visitJsContainerLocal("<", type.padding.typeArguments, JsContainer.Location.EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS, ",", ">", p); + this.afterSyntax(type, p); + return type; + } + + visitImportType(importType: JS.ImportType, p: PrintOutputCapture

): J.J { + this.beforeSyntax(importType, JsSpace.Location.IMPORT_TYPE_PREFIX, p); + + if (importType.hasTypeof) { + p.append("typeof"); + this.visitJsRightPadded(importType.padding.hasTypeof, JsRightPadded.Location.IMPORT_TYPE_HAS_TYPEOF, p); + } + + p.append("import"); + this.visitJsContainerLocal("(", importType.padding.argumentAndAttributes, JsContainer.Location.IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES, ",", ")", p); + this.visitJsLeftPaddedLocal(".", importType.padding.qualifier, JsLeftPadded.Location.IMPORT_TYPE_QUALIFIER, p); + this.visitJsContainerLocal("<", importType.padding.typeArguments, JsContainer.Location.IMPORT_TYPE_TYPE_ARGUMENTS, ",", ">", p); + + this.afterSyntax(importType, p); + return importType; + } + + visitTypeDeclaration(typeDeclaration: JS.TypeDeclaration, p: PrintOutputCapture

): J.J { + this.beforeSyntax(typeDeclaration, JsSpace.Location.TYPE_DECLARATION_PREFIX, p); + + typeDeclaration.modifiers.forEach(m => this.visitModifier(m, p)); + + this.visitJsLeftPaddedLocal("type", typeDeclaration.padding.name, JsLeftPadded.Location.TYPE_DECLARATION_NAME, p); + + const typeParameters = typeDeclaration.typeParameters; + if (typeParameters) { + this.visitNodes(typeParameters.annotations, p); + this.visitSpace(typeParameters.prefix, Space.Location.TYPE_PARAMETERS, p); + this.visitMarkers(typeParameters.markers, p); + p.append("<"); + this.visitJRightPaddedLocal(typeParameters.padding.typeParameters, JRightPadded.Location.TYPE_PARAMETER, ",", p); + p.append(">"); + } + + this.visitJsLeftPaddedLocal("=", typeDeclaration.padding.initializer, JsLeftPadded.Location.TYPE_DECLARATION_INITIALIZER, p); + + this.afterSyntax(typeDeclaration, p); + return typeDeclaration; + } + + visitLiteralType(literalType: JS.LiteralType, p: PrintOutputCapture

): J.J { + this.beforeSyntax(literalType, JsSpace.Location.LITERAL_TYPE_PREFIX, p); + this.visit(literalType.literal, p); + this.afterSyntax(literalType, p); + return literalType; + } + + visitNamedImports(namedImports: JS.NamedImports, p: PrintOutputCapture

): J.J { + this.beforeSyntax(namedImports, JsSpace.Location.NAMED_IMPORTS_PREFIX, p); + this.visitJsContainerLocal("{", namedImports.padding.elements, JsContainer.Location.NAMED_IMPORTS_ELEMENTS, ",", "}", p); + this.afterSyntax(namedImports, p); + return namedImports; + } + + visitNamedExports(ne: JS.NamedExports, p: PrintOutputCapture

): J.J { + this.beforeSyntax(ne, JsSpace.Location.NAMED_EXPORTS_PREFIX, p); + this.visitJsContainerLocal("{", ne.padding.elements, JsContainer.Location.NAMED_EXPORTS_ELEMENTS, ",", "}", p); + this.afterSyntax(ne, p); + return ne; + } + + visitImportAttributes(importAttributes: JS.ImportAttributes, p: PrintOutputCapture

): J.J { + this.beforeSyntax(importAttributes, JsSpace.Location.IMPORT_ATTRIBUTES_PREFIX, p); + + p.append(JS.ImportAttributes.Token[importAttributes.token].toLowerCase()); + this.visitJsContainerLocal("{", importAttributes.padding.elements, JsContainer.Location.IMPORT_ATTRIBUTES_ELEMENTS, ",", "}", p); + + this.afterSyntax(importAttributes, p); + return importAttributes; + } + + visitImportAttribute(importAttribute: JS.ImportAttribute, p: PrintOutputCapture

): J.J { + this.beforeSyntax(importAttribute, JsSpace.Location.IMPORT_ATTRIBUTE_PREFIX, p); + + this.visit(importAttribute.name, p); + this.visitJsLeftPaddedLocal(":", importAttribute.padding.value, JsLeftPadded.Location.IMPORT_ATTRIBUTE_VALUE, p); + + this.afterSyntax(importAttribute, p); + return importAttribute; + } + + visitImportTypeAttributes(importAttributes: JS.ImportTypeAttributes, p: PrintOutputCapture

): J.J { + this.beforeSyntax(importAttributes, JsSpace.Location.IMPORT_TYPE_ATTRIBUTES_PREFIX, p); + p.append("{"); + + this.visitJsRightPadded(importAttributes.padding.token, JsRightPadded.Location.IMPORT_TYPE_ATTRIBUTES_TOKEN, p); + p.append(":"); + this.visitJsContainerLocal("{", importAttributes.padding.elements, JsContainer.Location.IMPORT_TYPE_ATTRIBUTES_ELEMENTS, ",", "}", p); + this.visitSpace(importAttributes.end, JsSpace.Location.IMPORT_TYPE_ATTRIBUTES_END, p); + + p.append("}"); + this.afterSyntax(importAttributes, p); + return importAttributes; + } + + visitArrayBindingPattern(abp: JS.ArrayBindingPattern, p: PrintOutputCapture

): J.J { + this.beforeSyntax(abp, JsSpace.Location.ARRAY_BINDING_PATTERN_PREFIX, p); + + this.visitJsContainerLocal("[", abp.padding.elements, JsContainer.Location.ARRAY_BINDING_PATTERN_ELEMENTS, ",", "]", p); + + this.afterSyntax(abp, p); + return abp; + } + + visitMappedType(mappedType: JS.MappedType, p: PrintOutputCapture

): J.J { + this.beforeSyntax(mappedType, JsSpace.Location.MAPPED_TYPE_PREFIX, p); + p.append("{"); + + if (mappedType.prefixToken != null) { + this.visitJsLeftPadded(mappedType.padding.prefixToken, JsLeftPadded.Location.MAPPED_TYPE_PREFIX_TOKEN, p); + } + + if (mappedType.hasReadonly) { + this.visitJsLeftPaddedLocal("readonly", mappedType.padding.hasReadonly, JsLeftPadded.Location.MAPPED_TYPE_HAS_READONLY, p); + } + + this.visitMappedTypeKeysRemapping(mappedType.keysRemapping, p); + + if (mappedType.suffixToken != null) { + this.visitJsLeftPadded(mappedType.padding.suffixToken, JsLeftPadded.Location.MAPPED_TYPE_SUFFIX_TOKEN, p); + } + + if (mappedType.hasQuestionToken) { + this.visitJsLeftPaddedLocal("?", mappedType.padding.hasQuestionToken, JsLeftPadded.Location.MAPPED_TYPE_HAS_QUESTION_TOKEN, p); + } + + const colon = mappedType.valueType[0] instanceof J.Empty ? "" : ":"; + this.visitJsContainerLocal(colon, mappedType.padding.valueType, JsContainer.Location.MAPPED_TYPE_VALUE_TYPE, "", "", p); + + p.append("}"); + this.afterSyntax(mappedType, p); + return mappedType; + } + + visitMappedTypeKeysRemapping(mappedTypeKeys: JS.MappedType.KeysRemapping, p: PrintOutputCapture

): J.J { + this.beforeSyntax(mappedTypeKeys, JsSpace.Location.MAPPED_TYPE_KEYS_REMAPPING_PREFIX, p); + p.append("["); + this.visitJsRightPadded(mappedTypeKeys.padding.typeParameter, JsRightPadded.Location.MAPPED_TYPE_KEYS_REMAPPING_TYPE_PARAMETER, p); + + if (mappedTypeKeys.nameType != null) { + p.append("as"); + this.visitJsRightPadded(mappedTypeKeys.padding.nameType, JsRightPadded.Location.MAPPED_TYPE_KEYS_REMAPPING_NAME_TYPE, p); + } + + p.append("]"); + this.afterSyntax(mappedTypeKeys, p); + return mappedTypeKeys; + } + + visitMappedTypeMappedTypeParameter(mappedTypeParameter: JS.MappedType.MappedTypeParameter, p: PrintOutputCapture

): J.J { + this.beforeSyntax(mappedTypeParameter, JsSpace.Location.MAPPED_TYPE_MAPPED_TYPE_PARAMETER_PREFIX, p); + this.visit(mappedTypeParameter.name, p); + this.visitJsLeftPaddedLocal("in", mappedTypeParameter.padding.iterateType, JsLeftPadded.Location.MAPPED_TYPE_MAPPED_TYPE_PARAMETER_ITERATE_TYPE, p); + this.afterSyntax(mappedTypeParameter, p); + return mappedTypeParameter; + } + + visitObjectBindingDeclarations(objectBindingDeclarations: JS.ObjectBindingDeclarations, p: PrintOutputCapture

): J.J { + this.beforeSyntax(objectBindingDeclarations, JsSpace.Location.OBJECT_BINDING_DECLARATIONS_PREFIX, p); + this.visitNodes(objectBindingDeclarations.leadingAnnotations, p); + objectBindingDeclarations.modifiers.forEach(m => this.visitModifier(m, p)); + + this.visit(objectBindingDeclarations.typeExpression, p); + this.visitJsContainerLocal("{", objectBindingDeclarations.padding.bindings, JsContainer.Location.OBJECT_BINDING_DECLARATIONS_BINDINGS, ",", "}", p); + this.visitJsLeftPaddedLocal("=", objectBindingDeclarations.padding.initializer, JsLeftPadded.Location.OBJECT_BINDING_DECLARATIONS_INITIALIZER, p); + this.afterSyntax(objectBindingDeclarations, p); + return objectBindingDeclarations; + } + + visitTaggedTemplateExpression(taggedTemplateExpression: JS.TaggedTemplateExpression, p: PrintOutputCapture

): J.J { + this.beforeSyntax(taggedTemplateExpression, JsSpace.Location.TAGGED_TEMPLATE_EXPRESSION_PREFIX, p); + this.visitJsRightPadded(taggedTemplateExpression.padding.tag, JsRightPadded.Location.TAGGED_TEMPLATE_EXPRESSION_TAG, p); + this.visitJsContainerLocal("<", taggedTemplateExpression.padding.typeArguments, JsContainer.Location.TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS, ",", ">", p); + this.visit(taggedTemplateExpression.templateExpression, p); + this.afterSyntax(taggedTemplateExpression, p); + return taggedTemplateExpression; + } + + visitTuple(tuple: JS.Tuple, p: PrintOutputCapture

): J.J { + this.beforeSyntax(tuple, JsSpace.Location.TUPLE_PREFIX, p); + this.visitJsContainerLocal("[", tuple.padding.elements, JsContainer.Location.TUPLE_ELEMENTS, ",", "]", p); + this.afterSyntax(tuple, p); + return tuple; + } + + visitTypeQuery(typeQuery: JS.TypeQuery, p: PrintOutputCapture

): J.J { + this.beforeSyntax(typeQuery, JsSpace.Location.TYPE_QUERY_PREFIX, p); + p.append("typeof"); + this.visit(typeQuery.typeExpression, p); + this.visitJsContainerLocal("<", typeQuery.padding.typeArguments, JsContainer.Location.TYPE_QUERY_TYPE_ARGUMENTS, ",", ">", p); + this.afterSyntax(typeQuery, p); + return typeQuery; + } + + visitIndexSignatureDeclaration(isd: JS.IndexSignatureDeclaration, p: PrintOutputCapture

): J.J { + this.beforeSyntax(isd, JsSpace.Location.INDEX_SIGNATURE_DECLARATION_PREFIX, p); + + isd.modifiers.forEach(m => this.visitModifier(m, p)); + this.visitJsContainerLocal("[", isd.padding.parameters, JsContainer.Location.INDEX_SIGNATURE_DECLARATION_PARAMETERS, "", "]", p); + this.visitJsLeftPaddedLocal(":", isd.padding.typeExpression, JsLeftPadded.Location.INDEX_SIGNATURE_DECLARATION_TYPE_EXPRESSION, p); + + this.afterSyntax(isd, p); + return isd; + } + + visitAnnotation(annotation: J.Annotation, p: PrintOutputCapture

): J.J { + this.beforeSyntax(annotation, Space.Location.ANNOTATION_PREFIX, p); + + p.append("@"); + this.visit(annotation.annotationType, p); + this.visitJContainerLocal("(", annotation.padding.arguments, JContainer.Location.ANNOTATION_ARGUMENTS, ",", ")", p); + + this.afterSyntax(annotation, p); + return annotation; + } + + visitNewArray(newArray: J.NewArray, p: PrintOutputCapture

): J.J { + this.beforeSyntax(newArray, Space.Location.NEW_ARRAY_PREFIX, p); + this.visit(newArray.typeExpression, p); + this.visitNodes(newArray.dimensions, p); + this.visitJContainerLocal("[", newArray.padding.initializer, JContainer.Location.NEW_ARRAY_INITIALIZER, ",", "]", p); + this.afterSyntax(newArray, p); + return newArray; + } + + visitNewClass(newClass: J.NewClass, p: PrintOutputCapture

): J.J { + this.beforeSyntax(newClass, Space.Location.NEW_CLASS_PREFIX, p); + this.visitJRightPaddedLocal(newClass.padding.enclosing ? [newClass.padding.enclosing] : [], JRightPadded.Location.NEW_CLASS_ENCLOSING, ".", p); + this.visitSpace(newClass.new, Space.Location.NEW_PREFIX, p); + + if (newClass.clazz) { + p.append("new"); + this.visit(newClass.clazz, p); + + if (!newClass.padding.arguments.markers.findFirst(J.OmitParentheses)) { + this.visitJContainerLocal("(", newClass.padding.arguments, JContainer.Location.NEW_CLASS_ARGUMENTS, ",", ")", p); + } + } + + this.visit(newClass.body, p); + this.afterSyntax(newClass, p); + return newClass; + } + + visitSwitch(switch_: J.Switch, p: PrintOutputCapture

): J.J { + this.beforeSyntax(switch_, Space.Location.SWITCH_PREFIX, p); + p.append("switch"); + this.visit(switch_.selector, p); + this.visit(switch_.cases, p); + this.afterSyntax(switch_, p); + return switch_; + } + + visitCase(case_: J.Case, p: PrintOutputCapture

): J.J { + this.beforeSyntax(case_, Space.Location.CASE_PREFIX, p); + + const elem = case_.caseLabels[0]; + if (!(elem instanceof J.Identifier) || elem.simpleName !== "default") { + p.append("case"); + } + + this.visitJContainerLocal("", case_.padding.caseLabels, JContainer.Location.CASE_CASE_LABELS, ",", "", p); + + this.visitSpace(case_.padding.statements.before, Space.Location.CASE, p); + p.append(case_.type === J.Case.Type.Statement ? ":" : "->"); + + this.visitStatements(case_.padding.statements.padding.elements, JRightPadded.Location.CASE, p); + + this.afterSyntax(case_, p); + return case_; + } + + visitBreak(breakStatement: J.Break, p: PrintOutputCapture

): J.J { + this.beforeSyntax(breakStatement, Space.Location.BREAK_PREFIX, p); + p.append("break"); + this.visit(breakStatement.label, p); + this.afterSyntax(breakStatement, p); + return breakStatement; + } + + visitFieldAccess(fieldAccess: J.FieldAccess, p: PrintOutputCapture

): J.FieldAccess { + this.beforeSyntax(fieldAccess, Space.Location.FIELD_ACCESS_PREFIX, p); + this.visit(fieldAccess.target, p); + //const postFixOperator = fieldAccess.markers.findFirst(PostFixOperator).orElse(null); + + this.visitJLeftPaddedLocal(".", fieldAccess.padding.name, JLeftPadded.Location.FIELD_ACCESS_NAME, p); + this.afterSyntax(fieldAccess, p); + return fieldAccess; + } + + visitTypeLiteral(tl: JS.TypeLiteral, p: PrintOutputCapture

): JS.TypeLiteral { + this.beforeSyntax(tl, JsSpace.Location.TYPE_LITERAL_PREFIX, p); + + this.visit(tl.members, p); + + this.afterSyntax(tl, p); + return tl; + } + + visitParentheses(parens: J.Parentheses, p: PrintOutputCapture

): J.J { + this.beforeSyntax(parens, Space.Location.PARENTHESES_PREFIX, p); + p.append('('); + this.visitJRightPaddedLocal(parens.padding.tree ? [parens.padding.tree] : [], JRightPadded.Location.PARENTHESES, "", p); + p.append(')'); + this.afterSyntax(parens, p); + return parens; + } + + visitParameterizedType(type: J.ParameterizedType, p: PrintOutputCapture

): J.J { + this.beforeSyntax(type, Space.Location.PARAMETERIZED_TYPE_PREFIX, p); + this.visit(type.clazz, p); + this.visitJContainerLocal("<", type.padding.typeParameters, JContainer.Location.TYPE_PARAMETERS, ",", ">", p); + this.afterSyntax(type, p); + return type; + } + + visitAssignment(assignment: J.Assignment, p: PrintOutputCapture

): J.J { + this.beforeSyntax(assignment, Space.Location.ASSIGNMENT_PREFIX, p); + this.visit(assignment.variable, p); + this.visitJLeftPaddedLocal("=", assignment.padding.assignment, JLeftPadded.Location.ASSIGNMENT, p); + this.afterSyntax(assignment, p); + return assignment; + } + + public visitPropertyAssignment(propertyAssignment: JS.PropertyAssignment, p: PrintOutputCapture

): J.J { + this.beforeSyntax(propertyAssignment, JsSpace.Location.PROPERTY_ASSIGNMENT_PREFIX, p); + + this.visitJsRightPadded(propertyAssignment.padding.name, JsRightPadded.Location.PROPERTY_ASSIGNMENT_NAME, p); + + if (propertyAssignment.initializer) { + // if property is not null, we should print it like `{ a: b }` + // otherwise, it is a shorthand assignment where we have stuff like `{ a }` only + if (propertyAssignment.assigmentToken === JS.PropertyAssignment.AssigmentToken.Colon) { + p.append(':'); + } else if (propertyAssignment.assigmentToken === JS.PropertyAssignment.AssigmentToken.Equals) { + p.append('='); + } + this.visit(propertyAssignment.initializer, p); + } + + this.afterSyntax(propertyAssignment, p); + return propertyAssignment; + } + + public visitAssignmentOperation(assignOp: J.AssignmentOperation, p: PrintOutputCapture

): J.J { + let keyword = ""; + switch (assignOp.operator) { + case J.AssignmentOperation.Type.Addition: + keyword = "+="; + break; + case J.AssignmentOperation.Type.Subtraction: + keyword = "-="; + break; + case J.AssignmentOperation.Type.Multiplication: + keyword = "*="; + break; + case J.AssignmentOperation.Type.Division: + keyword = "/="; + break; + case J.AssignmentOperation.Type.Modulo: + keyword = "%="; + break; + case J.AssignmentOperation.Type.BitAnd: + keyword = "&="; + break; + case J.AssignmentOperation.Type.BitOr: + keyword = "|="; + break; + case J.AssignmentOperation.Type.BitXor: + keyword = "^="; + break; + case J.AssignmentOperation.Type.LeftShift: + keyword = "<<="; + break; + case J.AssignmentOperation.Type.RightShift: + keyword = ">>="; + break; + case J.AssignmentOperation.Type.UnsignedRightShift: + keyword = ">>>="; + break; + } + + this.beforeSyntax(assignOp, Space.Location.ASSIGNMENT_OPERATION_PREFIX, p); + this.visit(assignOp.variable, p); + this.visitSpace(assignOp.padding.operator.before, Space.Location.ASSIGNMENT_OPERATION_OPERATOR, p); + p.append(keyword); + this.visit(assignOp.assignment, p); + this.afterSyntax(assignOp, p); + + return assignOp; + } + + visitJsAssignmentOperation(assignOp: JS.JsAssignmentOperation, p: PrintOutputCapture

): J.J { + let keyword = ""; + switch (assignOp.operator) { + case JS.JsAssignmentOperation.Type.QuestionQuestion: + keyword = "??="; + break; + case JS.JsAssignmentOperation.Type.And: + keyword = "&&="; + break; + case JS.JsAssignmentOperation.Type.Or: + keyword = "||="; + break; + case JS.JsAssignmentOperation.Type.Power: + keyword = "**"; + break; + case JS.JsAssignmentOperation.Type.Exp: + keyword = "**="; + break; + } + + this.beforeSyntax(assignOp, JsSpace.Location.JS_ASSIGNMENT_OPERATION_PREFIX, p); + this.visit(assignOp.variable, p); + this.visitSpace(assignOp.padding.operator.before, JsSpace.Location.JS_ASSIGNMENT_OPERATION_OPERATOR_PREFIX, p); + p.append(keyword); + this.visit(assignOp.assignment, p); + this.afterSyntax(assignOp, p); + + return assignOp; + } + + visitEnumValue(enum_: J.EnumValue, p: PrintOutputCapture

): J.J { + this.beforeSyntax(enum_, Space.Location.ENUM_VALUE_PREFIX, p); + this.visit(enum_.name, p); + + const initializer = enum_.initializer; + if (initializer) { + this.visitSpace(initializer.prefix, Space.Location.NEW_CLASS_PREFIX, p); + p.append("="); + // There can be only one argument + const expression = initializer.arguments[0]; + this.visit(expression, p); + return enum_; + } + + this.afterSyntax(enum_, p); + return enum_; + } + + visitEnumValueSet(enums: J.EnumValueSet, p: PrintOutputCapture

): J.J { + this.beforeSyntax(enums, Space.Location.ENUM_VALUE_SET_PREFIX, p); + this.visitJRightPaddedLocal(enums.padding.enums, JRightPadded.Location.ENUM_VALUE, ",", p); + + if (enums.terminatedWithSemicolon) { + p.append(","); + } + + this.afterSyntax(enums, p); + return enums; + } + + visitBinary(binary: J.Binary, p: PrintOutputCapture

): J.J { + let keyword = ""; + switch (binary.operator) { + case J.Binary.Type.Addition: + keyword = "+"; + break; + case J.Binary.Type.Subtraction: + keyword = "-"; + break; + case J.Binary.Type.Multiplication: + keyword = "*"; + break; + case J.Binary.Type.Division: + keyword = "/"; + break; + case J.Binary.Type.Modulo: + keyword = "%"; + break; + case J.Binary.Type.LessThan: + keyword = "<"; + break; + case J.Binary.Type.GreaterThan: + keyword = ">"; + break; + case J.Binary.Type.LessThanOrEqual: + keyword = "<="; + break; + case J.Binary.Type.GreaterThanOrEqual: + keyword = ">="; + break; + case J.Binary.Type.Equal: + keyword = "=="; + break; + case J.Binary.Type.NotEqual: + keyword = "!="; + break; + case J.Binary.Type.BitAnd: + keyword = "&"; + break; + case J.Binary.Type.BitOr: + keyword = "|"; + break; + case J.Binary.Type.BitXor: + keyword = "^"; + break; + case J.Binary.Type.LeftShift: + keyword = "<<"; + break; + case J.Binary.Type.RightShift: + keyword = ">>"; + break; + case J.Binary.Type.UnsignedRightShift: + keyword = ">>>"; + break; + case J.Binary.Type.Or: + //keyword = binary.markers.find((marker) => marker instanceof Comma) ? "," : "||"; + keyword = "||"; + break; + case J.Binary.Type.And: + keyword = "&&"; + break; + } + + this.beforeSyntax(binary, Space.Location.BINARY_PREFIX, p); + this.visit(binary.left, p); + this.visitSpace(binary.padding.operator.before, Space.Location.BINARY_OPERATOR, p); + p.append(keyword); + this.visit(binary.right, p); + this.afterSyntax(binary, p); + + return binary; + } + + visitJsBinary(binary: JS.JsBinary, p: PrintOutputCapture

): J.J { + this.beforeSyntax(binary, JsSpace.Location.JS_BINARY_PREFIX, p); + + this.visit(binary.left, p); + let keyword = ""; + + switch (binary.operator) { + case JS.JsBinary.Type.As: + keyword = "as"; + break; + case JS.JsBinary.Type.IdentityEquals: + keyword = "==="; + break; + case JS.JsBinary.Type.IdentityNotEquals: + keyword = "!=="; + break; + case JS.JsBinary.Type.In: + keyword = "in"; + break; + case JS.JsBinary.Type.QuestionQuestion: + keyword = "??"; + break; + case JS.JsBinary.Type.Comma: + keyword = ","; + break; + } + + this.visitSpace(binary.padding.operator.before, JsSpace.Location.JS_BINARY_OPERATOR, p); + p.append(keyword); + + this.visit(binary.right, p); + + this.afterSyntax(binary, p); + return binary; + } + + visitUnary(unary: J.Unary, p: PrintOutputCapture

): J.Unary { + this.beforeSyntax(unary, Space.Location.UNARY_PREFIX, p); + switch (unary.operator) { + case J.Unary.Type.PreIncrement: + p.append("++"); + this.visit(unary.expression, p); + break; + case J.Unary.Type.PreDecrement: + p.append("--"); + this.visit(unary.expression, p); + break; + case J.Unary.Type.PostIncrement: + this.visit(unary.expression, p); + this.visitSpace(unary.padding.operator.before, Space.Location.UNARY_OPERATOR, p); + p.append("++"); + break; + case J.Unary.Type.PostDecrement: + this.visit(unary.expression, p); + this.visitSpace(unary.padding.operator.before, Space.Location.UNARY_OPERATOR, p); + p.append("--"); + break; + case J.Unary.Type.Positive: + p.append('+'); + this.visit(unary.expression, p); + break; + case J.Unary.Type.Negative: + p.append('-'); + this.visit(unary.expression, p); + break; + case J.Unary.Type.Complement: + p.append('~'); + this.visit(unary.expression, p); + break; + case J.Unary.Type.Not: + default: + p.append('!'); + this.visit(unary.expression, p); + } + this.afterSyntax(unary, p); + return unary; + } + + visitJsUnary(unary: JS.Unary, p: PrintOutputCapture

): J.J { + this.beforeSyntax(unary, JsSpace.Location.UNARY_PREFIX, p); + + switch (unary.operator) { + case JS.Unary.Type.Spread: + this.visitSpace(unary.padding.operator.before, JsSpace.Location.UNARY_OPERATOR, p); + p.append("..."); + this.visit(unary.expression, p); + break; + case JS.Unary.Type.Optional: + this.visit(unary.expression, p); + this.visitSpace(unary.padding.operator.before, JsSpace.Location.UNARY_OPERATOR, p); + p.append("?"); + break; + case JS.Unary.Type.Exclamation: + this.visit(unary.expression, p); + this.visitSpace(unary.padding.operator.before, JsSpace.Location.UNARY_OPERATOR, p); + p.append("!"); + break; + case JS.Unary.Type.QuestionDot: + this.visit(unary.expression, p); + this.visitSpace(unary.padding.operator.before, JsSpace.Location.UNARY_OPERATOR, p); + p.append("?"); + break; + case JS.Unary.Type.QuestionDotWithDot: + this.visit(unary.expression, p); + this.visitSpace(unary.padding.operator.before, JsSpace.Location.UNARY_OPERATOR, p); + p.append("?."); + break; + case JS.Unary.Type.Asterisk: + p.append("*"); + this.visitSpace(unary.padding.operator.before, JsSpace.Location.UNARY_OPERATOR, p); + this.visit(unary.expression, p); + break; + default: + break; + } + + this.afterSyntax(unary, p); + return unary; + } + + visitUnion(union: JS.Union, p: PrintOutputCapture

): JS.Union { + this.beforeSyntax(union, JsSpace.Location.UNION_PREFIX, p); + + this.visitJsRightPaddedLocal(union.padding.types, JsRightPadded.Location.UNION_TYPES, "|", p); + + this.afterSyntax(union, p); + return union; + } + + visitIntersection(intersection: JS.Intersection, p: PrintOutputCapture

): JS.Intersection { + this.beforeSyntax(intersection, JsSpace.Location.INTERSECTION_PREFIX, p); + + this.visitJsRightPaddedLocal(intersection.padding.types, JsRightPadded.Location.INTERSECTION_TYPES, "&", p); + + this.afterSyntax(intersection, p); + return intersection; + } + + visitForLoop(forLoop: J.ForLoop, p: PrintOutputCapture

): J.ForLoop { + this.beforeSyntax(forLoop, Space.Location.FOR_PREFIX, p); + p.append("for"); + const ctrl = forLoop.control; + this.visitSpace(ctrl.prefix, Space.Location.FOR_CONTROL_PREFIX, p); + p.append('('); + this.visitJRightPaddedLocal(ctrl.padding.init, JRightPadded.Location.FOR_INIT, ",", p); + p.append(';'); + this.visitJRightPaddedLocal(ctrl.padding.condition ? [ctrl.padding.condition] : [], JRightPadded.Location.FOR_CONDITION, "", p); + p.append(';'); + this.visitJRightPaddedLocal(ctrl.padding.update, JRightPadded.Location.FOR_UPDATE, ",", p); + p.append(')'); + this.visitStatementLocal(forLoop.padding.body, JRightPadded.Location.FOR_BODY, p); + this.afterSyntax(forLoop, p); + return forLoop; + } + + visitJSForOfLoop(loop: JS.JSForOfLoop, p: PrintOutputCapture

): JS.JSForOfLoop { + this.beforeSyntax(loop, JsSpace.Location.JSFOR_OF_LOOP_PREFIX, p); + p.append("for"); + if (loop.await) { + this.visitJsLeftPaddedLocal("await", loop.padding.await, JsLeftPadded.Location.JSFOR_OF_LOOP_AWAIT, p); + } + + const control = loop.control; + this.visitSpace(control.prefix, JsSpace.Location.JSFOR_IN_OF_LOOP_CONTROL_PREFIX, p); + p.append('('); + this.visitJsRightPadded(control.padding.variable, JsRightPadded.Location.JSFOR_IN_OF_LOOP_CONTROL_VARIABLE, p); + p.append("of"); + this.visitJsRightPadded(control.padding.iterable, JsRightPadded.Location.JSFOR_IN_OF_LOOP_CONTROL_ITERABLE, p); + p.append(')'); + this.visitJsRightPadded(loop.padding.body, JsRightPadded.Location.JSFOR_OF_LOOP_BODY, p); + this.afterSyntax(loop, p); + return loop; + } + + visitJSForInLoop(loop: JS.JSForInLoop, p: PrintOutputCapture

): JS.JSForInLoop { + this.beforeSyntax(loop, JsSpace.Location.JSFOR_IN_LOOP_PREFIX, p); + p.append("for"); + + const control = loop.control; + this.visitSpace(control.prefix, JsSpace.Location.JSFOR_IN_OF_LOOP_CONTROL_PREFIX, p); + p.append('('); + this.visitJsRightPadded(control.padding.variable, JsRightPadded.Location.JSFOR_IN_OF_LOOP_CONTROL_VARIABLE, p); + p.append("in"); + this.visitJsRightPadded(control.padding.iterable, JsRightPadded.Location.JSFOR_IN_OF_LOOP_CONTROL_ITERABLE, p); + p.append(')'); + this.visitJsRightPadded(loop.padding.body, JsRightPadded.Location.JSFOR_IN_LOOP_BODY, p); + this.afterSyntax(loop, p); + return loop; + } + + + + + + // ---- print utils + + private visitStatements(statements: JRightPadded[], location: JRightPadded.Location, p: PrintOutputCapture

) { + const objectLiteral = + this.getParentCursor(0)?.value() instanceof J.Block && + this.getParentCursor(1)?.value() instanceof J.NewClass; + + for (let i = 0; i < statements.length; i++) { + const paddedStat = statements[i]; + this.visitStatementLocal(paddedStat, location, p); + if (i < statements.length - 1 && objectLiteral) { + p.append(","); + } + } + } + + private visitStatementLocal(paddedStat: JRightPadded | null, location: JRightPadded.Location, p: PrintOutputCapture

) { + if (paddedStat !== null) { + this.visit(paddedStat.element, p); + this.visitSpace(paddedStat.after, JRightPadded.Location.afterLocation(location), p); + this.visitMarkers(paddedStat.markers, p); + } + } + + private getParentCursor(levels: number): Cursor | null { + let cursor: Cursor | null = this.cursor; + + for (let i = 0; i < levels && cursor !== null; i++) { + cursor = cursor.parent; + } + + return cursor; + } + + private afterSyntax(j: J.J, p: PrintOutputCapture

) { + this.afterSyntaxMarkers(j.markers, p); + } + + private afterSyntaxMarkers(markers: Markers, p: PrintOutputCapture

) { + for (const marker of markers.markers) { + p.out.concat(p.markerPrinter.afterSyntax(marker, new Cursor(this.cursor, marker), this.JAVA_SCRIPT_MARKER_WRAPPER)); + } + } + + private beforeSyntax(j: J.J, loc: Space.Location | JsSpace.Location | null, p: PrintOutputCapture

) { + this.beforeSyntaxExt(j.prefix, j.markers, loc, p); + } + + private beforeSyntaxExt(prefix: Space, markers: Markers, loc: Space.Location | JsSpace.Location | null, p: PrintOutputCapture

) { + for (const marker of markers.markers) { + p.out.concat( + p.markerPrinter.beforePrefix(marker, new Cursor(this.cursor, marker), this.JAVA_SCRIPT_MARKER_WRAPPER) + ); + } + + if (loc !== null) { + this.visitSpace(prefix, loc, p); + } + + this.visitMarkers(markers, p); + + for (const marker of markers.markers) { + p.out.concat( + p.markerPrinter.beforeSyntax(marker, new Cursor(this.cursor, marker), this.JAVA_SCRIPT_MARKER_WRAPPER) + ); + } + } + + visitSpace(space: Space, loc: Space.Location | JsSpace.Location | null, p: PrintOutputCapture

): Space { + p.append(space.whitespace!); + + const comments = space.comments; + for (let i = 0; i < comments.length; i++) { + const comment = comments[i]; + this.visitMarkers(comment.markers, p); + this.printComment(comment, this.cursor, p); + p.append(comment.suffix); + } + + return space; + } + + private visitJRightPaddedLocal(nodes: JRightPadded[], location: JRightPadded.Location, suffixBetween: string, p: PrintOutputCapture

) { + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + + this.visit(node.element, p); + + if (location) { + const loc = JRightPadded.Location.afterLocation(location); + this.visitSpace(node.after, loc, p); + } + this.visitMarkers(node.markers, p); + + if (i < nodes.length - 1) { + p.append(suffixBetween); + } + } + } + + private visitJsRightPaddedLocal(nodes: JRightPadded[], location: JsRightPadded.Location, suffixBetween: string, p: PrintOutputCapture

) { + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + + this.visit(node.element, p); + + if (location) { + const loc = JsRightPadded.Location.afterLocation(location); + this.visitSpace(node.after, loc, p); + } + this.visitMarkers(node.markers, p); + + if (i < nodes.length - 1) { + p.append(suffixBetween); + } + } + } + + private visitJLeftPaddedLocal(prefix: string | null, leftPadded: JLeftPadded | JLeftPadded | null, location: JLeftPadded.Location, p: PrintOutputCapture

) { + if (leftPadded) { + const loc = JLeftPadded.Location.beforeLocation(location); + + this.beforeSyntaxExt(leftPadded.before, leftPadded.markers, loc, p); + + if (prefix) { + p.append(prefix); + } + + if (typeof leftPadded.element !== 'boolean') { + this.visit(leftPadded.element, p); + } + + this.afterSyntaxMarkers(leftPadded.markers, p); + } + } + + private visitJsLeftPaddedLocal(prefix: string | null, leftPadded: JLeftPadded | JLeftPadded | null, location: JsLeftPadded.Location, p: PrintOutputCapture

) { + if (leftPadded) { + const loc = JsLeftPadded.Location.beforeLocation(location); + + this.beforeSyntaxExt(leftPadded.before, leftPadded.markers, loc, p); + + if (prefix) { + p.append(prefix); + } + + if (typeof leftPadded.element !== 'boolean') { + this.visit(leftPadded.element, p); + } + + this.afterSyntaxMarkers(leftPadded.markers, p); + } + } + + private visitJContainerLocal(before: string, container: JContainer | null, location: JContainer.Location, suffixBetween: string, after: string | null, p: PrintOutputCapture

) { + if (container === null) { + return; + } + + const beforeLocation = JContainer.Location.beforeLocation(location); + const elementLocation = JContainer.Location.elementLocation(location); + this.beforeSyntaxExt(container.before, container.markers, beforeLocation, p); + + p.append(before); + this.visitJRightPaddedLocal(container.padding.elements, elementLocation, suffixBetween, p); + this.afterSyntaxMarkers(container.markers, p); + + p.append(after === null ? "" : after); + } + + private visitJsContainerLocal(before: string, container: JContainer | null, location: JsContainer.Location, suffixBetween: string, after: string | null, p: PrintOutputCapture

) { + if (container === null) { + return; + } + + const beforeLocation = JsContainer.Location.beforeLocation(location); + const elementLocation = JsContainer.Location.elementLocation(location); + this.beforeSyntaxExt(container.before, container.markers, beforeLocation, p); + + p.append(before); + this.visitJsRightPaddedLocal(container.padding.elements, elementLocation, suffixBetween, p); + this.afterSyntaxMarkers(container.markers, p); + + p.append(after === null ? "" : after); + } + + visitMarker(marker: M, p: PrintOutputCapture

): M { + if (marker instanceof Semicolon) { + p.append(';'); + } + if (marker instanceof TrailingComma) { + p.append(','); + this.visitSpace(marker.suffix, Space.Location.TRAILING_COMMA_SUFFIX, p); + } + return marker; + } + + private printComment(comment: J.Comment, cursor: Cursor, p: PrintOutputCapture

): void { + for (const marker of comment.markers.markers) { + p.append(p.markerPrinter.beforeSyntax(marker, new Cursor(cursor, this), this.JAVA_SCRIPT_MARKER_WRAPPER)); + } + + if (comment instanceof J.TextComment) { + p.append(comment.multiline ? `/*${comment.text}*/` : `//${comment.text}`); + } + + for (const marker of comment.markers.markers) { + p.append(p.markerPrinter.afterSyntax(marker, new Cursor(cursor, this), this.JAVA_SCRIPT_MARKER_WRAPPER)); + } + } + + private visitNodes(nodes: T[] | null | undefined, p: PrintOutputCapture

): void { + if (nodes) { + for (const node of nodes) { + this.visit(node, p); + } + } + } + + public visitControlParentheses(controlParens: J.ControlParentheses, p: PrintOutputCapture

): J.J { + this.beforeSyntax(controlParens, Space.Location.CONTROL_PARENTHESES_PREFIX, p); + + if (this.getParentCursor(0)?.value() instanceof J.TypeCast) { + p.append('<'); + this.visitJRightPaddedLocal(controlParens.padding.tree ? [controlParens.padding.tree] : [], JRightPadded.Location.PARENTHESES, "", p); + p.append('>') + } else { + p.append('('); + this.visitJRightPaddedLocal(controlParens.padding.tree ? [controlParens.padding.tree] : [], JRightPadded.Location.PARENTHESES, "", p); + p.append(')'); + } + + this.afterSyntax(controlParens, p); + return controlParens; + } + +} diff --git a/openrewrite/src/javascript/tree/support_types.ts b/openrewrite/src/javascript/tree/support_types.ts index 812c0d1e..c77ab725 100644 --- a/openrewrite/src/javascript/tree/support_types.ts +++ b/openrewrite/src/javascript/tree/support_types.ts @@ -183,17 +183,22 @@ export class StatementExpression extends JSMixin(Object) implements Expression, export namespace JsSpace { export enum Location { ALIAS_PREFIX, - ARROW_FUNCTION_ARROW, ARROW_FUNCTION_PREFIX, + ARROW_FUNCTION_BODY_PREFIX, + LAMBDA_ARROW_PREFIX, AWAIT_PREFIX, DEFAULT_TYPE_BEFORE_EQUALS, DEFAULT_TYPE_PREFIX, DELETE_PREFIX, EXPORT_FROM, EXPORT_PREFIX, - FUNCTION_TYPE_ARROW, + FUNCTION_TYPE_RETURN_TYPE_PREFIX, FUNCTION_TYPE_PREFIX, + FUNCTION_TYPE_CONSTRUCTOR_PREFIX, + FUNCTION_TYPE_PARAMETERS, + FUNCTION_TYPE_PARAMETER_SUFFIX, JS_BINARY_PREFIX, + JS_BINARY_OPERATOR, JS_IMPORT_FROM, JS_IMPORT_PREFIX, JS_IMPORT_IMPORT_TYPE_PREFIX, @@ -202,19 +207,29 @@ export namespace JsSpace { OBJECT_BINDING_DECLARATIONS_BINDING_AFTER_VARARG, BINDING_ELEMENT_PREFIX, OBJECT_BINDING_DECLARATIONS_PREFIX, + OBJECT_BINDING_DECLARATIONS_INITIALIZER_PREFIX, + OBJECT_BINDING_DECLARATIONS_BINDINGS_PREFIX, + OBJECT_BINDING_DECLARATIONS_BINDINGS_SUFFIX, PROPERTY_ASSIGNMENT_PREFIX, + PROPERTY_ASSIGNMENT_NAME_SUFFIX, SCOPED_VARIABLE_DECLARATIONS_PREFIX, SCOPED_VARIABLE_DECLARATIONS_SCOPE_PREFIX, + SCOPED_VARIABLE_DECLARATIONS_VARIABLE_SUFFIX, TEMPLATE_EXPRESSION_PREFIX, TEMPLATE_EXPRESSION_VALUE_AFTER, TEMPLATE_EXPRESSION_VALUE_PREFIX, TUPLE_PREFIX, + TUPLE_ELEMENTS_PREFIX, + TUPLE_ELEMENTS_SUFFIX, TYPE_DECLARATION_PREFIX, TYPE_DECLARATION_NAME_PREFIX, + TYPE_DECLARATION_INITIALIZER_PREFIX, TYPE_OF_PREFIX, TYPE_OPERATOR_PREFIX, UNARY_PREFIX, + UNARY_OPERATOR, UNION_PREFIX, + UNION_TYPES_SUFFIX, VOID_PREFIX, YIELD_PREFIX, TYPE_INFO_PREFIX, @@ -223,8 +238,14 @@ export namespace JsSpace { JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_PREFIX, NAMESPACE_DECLARATION_PREFIX, JSMETHOD_DECLARATION_PREFIX, + JSMETHOD_DECLARATION_PARAMETERS, FUNCTION_DECLARATION_PREFIX, + FUNCTION_DECLARATION_ASTERISK_TOKEN_PREFIX, + FUNCTION_DECLARATION_NAME_PREFIX, + FUNCTION_DECLARATION_PARAMETERS, + FUNCTION_DECLARATION_PARAMETERS_SUFFIX, INTERSECTION_PREFIX, + INTERSECTION_TYPES_SUFFIX, TYPE_LITERAL_PREFIX, TYPE_LITERAL_MEMBERS_PREFIX, TYPE_LITERAL_MEMBERS_SUFFIX, @@ -233,19 +254,46 @@ export namespace JsSpace { INDEX_SIGNATURE_DECLARATION_PARAMETERS_SUFFIX, INDEX_SIGNATURE_DECLARATION_TYPE_EXPRESSION_PREFIX, JSFOR_OF_LOOP_PREFIX, + JSFOR_OF_LOOP_AWAIT_PREFIX, + JSFOR_OF_LOOP_BODY_SUFFIX, JSFOR_IN_LOOP_PREFIX, + JSFOR_IN_LOOP_BODY_SUFFIX, JSFOR_IN_OF_LOOP_CONTROL_PREFIX, + JSFOR_IN_OF_LOOP_CONTROL_VARIABLE_SUFFIX, + JSFOR_IN_OF_LOOP_CONTROL_ITERABLE_SUFFIX, TYPE_QUERY_PREFIX, + TYPE_QUERY_TYPE_ARGUMENTS_PREFIX, + TYPE_QUERY_TYPE_ARGUMENTS_SUFFIX, ARRAY_BINDING_PATTERN_PREFIX, + ARRAY_BINDING_PATTERN_ELEMENTS_PREFIX, + ARRAY_BINDING_PATTERN_ELEMENTS_SUFFIX, EXPRESSION_WITH_TYPE_ARGUMENTS_PREFIX, + EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS, + EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS_SUFFIX, TEMPLATE_EXPRESSION_TEMPLATE_SPAN_PREFIX, TAGGED_TEMPLATE_EXPRESSION_PREFIX, + TAGGED_TEMPLATE_EXPRESSION_TAG_SUFFIX, + TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS_PREFIX, + TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS_SUFFIX, CONDITIONAL_TYPE_PREFIX, + CONDITIONAL_TYPE_CONDITION, + CONDITIONAL_TYPE_CONDITION_SUFFIX, INFER_TYPE_PREFIX, TYPE_PREDICATE_PREFIX, LITERAL_TYPE_PREFIX, SATISFIES_EXPRESSION_PREFIX, IMPORT_TYPE_PREFIX, + IMPORT_TYPE_HAS_TYPEOF_SUFFIX, + IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES, + IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES_SUFFIX, + IMPORT_TYPE_TYPE_ARGUMENTS, + IMPORT_TYPE_TYPE_ARGUMENTS_SUFFIX, + IMPORT_TYPE_QUALIFIER_PREFIX, + IMPORT_TYPE_ATTRIBUTES_PREFIX, + IMPORT_TYPE_ATTRIBUTES_END, + IMPORT_TYPE_ATTRIBUTES_TOKEN_SUFFIX, + IMPORT_TYPE_ATTRIBUTES_ELEMENTS_PREFIX, + IMPORT_TYPE_ATTRIBUTES_ELEMENTS_SUFFIX, EXPORT_DECLARATION_PREFIX, EXPORT_DECLARATION_TYPE_ONLY_PREFIX, EXPORT_SPECIFIER_PREFIX, @@ -256,20 +304,35 @@ export namespace JsSpace { INDEXED_ACCESS_TYPE_INDEX_TYPE_SUFFIX, INDEXED_ACCESS_TYPE_INDEX_TYPE_ELEMENT_SUFFIX, JS_ASSIGNMENT_OPERATION_PREFIX, + JS_ASSIGNMENT_OPERATION_OPERATOR_PREFIX, MAPPED_TYPE_PREFIX, + MAPPED_TYPE_PREFIX_TOKEN_PREFIX, + MAPPED_TYPE_HAS_READONLY_PREFIX, + MAPPED_TYPE_SUFFIX_TOKEN_PREFIX, + MAPPED_TYPE_HAS_QUESTION_TOKEN_PREFIX, + MAPPED_TYPE_VALUE_TYPE, + MAPPED_TYPE_VALUE_TYPE_SUFFIX, MAPPED_TYPE_KEYS_REMAPPING_PREFIX, + MAPPED_TYPE_KEYS_REMAPPING_TYPE_PARAMETER_SUFFIX, + MAPPED_TYPE_KEYS_REMAPPING_NAME_TYPE_SUFFIX, MAPPED_TYPE_MAPPED_TYPE_PARAMETER_PREFIX, + MAPPED_TYPE_MAPPED_TYPE_PARAMETER_ITERATE_TYPE_PREFIX, TYPE_TREE_EXPRESSION_PREFIX, TRAILING_TOKEN_STATEMENT_PREFIX, JSTRY_PREFIX, JSTRY_JSCATCH_PREFIX, WITH_STATEMENT_PREFIX, IMPORT_ATTRIBUTE_PREFIX, + IMPORT_ATTRIBUTE_VALUE_PREFIX, IMPORT_ATTRIBUTES_PREFIX, + IMPORT_ATTRIBUTES_ELEMENTS_PREFIX, + IMPORT_ATTRIBUTES_ELEMENTS_SUFFIX, NAMED_IMPORTS_PREFIX, + NAMED_IMPORTS_ELEMENTS_PREFIX, + NAMED_IMPORTS_ELEMENTS_SUFFIX, + NAMED_EXPORTS_ELEMENTS_PREFIX, + NAMED_EXPORTS_ELEMENTS_SUFFIX, JS_IMPORT_CLAUSE_PREFIX, - IMPORT_TYPE_ATTRIBUTES_PREFIX, - IMPORT_TYPE_ATTRIBUTES_END, } } export namespace JsLeftPadded { @@ -277,105 +340,168 @@ export namespace JsLeftPadded { EXPORT_INITIALIZER, JS_IMPORT_INITIALIZER, JS_IMPORT_IMPORT_TYPE, - JS_BINARY_OPERATOR, + JS_BINARY_OPERATOR = JsSpace.Location.JS_BINARY_OPERATOR, JS_OPERATOR_OPERATOR, - OBJECT_BINDING_DECLARATIONS_INITIALIZER, + OBJECT_BINDING_DECLARATIONS_INITIALIZER = JsSpace.Location.OBJECT_BINDING_DECLARATIONS_INITIALIZER_PREFIX, OBJECT_BINDING_DECLARATIONS_BINDING_DIMENSIONS_AFTER_NAME, OBJECT_BINDING_DECLARATIONS_BINDING_INITIALIZER, - TYPE_DECLARATION_INITIALIZER, - TYPE_DECLARATION_NAME, + TYPE_DECLARATION_INITIALIZER = JsSpace.Location.TYPE_DECLARATION_INITIALIZER_PREFIX, + TYPE_DECLARATION_NAME = JsSpace.Location.TYPE_DECLARATION_NAME_PREFIX, TYPE_OPERATOR_EXPRESSION, - UNARY_OPERATOR, + UNARY_OPERATOR = JsSpace.Location.UNARY_OPERATOR, JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_INITIALIZER, JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_DIMENSIONS_AFTER_NAME, JSMETHOD_DECLARATION_DEFAULT_VALUE, NAMESPACE_DECLARATION_KEYWORD_TYPE, - SCOPED_VARIABLE_DECLARATIONS_SCOPE, + SCOPED_VARIABLE_DECLARATIONS_SCOPE = JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_SCOPE_PREFIX, JS_IMPORT_SPECIFIER_IMPORT_TYPE, - INDEX_SIGNATURE_DECLARATION_TYPE_EXPRESSION, - JSFOR_OF_LOOP_AWAIT, + INDEX_SIGNATURE_DECLARATION_TYPE_EXPRESSION = JsSpace.Location.INDEX_SIGNATURE_DECLARATION_TYPE_EXPRESSION_PREFIX, + JSFOR_OF_LOOP_AWAIT = JsSpace.Location.JSFOR_OF_LOOP_AWAIT_PREFIX, BINDING_ELEMENT_INITIALIZER, INFER_TYPE_TYPE_PARAMETER, TYPE_PREDICATE_ASSERTS, TYPE_PREDICATE_EXPRESSION, SATISFIES_EXPRESSION_SATISFIES_TYPE, - IMPORT_TYPE_QUALIFIER, + IMPORT_TYPE_QUALIFIER = JsSpace.Location.IMPORT_TYPE_QUALIFIER_PREFIX, EXPORT_DECLARATION_TYPE_ONLY, EXPORT_SPECIFIER_TYPE_ONLY, EXPORT_ASSIGNMENT_EXPORT_EQUALS, EXPORT_DECLARATION_MODULE_SPECIFIER, - FUNCTION_DECLARATION_ASTERISK_TOKEN, - FUNCTION_DECLARATION_NAME, - JS_ASSIGNMENT_OPERATION_OPERATOR, - MAPPED_TYPE_PREFIX_TOKEN, - MAPPED_TYPE_SUFFIX_TOKEN, - MAPPED_TYPE_MAPPED_TYPE_PARAMETER_ITERATE_TYPE, - MAPPED_TYPE_HAS_READONLY, - MAPPED_TYPE_HAS_QUESTION_TOKEN, - ARROW_FUNCTION_BODY, + FUNCTION_DECLARATION_ASTERISK_TOKEN = JsSpace.Location.FUNCTION_DECLARATION_ASTERISK_TOKEN_PREFIX, + FUNCTION_DECLARATION_NAME = JsSpace.Location.FUNCTION_DECLARATION_NAME_PREFIX, + JS_ASSIGNMENT_OPERATION_OPERATOR = JsSpace.Location.JS_ASSIGNMENT_OPERATION_OPERATOR_PREFIX, + MAPPED_TYPE_PREFIX_TOKEN = JsSpace.Location.MAPPED_TYPE_PREFIX_TOKEN_PREFIX, + MAPPED_TYPE_SUFFIX_TOKEN = JsSpace.Location.MAPPED_TYPE_SUFFIX_TOKEN_PREFIX, + MAPPED_TYPE_MAPPED_TYPE_PARAMETER_ITERATE_TYPE = JsSpace.Location.MAPPED_TYPE_MAPPED_TYPE_PARAMETER_ITERATE_TYPE_PREFIX, + MAPPED_TYPE_HAS_READONLY = JsSpace.Location.MAPPED_TYPE_HAS_READONLY_PREFIX, + MAPPED_TYPE_HAS_QUESTION_TOKEN = JsSpace.Location.MAPPED_TYPE_HAS_QUESTION_TOKEN_PREFIX, + LAMBDA_ARROW = JsSpace.Location.LAMBDA_ARROW_PREFIX, + ARROW_FUNCTION_BODY = JsSpace.Location.ARROW_FUNCTION_BODY_PREFIX, YIELD_DELEGATED, - FUNCTION_TYPE_CONSTRUCTOR_TYPE, - FUNCTION_TYPE_RETURN_TYPE, + FUNCTION_TYPE_CONSTRUCTOR_TYPE = JsSpace.Location.FUNCTION_TYPE_CONSTRUCTOR_PREFIX, + FUNCTION_TYPE_RETURN_TYPE = JsSpace.Location.FUNCTION_TYPE_RETURN_TYPE_PREFIX, JSTRY_FINALLIE, - IMPORT_ATTRIBUTE_VALUE, + IMPORT_ATTRIBUTE_VALUE = JsSpace.Location.IMPORT_ATTRIBUTE_VALUE_PREFIX, JS_IMPORT_MODULE_SPECIFIER, JS_IMPORT_IMPORT_CLAUSE, } + + export namespace Location { + export function beforeLocation(location: Location): JsSpace.Location { + return location as unknown as JsSpace.Location; + } + } } export namespace JsRightPadded { export enum Location { ALIAS_PROPERTY_NAME, + ARRAY_BINDING_PATTERN_ELEMENTS = JsSpace.Location.ARRAY_BINDING_PATTERN_ELEMENTS_SUFFIX, COMPILATION_UNIT_STATEMENTS, + CONDITIONAL_TYPE_CONDITION = JsSpace.Location.CONDITIONAL_TYPE_CONDITION_SUFFIX, JS_IMPORT_NAME, BINDING_ELEMENT_PROPERTY_NAME, - PROPERTY_ASSIGNMENT_NAME, - SCOPED_VARIABLE_DECLARATIONS_VARIABLES, - UNION_TYPES, + PROPERTY_ASSIGNMENT_NAME = JsSpace.Location.PROPERTY_ASSIGNMENT_NAME_SUFFIX, + SCOPED_VARIABLE_DECLARATIONS_VARIABLES = JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_VARIABLE_SUFFIX, + UNION_TYPES = JsSpace.Location.UNION_TYPES_SUFFIX, JSVARIABLE_DECLARATIONS_VARIABLES, NAMESPACE_DECLARATION_NAME, - INTERSECTION_TYPES, + INTERSECTION_TYPES = JsSpace.Location.INTERSECTION_TYPES_SUFFIX, TYPE_LITERAL_MEMBERS, - INDEX_SIGNATURE_DECLARATION_PARAMETERS, - JSFOR_IN_OF_LOOP_CONTROL_VARIABLE, - JSFOR_IN_OF_LOOP_CONTROL_ITERABLE, - JSFOR_OF_LOOP_BODY, - JSFOR_IN_LOOP_BODY, + INDEX_SIGNATURE_DECLARATION_PARAMETERS = JsSpace.Location.INDEX_SIGNATURE_DECLARATION_PARAMETERS_SUFFIX, + JSFOR_IN_OF_LOOP_CONTROL_VARIABLE = JsSpace.Location.JSFOR_IN_OF_LOOP_CONTROL_VARIABLE_SUFFIX, + JSFOR_IN_OF_LOOP_CONTROL_ITERABLE = JsSpace.Location.JSFOR_IN_OF_LOOP_CONTROL_ITERABLE_SUFFIX, + JSFOR_OF_LOOP_BODY = JsSpace.Location.JSFOR_OF_LOOP_BODY_SUFFIX, + JSFOR_IN_LOOP_BODY = JsSpace.Location.JSFOR_IN_LOOP_BODY_SUFFIX, + JSMETHOD_DECLARATION_PARAMETER = JsSpace.Location.JSMETHOD_DECLARATION_PARAMETERS, TEMPLATE_EXPRESSION_TEMPLATE_SPANS, - TAGGED_TEMPLATE_EXPRESSION_TAG, - IMPORT_TYPE_HAS_TYPEOF, + TAGGED_TEMPLATE_EXPRESSION_TAG = JsSpace.Location.TAGGED_TEMPLATE_EXPRESSION_TAG_SUFFIX, + TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS = JsSpace.Location.TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS_SUFFIX, + IMPORT_TYPE_HAS_TYPEOF = JsSpace.Location.IMPORT_TYPE_HAS_TYPEOF_SUFFIX, + IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES = JsSpace.Location.IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES_SUFFIX, + IMPORT_TYPE_TYPE_ARGUMENTS = JsSpace.Location.IMPORT_TYPE_TYPE_ARGUMENTS_SUFFIX, INDEXED_ACCESS_TYPE_INDEX_TYPE, INDEXED_ACCESS_TYPE_INDEX_TYPE_ELEMENT, - MAPPED_TYPE_KEYS_REMAPPING_TYPE_PARAMETER, - MAPPED_TYPE_KEYS_REMAPPING_NAME_TYPE, + MAPPED_TYPE_VALUE_TYPE = JsSpace.Location.MAPPED_TYPE_VALUE_TYPE_SUFFIX, + MAPPED_TYPE_KEYS_REMAPPING_TYPE_PARAMETER = JsSpace.Location.MAPPED_TYPE_KEYS_REMAPPING_TYPE_PARAMETER_SUFFIX, + MAPPED_TYPE_KEYS_REMAPPING_NAME_TYPE = JsSpace.Location.MAPPED_TYPE_KEYS_REMAPPING_NAME_TYPE_SUFFIX, TRAILING_TOKEN_STATEMENT_EXPRESSION, WITH_STATEMENT_BODY, JS_IMPORT_CLAUSE_NAME, - IMPORT_TYPE_ATTRIBUTES_TOKEN, + IMPORT_ATTRIBUTES_ELEMENTS = JsSpace.Location.IMPORT_ATTRIBUTES_ELEMENTS_SUFFIX, + IMPORT_TYPE_ATTRIBUTES_TOKEN = JsSpace.Location.IMPORT_TYPE_ATTRIBUTES_TOKEN_SUFFIX, + IMPORT_TYPE_ATTRIBUTES_ELEMENTS = JsSpace.Location.IMPORT_TYPE_ATTRIBUTES_ELEMENTS_SUFFIX, + FUNCTION_TYPE_PARAMETERS_SUFFIX = JsSpace.Location.FUNCTION_TYPE_PARAMETER_SUFFIX, + FUNCTION_DECLARATION_PARAMETERS_SUFFIX = JsSpace.Location.FUNCTION_DECLARATION_PARAMETERS_SUFFIX, + EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS_SUFFIX = JsSpace.Location.EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS_SUFFIX, + NAMED_IMPORTS_ELEMENTS = JsSpace.Location.NAMED_IMPORTS_ELEMENTS_SUFFIX, + NAMED_EXPORTS_ELEMENTS = JsSpace.Location.NAMED_EXPORTS_ELEMENTS_SUFFIX, + OBJECT_BINDING_DECLARATIONS_BINDINGS = JsSpace.Location.OBJECT_BINDING_DECLARATIONS_BINDINGS_SUFFIX, + TUPLE_ELEMENTS = JsSpace.Location.TUPLE_ELEMENTS_SUFFIX, + TYPE_QUERY_TYPE_ARGUMENTS = JsSpace.Location.TYPE_QUERY_TYPE_ARGUMENTS_SUFFIX, + } + + export namespace Location { + export function afterLocation(location: Location): JsSpace.Location { + return location as unknown as JsSpace.Location; + } } } export namespace JsContainer { export enum Location { EXPORT_EXPORTS, FUNCTION_TYPE_PARAMETERS, - JS_IMPORT_IMPORTS, OBJECT_BINDING_DECLARATIONS_BINDINGS, TUPLE_ELEMENTS, JSMETHOD_DECLARATION_PARAMETERS, - JSMETHOD_DECLARATION_THROWZ, + JSMETHOD_DECLARATION_THROWZ, // not used FUNCTION_DECLARATION_PARAMETERS, - TYPE_LITERAL_MEMBERS, INDEX_SIGNATURE_DECLARATION_PARAMETERS, ARRAY_BINDING_PATTERN_ELEMENTS, EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS, TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS, CONDITIONAL_TYPE_CONDITION, - IMPORT_TYPE_TYPE_ARGUMENTS, NAMED_EXPORTS_ELEMENTS, MAPPED_TYPE_VALUE_TYPE, TYPE_QUERY_TYPE_ARGUMENTS, IMPORT_ATTRIBUTES_ELEMENTS, NAMED_IMPORTS_ELEMENTS, + IMPORT_TYPE_TYPE_ARGUMENTS, IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES, IMPORT_TYPE_ATTRIBUTES_ELEMENTS, } + + export const LocationDetails = { + [Location.JSMETHOD_DECLARATION_PARAMETERS]: [JsSpace.Location.JSMETHOD_DECLARATION_PARAMETERS, JsRightPadded.Location.JSMETHOD_DECLARATION_PARAMETER], + [Location.FUNCTION_DECLARATION_PARAMETERS]: [JsSpace.Location.FUNCTION_DECLARATION_PARAMETERS, JsRightPadded.Location.FUNCTION_DECLARATION_PARAMETERS_SUFFIX], + [Location.FUNCTION_TYPE_PARAMETERS]: [JsSpace.Location.FUNCTION_TYPE_PARAMETERS, JsRightPadded.Location.FUNCTION_TYPE_PARAMETERS_SUFFIX], + [Location.CONDITIONAL_TYPE_CONDITION]: [JsSpace.Location.CONDITIONAL_TYPE_CONDITION, JsRightPadded.Location.CONDITIONAL_TYPE_CONDITION], + [Location.EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS]: [JsSpace.Location.EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS, JsRightPadded.Location.EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS_SUFFIX], + [Location.IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES]: [JsSpace.Location.IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES, JsRightPadded.Location.IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES], + [Location.IMPORT_TYPE_TYPE_ARGUMENTS]: [JsSpace.Location.IMPORT_TYPE_TYPE_ARGUMENTS, JsRightPadded.Location.IMPORT_TYPE_TYPE_ARGUMENTS], + [Location.NAMED_IMPORTS_ELEMENTS]: [JsSpace.Location.NAMED_IMPORTS_ELEMENTS_PREFIX, JsRightPadded.Location.NAMED_IMPORTS_ELEMENTS], + [Location.NAMED_EXPORTS_ELEMENTS]: [JsSpace.Location.NAMED_EXPORTS_ELEMENTS_PREFIX, JsRightPadded.Location.NAMED_EXPORTS_ELEMENTS], + [Location.IMPORT_ATTRIBUTES_ELEMENTS]: [JsSpace.Location.IMPORT_ATTRIBUTES_ELEMENTS_PREFIX, JsRightPadded.Location.IMPORT_ATTRIBUTES_ELEMENTS], + [Location.IMPORT_TYPE_ATTRIBUTES_ELEMENTS]: [JsSpace.Location.IMPORT_TYPE_ATTRIBUTES_ELEMENTS_PREFIX, JsRightPadded.Location.IMPORT_TYPE_ATTRIBUTES_ELEMENTS], + [Location.ARRAY_BINDING_PATTERN_ELEMENTS]: [JsSpace.Location.ARRAY_BINDING_PATTERN_ELEMENTS_PREFIX, JsRightPadded.Location.ARRAY_BINDING_PATTERN_ELEMENTS], + [Location.MAPPED_TYPE_VALUE_TYPE]: [JsSpace.Location.MAPPED_TYPE_VALUE_TYPE, JsRightPadded.Location.MAPPED_TYPE_VALUE_TYPE], + [Location.OBJECT_BINDING_DECLARATIONS_BINDINGS]: [JsSpace.Location.OBJECT_BINDING_DECLARATIONS_BINDINGS_PREFIX, JsRightPadded.Location.OBJECT_BINDING_DECLARATIONS_BINDINGS], + [Location.TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS]: [JsSpace.Location.TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS_PREFIX, JsRightPadded.Location.TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS], + [Location.TUPLE_ELEMENTS]: [JsSpace.Location.TUPLE_ELEMENTS_PREFIX, JsRightPadded.Location.TUPLE_ELEMENTS], + [Location.TYPE_QUERY_TYPE_ARGUMENTS]: [JsSpace.Location.TYPE_QUERY_TYPE_ARGUMENTS_PREFIX, JsRightPadded.Location.TYPE_QUERY_TYPE_ARGUMENTS], + [Location.INDEX_SIGNATURE_DECLARATION_PARAMETERS]: [JsSpace.Location.INDEX_SIGNATURE_DECLARATION_PARAMETERS_PREFIX, JsRightPadded.Location.INDEX_SIGNATURE_DECLARATION_PARAMETERS], + }; + + export namespace Location { + export function beforeLocation(location: Location): JsSpace.Location { + // @ts-ignore + const [before] = JsContainer.LocationDetails[location]; + return before as JsSpace.Location; + } + + export function elementLocation(location: Location): JsRightPadded.Location { + // @ts-ignore + const [, element] = JsContainer.LocationDetails[location]; + return element as JsRightPadded.Location; + } + } } diff --git a/openrewrite/test/javascript/parser/class.test.ts b/openrewrite/test/javascript/parser/class.test.ts index b47d6b25..2fd6fd3f 100644 --- a/openrewrite/test/javascript/parser/class.test.ts +++ b/openrewrite/test/javascript/parser/class.test.ts @@ -372,7 +372,7 @@ describe('class mapping', () => { return this._name; } - Setter + // Setter set name(value: string) { this._name = value; } diff --git a/openrewrite/test/javascript/testHarness.ts b/openrewrite/test/javascript/testHarness.ts index 2c994586..443f542f 100644 --- a/openrewrite/test/javascript/testHarness.ts +++ b/openrewrite/test/javascript/testHarness.ts @@ -11,14 +11,16 @@ import { PrinterFactory, PrintOutputCapture, RecipeRunException, - SourceFile + SourceFile, + Tree, + TreeVisitor } from '../../dist/src/core'; import * as J from "../../dist/src/java/tree"; import * as JS from "../../dist/src/javascript/tree"; import dedent from "dedent"; import {ReceiverContext, RemotePrinterFactory, RemotingContext, SenderContext} from "@openrewrite/rewrite-remote"; import net from "net"; -import {JavaScriptParser, JavaScriptVisitor} from "../../dist/src/javascript"; +import {JavaScriptParser, JavaScriptVisitor, JavaScriptPrinter} from "../../dist/src/javascript"; import {ChildProcessWithoutNullStreams, spawn} from "node:child_process"; import path from "node:path"; @@ -36,7 +38,10 @@ registerJavaCodecs(SenderContext, ReceiverContext, RemotingContext) let client: net.Socket; let remoting: RemotingContext; let javaTestEngine: ChildProcessWithoutNullStreams -function getRandomInt(min: number, max:number):number { +const ci = process.env.NODE_ENV === "ci" +console.log("NODE_ENV: " + process.env.NODE_ENV) + +function getRandomInt(min: number, max: number): number { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; @@ -44,20 +49,16 @@ function getRandomInt(min: number, max:number):number { const Socket = net.Socket; -const getNextPort = async (port: number): Promise => -{ - return new Promise((resolve, reject) => - { +const getNextPort = async (port: number): Promise => { + return new Promise((resolve, reject) => { const socket = new Socket(); - const timeout = () => - { + const timeout = () => { resolve(port); socket.destroy(); }; - const next = () => - { + const next = () => { socket.destroy(); resolve(getNextPort(++port)); }; @@ -67,8 +68,7 @@ const getNextPort = async (port: number): Promise => socket.on("connect", () => next()); - socket.on("error", (error: any) => - { + socket.on("error", (error: any) => { if (error.code !== "ECONNREFUSED") reject(error); else @@ -79,76 +79,83 @@ const getNextPort = async (port: number): Promise => }); }; - -export async function connect(): Promise { - return new Promise((resolve, reject) => { - const pathToJar = path.resolve(__dirname, '../../../rewrite-test-engine-remote/build/libs/rewrite-test-engine-remote-fat-jar.jar'); - console.log(pathToJar); - client = new net.Socket(); - client.connect(65432, 'localhost'); - - client.once('error', (err) => { - const randomPort = getRandomInt(50000, 60000); - getNextPort(randomPort).then(port => { - javaTestEngine = spawn('java', ['-jar', pathToJar, port.toString()]); - const errorfn = (data: string) => { - console.error(`stderr: ${data}`); - reject(data); - }; - const startfn = (data : string) => { - console.log(`stdout: ${data}`); - javaTestEngine.stderr.off("data", errorfn); - client = new net.Socket(); - client.connect(port, 'localhost'); - - client.once('error', (err) => reject(err)); - client.once('connect', () => { - remoting = new RemotingContext(); - remoting.connect(client); - PrinterFactory.current = new RemotePrinterFactory(remoting.client!); - resolve(remoting); - }); - client.setTimeout(10000, () => { - client.destroy(); - reject(new Error('Connection timed out')); - }); - } - - javaTestEngine.stdout.once('data', startfn); - javaTestEngine.stderr.on('data', errorfn); +export async function connect(): Promise { + if (ci) { + return new Promise((resolve, reject) => { + const pathToJar = path.resolve(__dirname, '../../../rewrite-test-engine-remote/build/libs/rewrite-test-engine-remote-fat-jar.jar'); + console.log(pathToJar); + client = new net.Socket(); + client.connect(65432, 'localhost'); + + client.once('error', (err) => { + const randomPort = getRandomInt(50000, 60000); + getNextPort(randomPort).then(port => { + javaTestEngine = spawn('java', ['-jar', pathToJar, port.toString()]); + const errorfn = (data: string) => { + console.error(`stderr: ${data}`); + reject(data); + }; + const startfn = (data: string) => { + console.log(`stdout: ${data}`); + javaTestEngine.stderr.off("data", errorfn); + client = new net.Socket(); + client.connect(port, 'localhost'); + + client.once('error', (err) => reject(err)); + client.once('connect', () => { + remoting = new RemotingContext(); + remoting.connect(client); + PrinterFactory.current = new RemotePrinterFactory(remoting.client!); + resolve(remoting); + }); + client.setTimeout(10000, () => { + client.destroy(); + reject(new Error('Connection timed out')); + }); + } + + javaTestEngine.stdout.once('data', startfn); + javaTestEngine.stderr.on('data', errorfn); + }); + }); + client.once('connect', () => { + remoting = new RemotingContext(); + remoting.connect(client); + PrinterFactory.current = new RemotePrinterFactory(remoting.client!); + resolve(remoting); }); - }); - client.once('connect', () => { - remoting = new RemotingContext(); - remoting.connect(client); - PrinterFactory.current = new RemotePrinterFactory(remoting.client!); - resolve(remoting); - }); - }); + }); + } else { + return undefined; + } } export async function disconnect(): Promise { - return new Promise((resolve, reject) => { - if (client) { - client.end(); - client.destroy(); - if (remoting) { - remoting.close(); - } + if (ci) { + return new Promise((resolve, reject) => { + if (client) { + client.end(); + client.destroy(); + if (remoting) { + remoting.close(); + } - if (javaTestEngine) { - javaTestEngine.once('close', (code: string) => { - resolve() - }); - javaTestEngine.kill("SIGINT"); + if (javaTestEngine) { + javaTestEngine.once('close', (code: string) => { + resolve() + }); + javaTestEngine.kill("SIGINT"); + } else { + resolve(); + } } else { resolve(); } - } else { - resolve(); - } - }); + }); + } else { + return Promise.resolve(); + } } export function rewriteRun(...sourceSpecs: SourceSpec[]) { @@ -166,14 +173,14 @@ function sourceFile(before: string, defaultPath: string, spec?: (sourceFile: JS. const ctx = new InMemoryExecutionContext(); before = options.normalizeIndent ?? true ? dedent(before) : before; const [sourceFile] = parser.parseInputs( - [new ParserInput( - defaultPath, + [new ParserInput( + defaultPath, + null, + true, + () => Buffer.from(before) + )], null, - true, - () => Buffer.from(before) - )], - null, - ctx) as Iterable; + ctx) as Iterable; if (isParseError(sourceFile)) { throw new Error(`Parsing failed for ${sourceFile.sourcePath}: ${sourceFile.markers.findFirst(ParseExceptionResult)!.message}`); } @@ -213,7 +220,19 @@ export function typeScript(before: string, spec?: (sourceFile: JS.CompilationUni } function print(parsed: SourceFile) { - remoting.reset(); - remoting.client?.reset(); + if (ci) { + remoting.reset(); + remoting.client?.reset(); + } else { + PrinterFactory.current = new LocalPrintFactory(); + } return parsed.print(new Cursor(null, Cursor.ROOT_VALUE), new PrintOutputCapture(0)); } + +class LocalPrintFactory extends PrinterFactory { + createPrinter

(cursor: Cursor): TreeVisitor> { + const printer = new JavaScriptPrinter

(); + printer.cursor = cursor; + return printer; + } +} From 18ffb1f2b018161d6aac124a1adf60c696f9251b Mon Sep 17 00:00:00 2001 From: Andrii Rodionov Date: Tue, 18 Feb 2025 16:48:25 +0100 Subject: [PATCH 2/3] Implemented TypeScript printer There are two printer implementations: - JavaScriptPrinter Java class - JavaScriptPrinter TypeScript class The TypeScript printer set as default for tests. To run Java printer tests, set environment variable NODE_ENV=it --- openrewrite/src/java/tree/support_types.ts | 27 +- openrewrite/src/javascript/printer.ts | 593 ++++++++++++++++-- .../src/javascript/tree/support_types.ts | 87 +-- openrewrite/test/javascript/testHarness.ts | 13 +- .../javascript/JavaScriptVisitor.java | 2 +- .../internal/JavaScriptPrinter.java | 2 +- .../javascript/tree/JsLeftPadded.java | 2 +- .../openrewrite/javascript/tree/JsSpace.java | 1 + 8 files changed, 628 insertions(+), 99 deletions(-) diff --git a/openrewrite/src/java/tree/support_types.ts b/openrewrite/src/java/tree/support_types.ts index 39e1d33e..2fee8d8c 100644 --- a/openrewrite/src/java/tree/support_types.ts +++ b/openrewrite/src/java/tree/support_types.ts @@ -702,15 +702,12 @@ export namespace Space { export namespace JRightPadded { export enum Location { ANNOTATION_ARGUMENT = Space.Location.ANNOTATION_ARGUMENT_SUFFIX, - ARRAY_INDEX, + ARRAY_INDEX = Space.Location.ARRAY_INDEX_SUFFIX, BLOCK_STATEMENT = Space.Location.BLOCK_STATEMENT_SUFFIX, CASE = Space.Location.CASE_SUFFIX, CASE_CASE_LABELS = Space.Location.CASE_CASE_LABELS_SUFFIX, CASE_BODY, - CASE_EXPRESSION, CATCH_ALTERNATIVE, - CONTROL_PARENTHESES_TREE, - DIMENSION, ENUM_VALUE = Space.Location.ENUM_VALUE_SUFFIX, FOREACH_ITERABLE, FOREACH_VARIABLE, @@ -718,12 +715,12 @@ export namespace JRightPadded { FOR_CONDITION = Space.Location.FOR_CONDITION_SUFFIX, FOR_INIT = Space.Location.FOR_INIT_SUFFIX, FOR_UPDATE = Space.Location.FOR_UPDATE_SUFFIX, - IF_ELSE, - IF_THEN, + IF_ELSE = Space.Location.IF_ELSE_SUFFIX, + IF_THEN = Space.Location.IF_THEN_SUFFIX, IMPLEMENTS = Space.Location.IMPLEMENTS_SUFFIX, IMPORT, - INSTANCEOF, - LABEL, + INSTANCEOF = Space.Location.INSTANCEOF_SUFFIX, + LABEL = Space.Location.LABEL_SUFFIX, LAMBDA_PARAM = Space.Location.LAMBDA_PARAMETER, LANGUAGE_EXTENSION = Space.Location.LANGUAGE_EXTENSION, MEMBER_REFERENCE_CONTAINING, @@ -737,14 +734,11 @@ export namespace JRightPadded { NULLABLE, PACKAGE, PARENTHESES = Space.Location.PARENTHESES_SUFFIX, - PERMITS, RECORD_STATE_VECTOR = Space.Location.RECORD_STATE_VECTOR_SUFFIX, STATIC_INIT = Space.Location.STATIC_INIT_SUFFIX, - THROWS, - TRY_RESOURCE, TYPE_BOUND = Space.Location.TYPE_BOUND_SUFFIX, TYPE_PARAMETER = Space.Location.TYPE_PARAMETER_SUFFIX, - WHILE_BODY, + WHILE_BODY = Space.Location.WHILE_BODY_SUFFIX, } export namespace Location { @@ -760,7 +754,6 @@ export namespace JLeftPadded { ASSIGNMENT = Space.Location.ASSIGNMENT, ASSIGNMENT_OPERATION_OPERATOR = Space.Location.ASSIGNMENT_OPERATION_OPERATOR, BINARY_OPERATOR = Space.Location.BINARY_OPERATOR, - CLASS_KIND, EXTENDS = Space.Location.EXTENDS, FIELD_ACCESS_NAME = Space.Location.FIELD_ACCESS_NAME, IMPORT_ALIAS_PREFIX, @@ -768,12 +761,12 @@ export namespace JLeftPadded { MEMBER_REFERENCE_NAME, METHOD_DECLARATION_DEFAULT_VALUE, STATIC_IMPORT, - TERNARY_TRUE, - TERNARY_FALSE, - TRY_FINALLY, + TERNARY_TRUE = Space.Location.TERNARY_TRUE, + TERNARY_FALSE = Space.Location.TERNARY_FALSE, + TRY_FINALLY = Space.Location.TRY_FINALLY, UNARY_OPERATOR = Space.Location.UNARY_OPERATOR, VARIABLE_INITIALIZER = Space.Location.VARIABLE_INITIALIZER, - WHILE_CONDITION, + WHILE_CONDITION = Space.Location.WHILE_CONDITION, WILDCARD_BOUND, } diff --git a/openrewrite/src/javascript/printer.ts b/openrewrite/src/javascript/printer.ts index 7d5600bf..6f28bca4 100644 --- a/openrewrite/src/javascript/printer.ts +++ b/openrewrite/src/javascript/printer.ts @@ -1,39 +1,31 @@ -import * as ts from 'typescript'; import * as J from '../java'; import { - FieldAccess, - JavaType, JContainer, JLeftPadded, JRightPadded, - Lambda, Literal, + Literal, Semicolon, Space, - TrailingComma, - TypedTree + TrailingComma } from '../java'; import * as JS from '.'; import { Cursor, - ExecutionContext, Marker, Markers, - ParseError, - ParseExceptionResult, - Parser, - ParserInput, PrintOutputCapture, - randomId, - SourceFile, Tree + PrintOutputCapture, + Tree } from "../core"; -import {JavaScriptVisitor, JsContainer, JsLeftPadded, JsRightPadded, JsSpace} from "."; +import {JavaScriptVisitor, JsContainer, JsLeftPadded, JsRightPadded, JsSpace, NamespaceDeclaration} from "."; export class JavaScriptPrinter

extends JavaScriptVisitor> { JAVA_SCRIPT_MARKER_WRAPPER: (out: string) => string = (out) => `/*~~${out}${out.length === 0 ? "" : "~~"}>*/`; - // constructor(cursor: Cursor) { - // super(cursor) - // } + constructor(cursor: Cursor) { + super(); + this.cursor = cursor; + } visit(tree: Tree | null, p: PrintOutputCapture

): J.J | null { return super.visit(tree, p); @@ -52,13 +44,360 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J | null { // this.beforeSyntax(cu, Space.Location.COMPILATION_UNIT_PREFIX, p); // - // //this.visitRightPadded(cu.padding.getStatements(), JRightPadded.Location.LANGUAGE_EXTENSION, "", p); + // //this.visitJRightPadded(cu.padding.getStatements(), JRightPadded.Location.LANGUAGE_EXTENSION, "", p); // // this.visitSpace(cu.eof, Space.Location.COMPILATION_UNIT_EOF, p); // this.afterSyntax(cu, p); // return cu; // } + visitAlias(alias: JS.Alias, p: PrintOutputCapture

): JS.Alias { + this.beforeSyntax(alias, JsSpace.Location.ALIAS_PREFIX, p); + this.visitJsRightPadded(alias.padding.propertyName, JsRightPadded.Location.ALIAS_PROPERTY_NAME, p); + p.append("as"); + this.visit(alias.alias, p); + this.afterSyntax(alias, p); + return alias; + } + + visitAwait(awaitExpr: JS.Await, p: PrintOutputCapture

): JS.Await { + this.beforeSyntax(awaitExpr, JsSpace.Location.AWAIT_PREFIX, p); + p.append("await"); + this.visit(awaitExpr.expression, p); + this.afterSyntax(awaitExpr, p); + return awaitExpr; + } + + visitBindingElement(binding: JS.BindingElement, p: PrintOutputCapture

): JS.BindingElement { + this.beforeSyntax(binding, JsSpace.Location.BINDING_ELEMENT_PREFIX, p); + if (binding.propertyName) { + this.visitJsRightPadded(binding.padding.propertyName, JsRightPadded.Location.BINDING_ELEMENT_PROPERTY_NAME, p); + p.append(":"); + } + this.visit(binding.name, p); + this.visitJsLeftPaddedLocal("=", binding.padding.initializer, JsLeftPadded.Location.BINDING_ELEMENT_INITIALIZER, p); + this.afterSyntax(binding, p); + return binding; + } + + visitDelete(del: JS.Delete, p: PrintOutputCapture

): JS.Delete { + this.beforeSyntax(del, JsSpace.Location.DELETE_PREFIX, p); + p.append("delete"); + this.visit(del.expression, p); + this.afterSyntax(del, p); + return del; + } + + visitTrailingTokenStatement(statement: JS.TrailingTokenStatement, p: PrintOutputCapture

): JS.TrailingTokenStatement { + this.beforeSyntax(statement, JsSpace.Location.TRAILING_TOKEN_STATEMENT_PREFIX, p); + this.visitJsRightPadded(statement.padding.expression, JsRightPadded.Location.TRAILING_TOKEN_STATEMENT_EXPRESSION, p); + this.afterSyntax(statement, p); + return statement; + } + + visitInferType(inferType: JS.InferType, p: PrintOutputCapture

): JS.InferType { + this.beforeSyntax(inferType, JsSpace.Location.INFER_TYPE_PREFIX, p); + this.visitJsLeftPaddedLocal("infer", inferType.padding.typeParameter, JsLeftPadded.Location.INFER_TYPE_TYPE_PARAMETER, p); + this.afterSyntax(inferType, p); + return inferType; + } + + visitJsImport(jsImport: JS.JsImport, p: PrintOutputCapture

): JS.JsImport { + this.beforeSyntax(jsImport, JsSpace.Location.JS_IMPORT_PREFIX, p); + jsImport.modifiers.forEach(m => this.visitModifier(m, p)); + p.append("import"); + this.visit(jsImport.importClause, p); + + this.visitJsLeftPaddedLocal(jsImport.importClause ? "from" : "", jsImport.padding.moduleSpecifier, JsLeftPadded.Location.JS_IMPORT_MODULE_SPECIFIER, p); + + this.visit(jsImport.attributes, p); + + this.afterSyntax(jsImport, p); + return jsImport; + } + + visitJsImportClause(jsImportClause: JS.JsImportClause, p: PrintOutputCapture

): JS.JsImportClause { + this.beforeSyntax(jsImportClause, JsSpace.Location.JS_IMPORT_CLAUSE_PREFIX, p); + + if (jsImportClause.typeOnly) { + p.append("type"); + } + + const name = jsImportClause.padding.name; + this.visitJsRightPadded(name, JsRightPadded.Location.JS_IMPORT_CLAUSE_NAME, p); + + if (name && jsImportClause.namedBindings) { + p.append(","); + } + + this.visit(jsImportClause.namedBindings, p); + + this.afterSyntax(jsImportClause, p); + + return jsImportClause; + } + + visitTypeTreeExpression(typeTreeExpression: JS.TypeTreeExpression, p: PrintOutputCapture

): JS.TypeTreeExpression { + this.beforeSyntax(typeTreeExpression, JsSpace.Location.TYPE_TREE_EXPRESSION_PREFIX, p); + this.visit(typeTreeExpression.expression, p); + this.afterSyntax(typeTreeExpression, p); + return typeTreeExpression; + } + + visitNamespaceDeclaration(namespaceDeclaration: JS.NamespaceDeclaration, p: PrintOutputCapture

): JS.NamespaceDeclaration { + this.beforeSyntax(namespaceDeclaration, JsSpace.Location.NAMESPACE_DECLARATION_PREFIX, p); + namespaceDeclaration.modifiers.forEach(it => this.visitModifier(it, p)); + this.visitSpace(namespaceDeclaration.padding.keywordType.before, JsSpace.Location.NAMESPACE_DECLARATION_KEYWORD_TYPE_PREFIX, p); + + switch (namespaceDeclaration.keywordType) { + case NamespaceDeclaration.KeywordType.Namespace: + p.append("namespace"); + break; + case NamespaceDeclaration.KeywordType.Module: + p.append("module"); + break; + default: + break; + } + + this.visitJsRightPadded(namespaceDeclaration.padding.name, JsRightPadded.Location.NAMESPACE_DECLARATION_NAME, p); + + if (namespaceDeclaration.body) { + this.visit(namespaceDeclaration.body, p); + } + + this.afterSyntax(namespaceDeclaration, p); + return namespaceDeclaration; + } + + visitSatisfiesExpression(satisfiesExpression: JS.SatisfiesExpression, p: PrintOutputCapture

): JS.SatisfiesExpression { + this.beforeSyntax(satisfiesExpression, JsSpace.Location.SATISFIES_EXPRESSION_PREFIX, p); + this.visit(satisfiesExpression.expression, p); + this.visitJsLeftPaddedLocal("satisfies", satisfiesExpression.padding.satisfiesType, JsLeftPadded.Location.SATISFIES_EXPRESSION_SATISFIES_TYPE, p); + this.afterSyntax(satisfiesExpression, p); + return satisfiesExpression; + } + + visitVoid(aVoid: JS.Void, p: PrintOutputCapture

): JS.Void { + this.beforeSyntax(aVoid, JsSpace.Location.VOID_PREFIX, p); + p.append("void"); + this.visit(aVoid.expression, p); + this.afterSyntax(aVoid, p); + return aVoid; + } + + visitJsYield(yield_: JS.Yield, p: PrintOutputCapture

): JS.Yield { + this.beforeSyntax(yield_, JsSpace.Location.YIELD_PREFIX, p); + + p.append("yield"); + + if (yield_.delegated) { + this.visitJsLeftPaddedLocal("*", yield_.padding.delegated, JsLeftPadded.Location.YIELD_DELEGATED, p); + } + + this.visit(yield_.expression, p); + + this.afterSyntax(yield_, p); + return yield_; + } + + visitTry(try_: J.Try, p: PrintOutputCapture

): J.Try { + this.beforeSyntax(try_, Space.Location.TRY_PREFIX, p); + p.append("try"); + this.visit(try_.body, p); + this.visitNodes(try_.catches, p); + this.visitJLeftPaddedLocal("finally", try_.padding.finally, JLeftPadded.Location.TRY_FINALLY, p); + this.afterSyntax(try_, p); + return try_; + } + + visitCatch(catch_: J.Try.Catch, p: PrintOutputCapture

): J.Try.Catch { + this.beforeSyntax(catch_, Space.Location.CATCH_PREFIX, p); + p.append("catch"); + if (catch_.parameter.tree.variables.length > 0) { + this.visit(catch_.parameter, p); + } + this.visit(catch_.body, p); + this.afterSyntax(catch_, p); + return catch_; + } + + visitJSTry(jsTry: JS.JSTry, p: PrintOutputCapture

): JS.JSTry { + this.beforeSyntax(jsTry, JsSpace.Location.JSTRY_PREFIX, p); + p.append("try"); + this.visit(jsTry.body, p); + this.visit(jsTry.catches, p); + this.visitJsLeftPaddedLocal("finally", jsTry.padding.finallie, JsLeftPadded.Location.JSTRY_FINALLIE, p); + this.afterSyntax(jsTry, p); + return jsTry; + } + + visitJSTryJSCatch(jsCatch: JS.JSTry.JSCatch, p: PrintOutputCapture

): JS.JSTry.JSCatch { + this.beforeSyntax(jsCatch, JsSpace.Location.JSTRY_JSCATCH_PREFIX, p); + p.append("catch"); + this.visit(jsCatch.parameter, p); + this.visit(jsCatch.body, p); + this.afterSyntax(jsCatch, p); + return jsCatch; + } + + visitJSVariableDeclarations(multiVariable: JS.JSVariableDeclarations, p: PrintOutputCapture

): JS.JSVariableDeclarations { + this.beforeSyntax(multiVariable, JsSpace.Location.JSVARIABLE_DECLARATIONS_PREFIX, p); + this.visitNodes(multiVariable.leadingAnnotations, p); + multiVariable.modifiers.forEach(it => this.visitModifier(it, p)); + + const variables = multiVariable.padding.variables; + for (let i = 0; i < variables.length; i++) { + const variable = variables[i]; + this.beforeSyntax(variable.element, JsSpace.Location.JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_PREFIX, p); + if (multiVariable.varargs) { + p.append("..."); + } + + this.visit(variable.element.name, p); + + this.visitSpace(variable.after, JsSpace.Location.JSVARIABLE_DECLARATIONS_VARIABLES_SUFFIX, p); + if (multiVariable.typeExpression) { + this.visit(multiVariable.typeExpression, p); + } + + if (variable.element.initializer) { + this.visitJsLeftPaddedLocal("=", variable.element.padding.initializer, JsLeftPadded.Location.JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_INITIALIZER, p); + } + + this.afterSyntax(variable.element, p); + if (i < variables.length - 1) { + p.append(","); + } else if (variable.markers.findFirst(Semicolon) !== undefined) { + p.append(";"); + } + } + + this.afterSyntax(multiVariable, p); + return multiVariable; + } + + visitJSVariableDeclarationsJSNamedVariable(variable: JS.JSVariableDeclarations.JSNamedVariable, p: PrintOutputCapture

): JS.JSVariableDeclarations.JSNamedVariable { + this.beforeSyntax(variable, JsSpace.Location.JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_PREFIX, p); + this.visit(variable.name, p); + const initializer = variable.padding.initializer; + this.visitJsLeftPaddedLocal("=", initializer, JsLeftPadded.Location.JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_INITIALIZER, p); + this.afterSyntax(variable, p); + return variable; + } + + visitArrayDimension(arrayDimension: J.ArrayDimension, p: PrintOutputCapture

): J.ArrayDimension { + this.beforeSyntax(arrayDimension, Space.Location.DIMENSION_PREFIX, p); + p.append("["); + this.visitJRightPaddedLocalSingle(arrayDimension.padding.index, JRightPadded.Location.ARRAY_INDEX, "]", p); + this.afterSyntax(arrayDimension, p); + return arrayDimension; + } + + visitArrayType(arrayType: J.ArrayType, p: PrintOutputCapture

): J.ArrayType { + this.beforeSyntax(arrayType, Space.Location.ARRAY_TYPE_PREFIX, p); + let type: J.TypeTree = arrayType; + + while (type instanceof J.ArrayType) { + type = (type as J.ArrayType).elementType; + } + + this.visit(type, p); + this.visitNodes(arrayType.annotations, p); + + if (arrayType.dimension) { + this.visitSpace(arrayType.dimension.before, Space.Location.DIMENSION_PREFIX, p); + p.append("["); + this.visitSpace(arrayType.dimension.element, Space.Location.DIMENSION, p); + p.append("]"); + + if (arrayType.elementType instanceof J.ArrayType) { + this.printDimensions(arrayType.elementType as J.ArrayType, p); + } + } + + this.afterSyntax(arrayType, p); + return arrayType; + } + + private printDimensions(arrayType: J.ArrayType, p: PrintOutputCapture

) { + this.beforeSyntax(arrayType, Space.Location.ARRAY_TYPE_PREFIX, p); + this.visitNodes(arrayType.annotations, p); + this.visitSpace(arrayType.dimension?.before ?? Space.EMPTY, Space.Location.DIMENSION_PREFIX, p); + + p.append("["); + this.visitSpace(arrayType.dimension?.element ?? Space.EMPTY, Space.Location.DIMENSION, p); + p.append("]"); + + if (arrayType.elementType instanceof J.ArrayType) { + this.printDimensions(arrayType.elementType as J.ArrayType, p); + } + + this.afterSyntax(arrayType, p); + } + + visitTernary(ternary: J.Ternary, p: PrintOutputCapture

): J.Ternary { + this.beforeSyntax(ternary, Space.Location.TERNARY_PREFIX, p); + this.visit(ternary.condition, p); + this.visitJLeftPaddedLocal("?", ternary.padding.truePart, JLeftPadded.Location.TERNARY_TRUE, p); + this.visitJLeftPaddedLocal(":", ternary.padding.falsePart, JLeftPadded.Location.TERNARY_FALSE, p); + this.afterSyntax(ternary, p); + return ternary; + } + + visitThrow(thrown: J.Throw, p: PrintOutputCapture

): J.Throw { + this.beforeSyntax(thrown, Space.Location.THROW_PREFIX, p); + p.append("throw"); + this.visit(thrown.exception, p); + this.afterSyntax(thrown, p); + return thrown; + } + + visitIf(iff: J.If, p: PrintOutputCapture

): J.If { + this.beforeSyntax(iff, Space.Location.IF_PREFIX, p); + p.append("if"); + this.visit(iff.ifCondition, p); + this.visitStatementLocal(iff.padding.thenPart, JRightPadded.Location.IF_THEN, p); + this.visit(iff.elsePart, p); + this.afterSyntax(iff, p); + return iff; + } + + visitElse(else_: J.If.Else, p: PrintOutputCapture

): J.If.Else { + this.beforeSyntax(else_, Space.Location.ELSE_PREFIX, p); + p.append("else"); + this.visitStatementLocal(else_.padding.body, JRightPadded.Location.IF_ELSE, p); + this.afterSyntax(else_, p); + return else_; + } + + visitDoWhileLoop(doWhileLoop: J.DoWhileLoop, p: PrintOutputCapture

): J.DoWhileLoop { + this.beforeSyntax(doWhileLoop, Space.Location.DO_WHILE_PREFIX, p); + p.append("do"); + this.visitStatementLocal(doWhileLoop.padding.body, JRightPadded.Location.WHILE_BODY, p); + this.visitJLeftPaddedLocal("while", doWhileLoop.padding.whileCondition, JLeftPadded.Location.WHILE_CONDITION, p); + this.afterSyntax(doWhileLoop, p); + return doWhileLoop; + } + + visitWhileLoop(whileLoop: J.WhileLoop, p: PrintOutputCapture

): J.WhileLoop { + this.beforeSyntax(whileLoop, Space.Location.WHILE_PREFIX, p); + p.append("while"); + this.visit(whileLoop.condition, p); + this.visitStatementLocal(whileLoop.padding.body, JRightPadded.Location.WHILE_BODY, p); + this.afterSyntax(whileLoop, p); + return whileLoop; + } + + visitInstanceOf(instanceOf: J.InstanceOf, p: PrintOutputCapture

): J.InstanceOf { + this.beforeSyntax(instanceOf, Space.Location.INSTANCEOF_PREFIX, p); + this.visitJRightPaddedLocalSingle(instanceOf.padding.expression, JRightPadded.Location.INSTANCEOF, "instanceof", p); + this.visit(instanceOf.clazz, p); + this.visit(instanceOf.pattern, p); + this.afterSyntax(instanceOf, p); + return instanceOf; + } + visitLiteral(literal: Literal, p: PrintOutputCapture

): J.J { this.beforeSyntax(literal, Space.Location.LITERAL_PREFIX, p); @@ -441,7 +780,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor extends JavaScriptVisitor): JS.JsImportSpecifier { + this.beforeSyntax(jis, JsSpace.Location.JS_IMPORT_SPECIFIER_PREFIX, p); + + if (jis.importType) { + this.visitJsLeftPaddedLocal("type", jis.padding.importType, JsLeftPadded.Location.JS_IMPORT_SPECIFIER_IMPORT_TYPE, p); + } + + this.visit(jis.specifier, p); + + this.afterSyntax(jis, p); + return jis; + } + + visitExportDeclaration(ed: JS.ExportDeclaration, p: PrintOutputCapture

): JS.ExportDeclaration { + this.beforeSyntax(ed, JsSpace.Location.EXPORT_DECLARATION_PREFIX, p); + p.append("export"); + ed.modifiers.forEach(it => this.visitModifier(it, p)); + + if (ed.typeOnly) { + this.visitJsLeftPaddedLocal("type", ed.padding.typeOnly, JsLeftPadded.Location.EXPORT_DECLARATION_TYPE_ONLY, p); + } + + this.visit(ed.exportClause, p); + this.visitJsLeftPaddedLocal("from", ed.padding.moduleSpecifier, JsLeftPadded.Location.EXPORT_DECLARATION_MODULE_SPECIFIER, p); + this.visit(ed.attributes, p); + + this.afterSyntax(ed, p); + return ed; + } + + visitExportAssignment(es: JS.ExportAssignment, p: PrintOutputCapture

): JS.ExportAssignment { + this.beforeSyntax(es, JsSpace.Location.EXPORT_ASSIGNMENT_PREFIX, p); + p.append("export"); + es.modifiers.forEach(it => this.visitModifier(it, p)); + + if (es.exportEquals) { + this.visitJsLeftPaddedLocal("=", es.padding.exportEquals, JsLeftPadded.Location.EXPORT_ASSIGNMENT_EXPORT_EQUALS, p); + } + + this.visit(es.expression, p); + this.afterSyntax(es, p); + return es; + } + + visitIndexedAccessType(iat: JS.IndexedAccessType, p: PrintOutputCapture

): JS.IndexedAccessType { + this.beforeSyntax(iat, JsSpace.Location.INDEXED_ACCESS_TYPE_PREFIX, p); + + this.visit(iat.objectType, p); + // expect that this element is printed accordingly + // [index] + this.visit(iat.indexType, p); + + this.afterSyntax(iat, p); + return iat; + } + + visitIndexedAccessTypeIndexType(iatit: JS.IndexedAccessType.IndexType, p: PrintOutputCapture

): JS.IndexedAccessType.IndexType { + this.beforeSyntax(iatit, JsSpace.Location.INDEXED_ACCESS_TYPE_INDEX_TYPE_PREFIX, p); + + p.append("["); + this.visitJsRightPadded(iatit.padding.element, JsRightPadded.Location.INDEXED_ACCESS_TYPE_INDEX_TYPE_ELEMENT, p); + p.append("]"); + + this.afterSyntax(iatit, p); + return iatit; + } + + visitWithStatement(withStatement: JS.WithStatement, p: PrintOutputCapture

): JS.WithStatement { + this.beforeSyntax(withStatement, JsSpace.Location.WITH_STATEMENT_PREFIX, p); + p.append("with"); + this.visit(withStatement.expression, p); + this.visitJsRightPadded(withStatement.padding.body, JsRightPadded.Location.WITH_STATEMENT_BODY, p); + this.afterSyntax(withStatement, p); + return withStatement; + } + + visitExportSpecifier(es: JS.ExportSpecifier, p: PrintOutputCapture

): JS.ExportSpecifier { + this.beforeSyntax(es, JsSpace.Location.EXPORT_SPECIFIER_PREFIX, p); + if (es.typeOnly) { + this.visitJsLeftPaddedLocal("type", es.padding.typeOnly, JsLeftPadded.Location.EXPORT_SPECIFIER_TYPE_ONLY, p); + } + + this.visit(es.specifier, p); + + this.afterSyntax(es, p); + return es; + } + + + visitNamedExports(ne: JS.NamedExports, p: PrintOutputCapture

): J.J { this.beforeSyntax(ne, JsSpace.Location.NAMED_EXPORTS_PREFIX, p); this.visitJsContainerLocal("{", ne.padding.elements, JsContainer.Location.NAMED_EXPORTS_ELEMENTS, ",", "}", p); @@ -707,6 +1136,22 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TemplateExpression { + this.beforeSyntax(templateExpression, JsSpace.Location.TEMPLATE_EXPRESSION_PREFIX, p); + this.visit(templateExpression.head, p); + this.visitJsRightPaddedLocal(templateExpression.padding.templateSpans, JsRightPadded.Location.TEMPLATE_EXPRESSION_TEMPLATE_SPANS, "", p); + this.afterSyntax(templateExpression, p); + return templateExpression; + } + + visitTemplateExpressionTemplateSpan(value: JS.TemplateExpression.TemplateSpan, p: PrintOutputCapture

): JS.TemplateExpression.TemplateSpan { + this.beforeSyntax(value, JsSpace.Location.TEMPLATE_EXPRESSION_TEMPLATE_SPAN_PREFIX, p); + this.visit(value.expression, p); + this.visit(value.tail, p); + this.afterSyntax(value, p); + return value; + } + visitTuple(tuple: JS.Tuple, p: PrintOutputCapture

): J.J { this.beforeSyntax(tuple, JsSpace.Location.TUPLE_PREFIX, p); this.visitJsContainerLocal("[", tuple.padding.elements, JsContainer.Location.TUPLE_ELEMENTS, ",", "]", p); @@ -723,6 +1168,48 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TypeOf { + this.beforeSyntax(typeOf, JsSpace.Location.TYPE_OF_PREFIX, p); + p.append("typeof"); + this.visit(typeOf.expression, p); + this.afterSyntax(typeOf, p); + return typeOf; + } + + visitTypeOperator(typeOperator: JS.TypeOperator, p: PrintOutputCapture

): JS.TypeOperator { + this.beforeSyntax(typeOperator, JsSpace.Location.TYPE_OPERATOR_PREFIX, p); + + let keyword = ""; + if (typeOperator.operator === JS.TypeOperator.Type.ReadOnly) { + keyword = "readonly"; + } else if (typeOperator.operator === JS.TypeOperator.Type.KeyOf) { + keyword = "keyof"; + } else if (typeOperator.operator === JS.TypeOperator.Type.Unique) { + keyword = "unique"; + } + + p.append(keyword); + + this.visitJsLeftPadded(typeOperator.padding.expression, JsLeftPadded.Location.TYPE_OPERATOR_EXPRESSION, p); + + this.afterSyntax(typeOperator, p); + return typeOperator; + } + + visitTypePredicate(typePredicate: JS.TypePredicate, p: PrintOutputCapture

): JS.TypePredicate { + this.beforeSyntax(typePredicate, JsSpace.Location.TYPE_PREDICATE_PREFIX, p); + + if (typePredicate.asserts) { + this.visitJsLeftPaddedLocal("asserts", typePredicate.padding.asserts, JsLeftPadded.Location.TYPE_PREDICATE_ASSERTS, p); + } + + this.visit(typePredicate.parameterName, p); + this.visitJsLeftPaddedLocal("is", typePredicate.padding.expression, JsLeftPadded.Location.TYPE_PREDICATE_EXPRESSION, p); + + this.afterSyntax(typePredicate, p); + return typePredicate; + } + visitIndexSignatureDeclaration(isd: JS.IndexSignatureDeclaration, p: PrintOutputCapture

): J.J { this.beforeSyntax(isd, JsSpace.Location.INDEX_SIGNATURE_DECLARATION_PREFIX, p); @@ -756,7 +1243,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { this.beforeSyntax(newClass, Space.Location.NEW_CLASS_PREFIX, p); - this.visitJRightPaddedLocal(newClass.padding.enclosing ? [newClass.padding.enclosing] : [], JRightPadded.Location.NEW_CLASS_ENCLOSING, ".", p); + this.visitJRightPaddedLocalSingle(newClass.padding.enclosing, JRightPadded.Location.NEW_CLASS_ENCLOSING, ".", p); this.visitSpace(newClass.new, Space.Location.NEW_PREFIX, p); if (newClass.clazz) { @@ -801,6 +1288,22 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Label { + this.beforeSyntax(label, Space.Location.LABEL_PREFIX, p); + this.visitJRightPaddedLocalSingle(label.padding.label, JRightPadded.Location.LABEL, ":", p); + this.visit(label.statement, p); + this.afterSyntax(label, p); + return label; + } + + visitContinue(continueStatement: J.Continue, p: PrintOutputCapture

): J.Continue { + this.beforeSyntax(continueStatement, Space.Location.CONTINUE_PREFIX, p); + p.append("continue"); + this.visit(continueStatement.label, p); + this.afterSyntax(continueStatement, p); + return continueStatement; + } + visitBreak(breakStatement: J.Break, p: PrintOutputCapture

): J.J { this.beforeSyntax(breakStatement, Space.Location.BREAK_PREFIX, p); p.append("break"); @@ -819,6 +1322,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TypeLiteral { this.beforeSyntax(tl, JsSpace.Location.TYPE_LITERAL_PREFIX, p); @@ -831,8 +1335,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor(parens: J.Parentheses, p: PrintOutputCapture

): J.J { this.beforeSyntax(parens, Space.Location.PARENTHESES_PREFIX, p); p.append('('); - this.visitJRightPaddedLocal(parens.padding.tree ? [parens.padding.tree] : [], JRightPadded.Location.PARENTHESES, "", p); - p.append(')'); + this.visitJRightPaddedLocalSingle(parens.padding.tree, JRightPadded.Location.PARENTHESES, ")", p); this.afterSyntax(parens, p); return parens; } @@ -1200,8 +1703,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor extends JavaScriptVisitor[], location: JRightPadded.Location, p: PrintOutputCapture

) { @@ -1348,6 +1846,20 @@ export class JavaScriptPrinter

extends JavaScriptVisitor | null, location: JRightPadded.Location, suffix: string, p: PrintOutputCapture

) { + if (node) { + this.visit(node.element, p); + + if (location) { + const loc = JRightPadded.Location.afterLocation(location); + this.visitSpace(node.after, loc, p); + } + this.visitMarkers(node.markers, p); + + p.append(suffix); + } + } + private visitJsRightPaddedLocal(nodes: JRightPadded[], location: JsRightPadded.Location, suffixBetween: string, p: PrintOutputCapture

) { for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; @@ -1366,6 +1878,20 @@ export class JavaScriptPrinter

extends JavaScriptVisitor | null, location: JsRightPadded.Location, suffix: string, p: PrintOutputCapture

) { + if (node) { + this.visit(node.element, p); + + if (location) { + const loc = JsRightPadded.Location.afterLocation(location); + this.visitSpace(node.after, loc, p); + } + this.visitMarkers(node.markers, p); + + p.append(suffix); + } + } + private visitJLeftPaddedLocal(prefix: string | null, leftPadded: JLeftPadded | JLeftPadded | null, location: JLeftPadded.Location, p: PrintOutputCapture

) { if (leftPadded) { const loc = JLeftPadded.Location.beforeLocation(location); @@ -1470,18 +1996,15 @@ export class JavaScriptPrinter

extends JavaScriptVisitor(controlParens: J.ControlParentheses, p: PrintOutputCapture

): J.J { this.beforeSyntax(controlParens, Space.Location.CONTROL_PARENTHESES_PREFIX, p); - if (this.getParentCursor(0)?.value() instanceof J.TypeCast) { + if (this.getParentCursor(1)?.value() instanceof J.TypeCast) { p.append('<'); - this.visitJRightPaddedLocal(controlParens.padding.tree ? [controlParens.padding.tree] : [], JRightPadded.Location.PARENTHESES, "", p); - p.append('>') + this.visitJRightPaddedLocalSingle(controlParens.padding.tree, JRightPadded.Location.PARENTHESES, ">", p); } else { p.append('('); - this.visitJRightPaddedLocal(controlParens.padding.tree ? [controlParens.padding.tree] : [], JRightPadded.Location.PARENTHESES, "", p); - p.append(')'); + this.visitJRightPaddedLocalSingle(controlParens.padding.tree, JRightPadded.Location.PARENTHESES, ")", p); } this.afterSyntax(controlParens, p); return controlParens; } - } diff --git a/openrewrite/src/javascript/tree/support_types.ts b/openrewrite/src/javascript/tree/support_types.ts index c77ab725..f9a480f4 100644 --- a/openrewrite/src/javascript/tree/support_types.ts +++ b/openrewrite/src/javascript/tree/support_types.ts @@ -183,6 +183,7 @@ export class StatementExpression extends JSMixin(Object) implements Expression, export namespace JsSpace { export enum Location { ALIAS_PREFIX, + ALIAS_PROPERTY_NAME_PREFIX, ARROW_FUNCTION_PREFIX, ARROW_FUNCTION_BODY_PREFIX, LAMBDA_ARROW_PREFIX, @@ -201,11 +202,14 @@ export namespace JsSpace { JS_BINARY_OPERATOR, JS_IMPORT_FROM, JS_IMPORT_PREFIX, + JS_IMPORT_MODULE_SPECIFIER_PREFIX, JS_IMPORT_IMPORT_TYPE_PREFIX, JS_IMPORT_SPECIFIER_PREFIX, JS_IMPORT_SPECIFIER_IMPORT_TYPE_PREFIX, OBJECT_BINDING_DECLARATIONS_BINDING_AFTER_VARARG, BINDING_ELEMENT_PREFIX, + BINDING_ELEMENT_PROPERTY_NAME_SUFFIX, + BINDING_INITIALIZER_PREFIX, OBJECT_BINDING_DECLARATIONS_PREFIX, OBJECT_BINDING_DECLARATIONS_INITIALIZER_PREFIX, OBJECT_BINDING_DECLARATIONS_BINDINGS_PREFIX, @@ -216,6 +220,7 @@ export namespace JsSpace { SCOPED_VARIABLE_DECLARATIONS_SCOPE_PREFIX, SCOPED_VARIABLE_DECLARATIONS_VARIABLE_SUFFIX, TEMPLATE_EXPRESSION_PREFIX, + TEMPLATE_EXPRESSION_TEMPLATE_SPANS_SUFFIX, TEMPLATE_EXPRESSION_VALUE_AFTER, TEMPLATE_EXPRESSION_VALUE_PREFIX, TUPLE_PREFIX, @@ -226,19 +231,26 @@ export namespace JsSpace { TYPE_DECLARATION_INITIALIZER_PREFIX, TYPE_OF_PREFIX, TYPE_OPERATOR_PREFIX, + TYPE_OPERATOR_EXPRESSION_PREFIX, UNARY_PREFIX, UNARY_OPERATOR, UNION_PREFIX, UNION_TYPES_SUFFIX, VOID_PREFIX, YIELD_PREFIX, + YIELD_DELEGATED_PREFIX, TYPE_INFO_PREFIX, JSVARIABLE_DECLARATIONS_PREFIX, JSVARIABLE_DECLARATIONS_VARARGS, JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_PREFIX, + JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_INITIALIZER_PREFIX, + JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_DIMENSIONS_AFTER_NAME_PREFIX, + JSVARIABLE_DECLARATIONS_VARIABLES_SUFFIX, NAMESPACE_DECLARATION_PREFIX, + NAMESPACE_DECLARATION_KEYWORD_TYPE_PREFIX, JSMETHOD_DECLARATION_PREFIX, JSMETHOD_DECLARATION_PARAMETERS, + JSMETHOD_DECLARATION_DEFAULT_VALUE_PREFIX, FUNCTION_DECLARATION_PREFIX, FUNCTION_DECLARATION_ASTERISK_TOKEN_PREFIX, FUNCTION_DECLARATION_NAME_PREFIX, @@ -279,9 +291,13 @@ export namespace JsSpace { CONDITIONAL_TYPE_CONDITION, CONDITIONAL_TYPE_CONDITION_SUFFIX, INFER_TYPE_PREFIX, + INFER_TYPE_TYPE_PARAMETER_PREFIX, TYPE_PREDICATE_PREFIX, + TYPE_PREDICATE_ASSERTS_PREFIX, + TYPE_PREDICATE_EXPRESSION_PREFIX, LITERAL_TYPE_PREFIX, SATISFIES_EXPRESSION_PREFIX, + SATISFIES_EXPRESSION_SATISFIES_TYPE_PREFIX, IMPORT_TYPE_PREFIX, IMPORT_TYPE_HAS_TYPEOF_SUFFIX, IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES, @@ -296,9 +312,12 @@ export namespace JsSpace { IMPORT_TYPE_ATTRIBUTES_ELEMENTS_SUFFIX, EXPORT_DECLARATION_PREFIX, EXPORT_DECLARATION_TYPE_ONLY_PREFIX, + EXPORT_DECLARATION_MODULE_SPECIFIER_PREFIX, EXPORT_SPECIFIER_PREFIX, + EXPORT_SPECIFIER_TYPE_ONLY_PREFIX, NAMED_EXPORTS_PREFIX, EXPORT_ASSIGNMENT_PREFIX, + EXPORT_ASSIGNMENT_EXPORT_EQUALS_PREFIX, INDEXED_ACCESS_TYPE_PREFIX, INDEXED_ACCESS_TYPE_INDEX_TYPE_PREFIX, INDEXED_ACCESS_TYPE_INDEX_TYPE_SUFFIX, @@ -319,9 +338,12 @@ export namespace JsSpace { MAPPED_TYPE_MAPPED_TYPE_PARAMETER_ITERATE_TYPE_PREFIX, TYPE_TREE_EXPRESSION_PREFIX, TRAILING_TOKEN_STATEMENT_PREFIX, + TRAILING_TOKEN_STATEMENT_EXPRESSION_SUFFIX, JSTRY_PREFIX, + JSTRY_FINALLIE_PREFIX, JSTRY_JSCATCH_PREFIX, WITH_STATEMENT_PREFIX, + WITH_STATEMENT_BODY_SUFFIX, IMPORT_ATTRIBUTE_PREFIX, IMPORT_ATTRIBUTE_VALUE_PREFIX, IMPORT_ATTRIBUTES_PREFIX, @@ -333,40 +355,36 @@ export namespace JsSpace { NAMED_EXPORTS_ELEMENTS_PREFIX, NAMED_EXPORTS_ELEMENTS_SUFFIX, JS_IMPORT_CLAUSE_PREFIX, + JS_IMPORT_CLAUSE_NAME_SUFFIX } } export namespace JsLeftPadded { export enum Location { EXPORT_INITIALIZER, - JS_IMPORT_INITIALIZER, - JS_IMPORT_IMPORT_TYPE, JS_BINARY_OPERATOR = JsSpace.Location.JS_BINARY_OPERATOR, - JS_OPERATOR_OPERATOR, OBJECT_BINDING_DECLARATIONS_INITIALIZER = JsSpace.Location.OBJECT_BINDING_DECLARATIONS_INITIALIZER_PREFIX, - OBJECT_BINDING_DECLARATIONS_BINDING_DIMENSIONS_AFTER_NAME, - OBJECT_BINDING_DECLARATIONS_BINDING_INITIALIZER, TYPE_DECLARATION_INITIALIZER = JsSpace.Location.TYPE_DECLARATION_INITIALIZER_PREFIX, TYPE_DECLARATION_NAME = JsSpace.Location.TYPE_DECLARATION_NAME_PREFIX, - TYPE_OPERATOR_EXPRESSION, + TYPE_OPERATOR_EXPRESSION = JsSpace.Location.TYPE_OPERATOR_EXPRESSION_PREFIX, UNARY_OPERATOR = JsSpace.Location.UNARY_OPERATOR, - JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_INITIALIZER, - JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_DIMENSIONS_AFTER_NAME, - JSMETHOD_DECLARATION_DEFAULT_VALUE, - NAMESPACE_DECLARATION_KEYWORD_TYPE, + JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_INITIALIZER = JsSpace.Location.JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_INITIALIZER_PREFIX, + JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_DIMENSIONS_AFTER_NAME = JsSpace.Location.JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_DIMENSIONS_AFTER_NAME_PREFIX, + JSMETHOD_DECLARATION_DEFAULT_VALUE = JsSpace.Location.JSMETHOD_DECLARATION_DEFAULT_VALUE_PREFIX, + NAMESPACE_DECLARATION_KEYWORD_TYPE = JsSpace.Location.NAMESPACE_DECLARATION_KEYWORD_TYPE_PREFIX, SCOPED_VARIABLE_DECLARATIONS_SCOPE = JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_SCOPE_PREFIX, - JS_IMPORT_SPECIFIER_IMPORT_TYPE, + JS_IMPORT_SPECIFIER_IMPORT_TYPE = JsSpace.Location.JS_IMPORT_SPECIFIER_IMPORT_TYPE_PREFIX, INDEX_SIGNATURE_DECLARATION_TYPE_EXPRESSION = JsSpace.Location.INDEX_SIGNATURE_DECLARATION_TYPE_EXPRESSION_PREFIX, JSFOR_OF_LOOP_AWAIT = JsSpace.Location.JSFOR_OF_LOOP_AWAIT_PREFIX, - BINDING_ELEMENT_INITIALIZER, - INFER_TYPE_TYPE_PARAMETER, - TYPE_PREDICATE_ASSERTS, - TYPE_PREDICATE_EXPRESSION, - SATISFIES_EXPRESSION_SATISFIES_TYPE, + BINDING_ELEMENT_INITIALIZER = JsSpace.Location.BINDING_INITIALIZER_PREFIX, + INFER_TYPE_TYPE_PARAMETER = JsSpace.Location.INFER_TYPE_TYPE_PARAMETER_PREFIX, + TYPE_PREDICATE_ASSERTS = JsSpace.Location.TYPE_PREDICATE_ASSERTS_PREFIX, + TYPE_PREDICATE_EXPRESSION = JsSpace.Location.TYPE_PREDICATE_EXPRESSION_PREFIX, + SATISFIES_EXPRESSION_SATISFIES_TYPE = JsSpace.Location.SATISFIES_EXPRESSION_SATISFIES_TYPE_PREFIX, IMPORT_TYPE_QUALIFIER = JsSpace.Location.IMPORT_TYPE_QUALIFIER_PREFIX, - EXPORT_DECLARATION_TYPE_ONLY, - EXPORT_SPECIFIER_TYPE_ONLY, - EXPORT_ASSIGNMENT_EXPORT_EQUALS, - EXPORT_DECLARATION_MODULE_SPECIFIER, + EXPORT_DECLARATION_TYPE_ONLY = JsSpace.Location.EXPORT_DECLARATION_TYPE_ONLY_PREFIX, + EXPORT_SPECIFIER_TYPE_ONLY = JsSpace.Location.EXPORT_SPECIFIER_TYPE_ONLY_PREFIX, + EXPORT_ASSIGNMENT_EXPORT_EQUALS = JsSpace.Location.EXPORT_ASSIGNMENT_EXPORT_EQUALS_PREFIX, + EXPORT_DECLARATION_MODULE_SPECIFIER = JsSpace.Location.EXPORT_DECLARATION_MODULE_SPECIFIER_PREFIX, FUNCTION_DECLARATION_ASTERISK_TOKEN = JsSpace.Location.FUNCTION_DECLARATION_ASTERISK_TOKEN_PREFIX, FUNCTION_DECLARATION_NAME = JsSpace.Location.FUNCTION_DECLARATION_NAME_PREFIX, JS_ASSIGNMENT_OPERATION_OPERATOR = JsSpace.Location.JS_ASSIGNMENT_OPERATION_OPERATOR_PREFIX, @@ -375,15 +393,13 @@ export namespace JsLeftPadded { MAPPED_TYPE_MAPPED_TYPE_PARAMETER_ITERATE_TYPE = JsSpace.Location.MAPPED_TYPE_MAPPED_TYPE_PARAMETER_ITERATE_TYPE_PREFIX, MAPPED_TYPE_HAS_READONLY = JsSpace.Location.MAPPED_TYPE_HAS_READONLY_PREFIX, MAPPED_TYPE_HAS_QUESTION_TOKEN = JsSpace.Location.MAPPED_TYPE_HAS_QUESTION_TOKEN_PREFIX, - LAMBDA_ARROW = JsSpace.Location.LAMBDA_ARROW_PREFIX, ARROW_FUNCTION_BODY = JsSpace.Location.ARROW_FUNCTION_BODY_PREFIX, - YIELD_DELEGATED, + YIELD_DELEGATED = JsSpace.Location.YIELD_DELEGATED_PREFIX, FUNCTION_TYPE_CONSTRUCTOR_TYPE = JsSpace.Location.FUNCTION_TYPE_CONSTRUCTOR_PREFIX, FUNCTION_TYPE_RETURN_TYPE = JsSpace.Location.FUNCTION_TYPE_RETURN_TYPE_PREFIX, - JSTRY_FINALLIE, + JSTRY_FINALLIE = JsSpace.Location.JSTRY_FINALLIE_PREFIX, IMPORT_ATTRIBUTE_VALUE = JsSpace.Location.IMPORT_ATTRIBUTE_VALUE_PREFIX, - JS_IMPORT_MODULE_SPECIFIER, - JS_IMPORT_IMPORT_CLAUSE, + JS_IMPORT_MODULE_SPECIFIER = JsSpace.Location.JS_IMPORT_MODULE_SPECIFIER_PREFIX, } export namespace Location { @@ -394,39 +410,36 @@ export namespace JsLeftPadded { } export namespace JsRightPadded { export enum Location { - ALIAS_PROPERTY_NAME, + ALIAS_PROPERTY_NAME = JsSpace.Location.ALIAS_PROPERTY_NAME_PREFIX, ARRAY_BINDING_PATTERN_ELEMENTS = JsSpace.Location.ARRAY_BINDING_PATTERN_ELEMENTS_SUFFIX, COMPILATION_UNIT_STATEMENTS, CONDITIONAL_TYPE_CONDITION = JsSpace.Location.CONDITIONAL_TYPE_CONDITION_SUFFIX, - JS_IMPORT_NAME, - BINDING_ELEMENT_PROPERTY_NAME, + BINDING_ELEMENT_PROPERTY_NAME = JsSpace.Location.BINDING_ELEMENT_PROPERTY_NAME_SUFFIX, PROPERTY_ASSIGNMENT_NAME = JsSpace.Location.PROPERTY_ASSIGNMENT_NAME_SUFFIX, SCOPED_VARIABLE_DECLARATIONS_VARIABLES = JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_VARIABLE_SUFFIX, UNION_TYPES = JsSpace.Location.UNION_TYPES_SUFFIX, - JSVARIABLE_DECLARATIONS_VARIABLES, - NAMESPACE_DECLARATION_NAME, + JSVARIABLE_DECLARATIONS_VARIABLES = JsSpace.Location.JSVARIABLE_DECLARATIONS_VARIABLES_SUFFIX, + NAMESPACE_DECLARATION_NAME = JsSpace.Location.NAMESPACE_DECLARATION_PREFIX, INTERSECTION_TYPES = JsSpace.Location.INTERSECTION_TYPES_SUFFIX, - TYPE_LITERAL_MEMBERS, INDEX_SIGNATURE_DECLARATION_PARAMETERS = JsSpace.Location.INDEX_SIGNATURE_DECLARATION_PARAMETERS_SUFFIX, JSFOR_IN_OF_LOOP_CONTROL_VARIABLE = JsSpace.Location.JSFOR_IN_OF_LOOP_CONTROL_VARIABLE_SUFFIX, JSFOR_IN_OF_LOOP_CONTROL_ITERABLE = JsSpace.Location.JSFOR_IN_OF_LOOP_CONTROL_ITERABLE_SUFFIX, JSFOR_OF_LOOP_BODY = JsSpace.Location.JSFOR_OF_LOOP_BODY_SUFFIX, JSFOR_IN_LOOP_BODY = JsSpace.Location.JSFOR_IN_LOOP_BODY_SUFFIX, JSMETHOD_DECLARATION_PARAMETER = JsSpace.Location.JSMETHOD_DECLARATION_PARAMETERS, - TEMPLATE_EXPRESSION_TEMPLATE_SPANS, + TEMPLATE_EXPRESSION_TEMPLATE_SPANS = JsSpace.Location.TEMPLATE_EXPRESSION_TEMPLATE_SPANS_SUFFIX, TAGGED_TEMPLATE_EXPRESSION_TAG = JsSpace.Location.TAGGED_TEMPLATE_EXPRESSION_TAG_SUFFIX, TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS = JsSpace.Location.TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS_SUFFIX, IMPORT_TYPE_HAS_TYPEOF = JsSpace.Location.IMPORT_TYPE_HAS_TYPEOF_SUFFIX, IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES = JsSpace.Location.IMPORT_TYPE_ARGUMENT_AND_ATTRIBUTES_SUFFIX, IMPORT_TYPE_TYPE_ARGUMENTS = JsSpace.Location.IMPORT_TYPE_TYPE_ARGUMENTS_SUFFIX, - INDEXED_ACCESS_TYPE_INDEX_TYPE, - INDEXED_ACCESS_TYPE_INDEX_TYPE_ELEMENT, + INDEXED_ACCESS_TYPE_INDEX_TYPE_ELEMENT = JsSpace.Location.INDEXED_ACCESS_TYPE_INDEX_TYPE_ELEMENT_SUFFIX, MAPPED_TYPE_VALUE_TYPE = JsSpace.Location.MAPPED_TYPE_VALUE_TYPE_SUFFIX, MAPPED_TYPE_KEYS_REMAPPING_TYPE_PARAMETER = JsSpace.Location.MAPPED_TYPE_KEYS_REMAPPING_TYPE_PARAMETER_SUFFIX, MAPPED_TYPE_KEYS_REMAPPING_NAME_TYPE = JsSpace.Location.MAPPED_TYPE_KEYS_REMAPPING_NAME_TYPE_SUFFIX, - TRAILING_TOKEN_STATEMENT_EXPRESSION, - WITH_STATEMENT_BODY, - JS_IMPORT_CLAUSE_NAME, + TRAILING_TOKEN_STATEMENT_EXPRESSION = JsSpace.Location.TRAILING_TOKEN_STATEMENT_EXPRESSION_SUFFIX, + WITH_STATEMENT_BODY = JsSpace.Location.WITH_STATEMENT_BODY_SUFFIX, + JS_IMPORT_CLAUSE_NAME = JsSpace.Location.JS_IMPORT_CLAUSE_NAME_SUFFIX, IMPORT_ATTRIBUTES_ELEMENTS = JsSpace.Location.IMPORT_ATTRIBUTES_ELEMENTS_SUFFIX, IMPORT_TYPE_ATTRIBUTES_TOKEN = JsSpace.Location.IMPORT_TYPE_ATTRIBUTES_TOKEN_SUFFIX, IMPORT_TYPE_ATTRIBUTES_ELEMENTS = JsSpace.Location.IMPORT_TYPE_ATTRIBUTES_ELEMENTS_SUFFIX, diff --git a/openrewrite/test/javascript/testHarness.ts b/openrewrite/test/javascript/testHarness.ts index 443f542f..6500d45c 100644 --- a/openrewrite/test/javascript/testHarness.ts +++ b/openrewrite/test/javascript/testHarness.ts @@ -38,8 +38,8 @@ registerJavaCodecs(SenderContext, ReceiverContext, RemotingContext) let client: net.Socket; let remoting: RemotingContext; let javaTestEngine: ChildProcessWithoutNullStreams -const ci = process.env.NODE_ENV === "ci" -console.log("NODE_ENV: " + process.env.NODE_ENV) +// to run integration tests with JavaPrinter set env NODE_ENV=it +const it = process.env.NODE_ENV === "it" function getRandomInt(min: number, max: number): number { min = Math.ceil(min); @@ -80,7 +80,7 @@ const getNextPort = async (port: number): Promise => { }; export async function connect(): Promise { - if (ci) { + if (it) { return new Promise((resolve, reject) => { const pathToJar = path.resolve(__dirname, '../../../rewrite-test-engine-remote/build/libs/rewrite-test-engine-remote-fat-jar.jar'); console.log(pathToJar); @@ -132,7 +132,7 @@ export async function connect(): Promise { } export async function disconnect(): Promise { - if (ci) { + if (it) { return new Promise((resolve, reject) => { if (client) { client.end(); @@ -220,7 +220,7 @@ export function typeScript(before: string, spec?: (sourceFile: JS.CompilationUni } function print(parsed: SourceFile) { - if (ci) { + if (it) { remoting.reset(); remoting.client?.reset(); } else { @@ -231,8 +231,7 @@ function print(parsed: SourceFile) { class LocalPrintFactory extends PrinterFactory { createPrinter

(cursor: Cursor): TreeVisitor> { - const printer = new JavaScriptPrinter

(); - printer.cursor = cursor; + const printer = new JavaScriptPrinter

(cursor); return printer; } } diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java index 06d4160b..0df79b64 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java @@ -623,7 +623,7 @@ public J visitTypeOperator(JS.TypeOperator typeOperator, P p) { } else { t = (JS.TypeOperator) temp; } - t = t.getPadding().withExpression(Objects.requireNonNull(visitLeftPadded(t.getPadding().getExpression(), JsLeftPadded.Location.TYPE_OPERATOR, p))); + t = t.getPadding().withExpression(Objects.requireNonNull(visitLeftPadded(t.getPadding().getExpression(), JsLeftPadded.Location.TYPE_OPERATOR_EXPRESSION, p))); return t; } diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/JavaScriptPrinter.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/JavaScriptPrinter.java index cde378b2..7069fee0 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/JavaScriptPrinter.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/internal/JavaScriptPrinter.java @@ -675,7 +675,7 @@ public J visitTypeOperator(JS.TypeOperator typeOperator, PrintOutputCapture

p p.append(keyword); - visitLeftPadded(typeOperator.getPadding().getExpression(), JsLeftPadded.Location.TYPE_OPERATOR, p); + visitLeftPadded(typeOperator.getPadding().getExpression(), JsLeftPadded.Location.TYPE_OPERATOR_EXPRESSION, p); afterSyntax(typeOperator, p); return typeOperator; diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsLeftPadded.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsLeftPadded.java index 3746cc8f..835d9e82 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsLeftPadded.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsLeftPadded.java @@ -26,7 +26,7 @@ public enum Location { IMPORT_INITIALIZER(JsSpace.Location.IMPORT_INITIALIZER_PREFIX), TYPE_DECLARATION_NAME(JsSpace.Location.TYPE_DECLARATION_NAME_PREFIX), TYPE_DECLARATION_INITIALIZER(JsSpace.Location.TYPE_DECLARATION_INITIALIZER_PREFIX), - TYPE_OPERATOR(JsSpace.Location.TYPE_OPERATOR_PREFIX), + TYPE_OPERATOR_EXPRESSION(JsSpace.Location.TYPE_OPERATOR_EXPRESSION_PREFIX), JSVARIABLE_INITIALIZER(JsSpace.Location.JSVARIABLE_INITIALIZER), SCOPED_VARIABLE_DECLARATIONS_SCOPE(JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_SCOPE_PREFIX), NAMESPACE_DECLARATION_KEYWORD_TYPE(JsSpace.Location.NAMESPACE_DECLARATION_KEYWORD_PREFIX), diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsSpace.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsSpace.java index c82972bd..6eff54b7 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsSpace.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsSpace.java @@ -195,5 +195,6 @@ public enum Location { JS_IMPORT_TYPE_ATTRIBUTES_PREFIX, JS_IMPORT_TYPE_ATTRIBUTES_ELEMENTS, JS_IMPORT_TYPE_ATTRIBUTES_ELEMENTS_SUFFIX, + TYPE_OPERATOR_EXPRESSION_PREFIX, } } From 00cffadc1d2bd9b3eafb249883d078c27b50b05a Mon Sep 17 00:00:00 2001 From: Andrii Rodionov Date: Wed, 19 Feb 2025 15:08:24 +0100 Subject: [PATCH 3/3] - added override keyword to print methods --- openrewrite/src/javascript/printer.ts | 225 +++++++++--------- .../test/javascript/parser/for.test.ts | 7 + 2 files changed, 117 insertions(+), 115 deletions(-) diff --git a/openrewrite/src/javascript/printer.ts b/openrewrite/src/javascript/printer.ts index 6f28bca4..6e857652 100644 --- a/openrewrite/src/javascript/printer.ts +++ b/openrewrite/src/javascript/printer.ts @@ -27,11 +27,11 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J | null { + override visit(tree: Tree | null, p: PrintOutputCapture

): J.J | null { return super.visit(tree, p); } - visitJsCompilationUnit(cu: JS.CompilationUnit, p: PrintOutputCapture

): J.J | null { + override visitJsCompilationUnit(cu: JS.CompilationUnit, p: PrintOutputCapture

): J.J | null { this.beforeSyntax(cu, Space.Location.COMPILATION_UNIT_PREFIX, p); this.visitJsRightPaddedLocal(cu.padding.statements, JsRightPadded.Location.COMPILATION_UNIT_STATEMENTS, "", p); @@ -41,7 +41,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J | null { + // override visitCompilationUnit(cu: J.CompilationUnit, p: PrintOutputCapture

): J.J | null { // this.beforeSyntax(cu, Space.Location.COMPILATION_UNIT_PREFIX, p); // // //this.visitJRightPadded(cu.padding.getStatements(), JRightPadded.Location.LANGUAGE_EXTENSION, "", p); @@ -51,7 +51,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.Alias { + override visitAlias(alias: JS.Alias, p: PrintOutputCapture

): JS.Alias { this.beforeSyntax(alias, JsSpace.Location.ALIAS_PREFIX, p); this.visitJsRightPadded(alias.padding.propertyName, JsRightPadded.Location.ALIAS_PROPERTY_NAME, p); p.append("as"); @@ -60,7 +60,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.Await { + override visitAwait(awaitExpr: JS.Await, p: PrintOutputCapture

): JS.Await { this.beforeSyntax(awaitExpr, JsSpace.Location.AWAIT_PREFIX, p); p.append("await"); this.visit(awaitExpr.expression, p); @@ -68,7 +68,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.BindingElement { + override visitBindingElement(binding: JS.BindingElement, p: PrintOutputCapture

): JS.BindingElement { this.beforeSyntax(binding, JsSpace.Location.BINDING_ELEMENT_PREFIX, p); if (binding.propertyName) { this.visitJsRightPadded(binding.padding.propertyName, JsRightPadded.Location.BINDING_ELEMENT_PROPERTY_NAME, p); @@ -80,7 +80,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.Delete { + override visitDelete(del: JS.Delete, p: PrintOutputCapture

): JS.Delete { this.beforeSyntax(del, JsSpace.Location.DELETE_PREFIX, p); p.append("delete"); this.visit(del.expression, p); @@ -88,21 +88,21 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TrailingTokenStatement { + override visitTrailingTokenStatement(statement: JS.TrailingTokenStatement, p: PrintOutputCapture

): JS.TrailingTokenStatement { this.beforeSyntax(statement, JsSpace.Location.TRAILING_TOKEN_STATEMENT_PREFIX, p); this.visitJsRightPadded(statement.padding.expression, JsRightPadded.Location.TRAILING_TOKEN_STATEMENT_EXPRESSION, p); this.afterSyntax(statement, p); return statement; } - visitInferType(inferType: JS.InferType, p: PrintOutputCapture

): JS.InferType { + override visitInferType(inferType: JS.InferType, p: PrintOutputCapture

): JS.InferType { this.beforeSyntax(inferType, JsSpace.Location.INFER_TYPE_PREFIX, p); this.visitJsLeftPaddedLocal("infer", inferType.padding.typeParameter, JsLeftPadded.Location.INFER_TYPE_TYPE_PARAMETER, p); this.afterSyntax(inferType, p); return inferType; } - visitJsImport(jsImport: JS.JsImport, p: PrintOutputCapture

): JS.JsImport { + override visitJsImport(jsImport: JS.JsImport, p: PrintOutputCapture

): JS.JsImport { this.beforeSyntax(jsImport, JsSpace.Location.JS_IMPORT_PREFIX, p); jsImport.modifiers.forEach(m => this.visitModifier(m, p)); p.append("import"); @@ -116,7 +116,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.JsImportClause { + override visitJsImportClause(jsImportClause: JS.JsImportClause, p: PrintOutputCapture

): JS.JsImportClause { this.beforeSyntax(jsImportClause, JsSpace.Location.JS_IMPORT_CLAUSE_PREFIX, p); if (jsImportClause.typeOnly) { @@ -137,14 +137,14 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TypeTreeExpression { + override visitTypeTreeExpression(typeTreeExpression: JS.TypeTreeExpression, p: PrintOutputCapture

): JS.TypeTreeExpression { this.beforeSyntax(typeTreeExpression, JsSpace.Location.TYPE_TREE_EXPRESSION_PREFIX, p); this.visit(typeTreeExpression.expression, p); this.afterSyntax(typeTreeExpression, p); return typeTreeExpression; } - visitNamespaceDeclaration(namespaceDeclaration: JS.NamespaceDeclaration, p: PrintOutputCapture

): JS.NamespaceDeclaration { + override visitNamespaceDeclaration(namespaceDeclaration: JS.NamespaceDeclaration, p: PrintOutputCapture

): JS.NamespaceDeclaration { this.beforeSyntax(namespaceDeclaration, JsSpace.Location.NAMESPACE_DECLARATION_PREFIX, p); namespaceDeclaration.modifiers.forEach(it => this.visitModifier(it, p)); this.visitSpace(namespaceDeclaration.padding.keywordType.before, JsSpace.Location.NAMESPACE_DECLARATION_KEYWORD_TYPE_PREFIX, p); @@ -170,7 +170,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.SatisfiesExpression { + override visitSatisfiesExpression(satisfiesExpression: JS.SatisfiesExpression, p: PrintOutputCapture

): JS.SatisfiesExpression { this.beforeSyntax(satisfiesExpression, JsSpace.Location.SATISFIES_EXPRESSION_PREFIX, p); this.visit(satisfiesExpression.expression, p); this.visitJsLeftPaddedLocal("satisfies", satisfiesExpression.padding.satisfiesType, JsLeftPadded.Location.SATISFIES_EXPRESSION_SATISFIES_TYPE, p); @@ -178,7 +178,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.Void { + override visitVoid(aVoid: JS.Void, p: PrintOutputCapture

): JS.Void { this.beforeSyntax(aVoid, JsSpace.Location.VOID_PREFIX, p); p.append("void"); this.visit(aVoid.expression, p); @@ -186,7 +186,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.Yield { + override visitJsYield(yield_: JS.Yield, p: PrintOutputCapture

): JS.Yield { this.beforeSyntax(yield_, JsSpace.Location.YIELD_PREFIX, p); p.append("yield"); @@ -201,7 +201,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Try { + override visitTry(try_: J.Try, p: PrintOutputCapture

): J.Try { this.beforeSyntax(try_, Space.Location.TRY_PREFIX, p); p.append("try"); this.visit(try_.body, p); @@ -211,7 +211,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Try.Catch { + override visitCatch(catch_: J.Try.Catch, p: PrintOutputCapture

): J.Try.Catch { this.beforeSyntax(catch_, Space.Location.CATCH_PREFIX, p); p.append("catch"); if (catch_.parameter.tree.variables.length > 0) { @@ -222,7 +222,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.JSTry { + override visitJSTry(jsTry: JS.JSTry, p: PrintOutputCapture

): JS.JSTry { this.beforeSyntax(jsTry, JsSpace.Location.JSTRY_PREFIX, p); p.append("try"); this.visit(jsTry.body, p); @@ -232,7 +232,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.JSTry.JSCatch { + override visitJSTryJSCatch(jsCatch: JS.JSTry.JSCatch, p: PrintOutputCapture

): JS.JSTry.JSCatch { this.beforeSyntax(jsCatch, JsSpace.Location.JSTRY_JSCATCH_PREFIX, p); p.append("catch"); this.visit(jsCatch.parameter, p); @@ -241,7 +241,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.JSVariableDeclarations { + override visitJSVariableDeclarations(multiVariable: JS.JSVariableDeclarations, p: PrintOutputCapture

): JS.JSVariableDeclarations { this.beforeSyntax(multiVariable, JsSpace.Location.JSVARIABLE_DECLARATIONS_PREFIX, p); this.visitNodes(multiVariable.leadingAnnotations, p); multiVariable.modifiers.forEach(it => this.visitModifier(it, p)); @@ -277,7 +277,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.JSVariableDeclarations.JSNamedVariable { + override visitJSVariableDeclarationsJSNamedVariable(variable: JS.JSVariableDeclarations.JSNamedVariable, p: PrintOutputCapture

): JS.JSVariableDeclarations.JSNamedVariable { this.beforeSyntax(variable, JsSpace.Location.JSVARIABLE_DECLARATIONS_JSNAMED_VARIABLE_PREFIX, p); this.visit(variable.name, p); const initializer = variable.padding.initializer; @@ -286,7 +286,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.ArrayDimension { + override visitArrayDimension(arrayDimension: J.ArrayDimension, p: PrintOutputCapture

): J.ArrayDimension { this.beforeSyntax(arrayDimension, Space.Location.DIMENSION_PREFIX, p); p.append("["); this.visitJRightPaddedLocalSingle(arrayDimension.padding.index, JRightPadded.Location.ARRAY_INDEX, "]", p); @@ -294,7 +294,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.ArrayType { + override visitArrayType(arrayType: J.ArrayType, p: PrintOutputCapture

): J.ArrayType { this.beforeSyntax(arrayType, Space.Location.ARRAY_TYPE_PREFIX, p); let type: J.TypeTree = arrayType; @@ -336,7 +336,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Ternary { + override visitTernary(ternary: J.Ternary, p: PrintOutputCapture

): J.Ternary { this.beforeSyntax(ternary, Space.Location.TERNARY_PREFIX, p); this.visit(ternary.condition, p); this.visitJLeftPaddedLocal("?", ternary.padding.truePart, JLeftPadded.Location.TERNARY_TRUE, p); @@ -345,7 +345,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Throw { + override visitThrow(thrown: J.Throw, p: PrintOutputCapture

): J.Throw { this.beforeSyntax(thrown, Space.Location.THROW_PREFIX, p); p.append("throw"); this.visit(thrown.exception, p); @@ -353,7 +353,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.If { + override visitIf(iff: J.If, p: PrintOutputCapture

): J.If { this.beforeSyntax(iff, Space.Location.IF_PREFIX, p); p.append("if"); this.visit(iff.ifCondition, p); @@ -363,7 +363,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.If.Else { + override visitElse(else_: J.If.Else, p: PrintOutputCapture

): J.If.Else { this.beforeSyntax(else_, Space.Location.ELSE_PREFIX, p); p.append("else"); this.visitStatementLocal(else_.padding.body, JRightPadded.Location.IF_ELSE, p); @@ -371,7 +371,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.DoWhileLoop { + override visitDoWhileLoop(doWhileLoop: J.DoWhileLoop, p: PrintOutputCapture

): J.DoWhileLoop { this.beforeSyntax(doWhileLoop, Space.Location.DO_WHILE_PREFIX, p); p.append("do"); this.visitStatementLocal(doWhileLoop.padding.body, JRightPadded.Location.WHILE_BODY, p); @@ -380,7 +380,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.WhileLoop { + override visitWhileLoop(whileLoop: J.WhileLoop, p: PrintOutputCapture

): J.WhileLoop { this.beforeSyntax(whileLoop, Space.Location.WHILE_PREFIX, p); p.append("while"); this.visit(whileLoop.condition, p); @@ -389,7 +389,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.InstanceOf { + override visitInstanceOf(instanceOf: J.InstanceOf, p: PrintOutputCapture

): J.InstanceOf { this.beforeSyntax(instanceOf, Space.Location.INSTANCEOF_PREFIX, p); this.visitJRightPaddedLocalSingle(instanceOf.padding.expression, JRightPadded.Location.INSTANCEOF, "instanceof", p); this.visit(instanceOf.clazz, p); @@ -398,7 +398,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitLiteral(literal: Literal, p: PrintOutputCapture

): J.J { this.beforeSyntax(literal, Space.Location.LITERAL_PREFIX, p); const unicodeEscapes = literal.unicodeEscapes; @@ -432,7 +432,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitScopedVariableDeclarations(variableDeclarations: JS.ScopedVariableDeclarations, p: PrintOutputCapture

): J.J { this.beforeSyntax(variableDeclarations, JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_PREFIX, p); variableDeclarations.modifiers.forEach(m => this.visitModifier(m, p)); @@ -466,7 +466,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitVariableDeclarations(multiVariable: J.VariableDeclarations, p: PrintOutputCapture

): J.J { this.beforeSyntax(multiVariable, Space.Location.VARIABLE_DECLARATIONS_PREFIX, p); this.visitNodes(multiVariable.leadingAnnotations, p); @@ -506,7 +506,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitVariable(variable: J.VariableDeclarations.NamedVariable, p: PrintOutputCapture

): J.J { this.beforeSyntax(variable, Space.Location.VARIABLE_PREFIX, p); this.visit(variable.name, p); @@ -517,7 +517,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitIdentifier(ident: J.Identifier, p: PrintOutputCapture

): J.J { this.visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); this.visitNodes(ident.annotations, p); this.beforeSyntax(ident, Space.Location.IDENTIFIER_PREFIX, p); @@ -526,7 +526,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.FunctionDeclaration { + override visitFunctionDeclaration(functionDeclaration: JS.FunctionDeclaration, p: PrintOutputCapture

): JS.FunctionDeclaration { this.beforeSyntax(functionDeclaration, JsSpace.Location.FUNCTION_DECLARATION_PREFIX, p); functionDeclaration.modifiers.forEach((m) => this.visitModifier(m, p)); @@ -560,7 +560,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Block { + override visitBlock(block: J.Block, p: PrintOutputCapture

): J.Block { this.beforeSyntax(block, Space.Location.BLOCK_PREFIX, p); if (block.static) { @@ -577,7 +577,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TypeInfo { + override visitTypeInfo(typeInfo: JS.TypeInfo, p: PrintOutputCapture

): JS.TypeInfo { this.beforeSyntax(typeInfo, JsSpace.Location.TYPE_INFO_PREFIX, p); p.append(":"); this.visit(typeInfo.typeIdentifier, p); @@ -585,7 +585,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Return { + override visitReturn(return_: J.Return, p: PrintOutputCapture

): J.Return { this.beforeSyntax(return_, Space.Location.RETURN_PREFIX, p); p.append("return"); this.visit(return_.expression, p); @@ -593,7 +593,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Modifier { + override visitModifier(mod: J.Modifier, p: PrintOutputCapture

): J.Modifier { this.visitNodes(mod.annotations, p); let keyword: string; @@ -653,7 +653,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.FunctionType { + override visitFunctionType(functionType: JS.FunctionType, p: PrintOutputCapture

): JS.FunctionType { this.beforeSyntax(functionType, JsSpace.Location.FUNCTION_TYPE_PREFIX, p); functionType.modifiers.forEach(m => this.visitModifier(m, p)); @@ -678,7 +678,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.ClassDeclaration { + override visitClassDeclaration(classDecl: J.ClassDeclaration, p: PrintOutputCapture

): J.ClassDeclaration { let kind = ""; switch (classDecl.padding.kind.type) { case J.ClassDeclaration.Kind.Type.Class: @@ -717,7 +717,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitMethodDeclaration(method: J.MethodDeclaration, p: PrintOutputCapture

): J.J { this.beforeSyntax(method, Space.Location.METHOD_DECLARATION_PREFIX, p); this.visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); this.visitNodes(method.leadingAnnotations, p); @@ -746,7 +746,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.JSMethodDeclaration { + override visitJSMethodDeclaration(method: JS.JSMethodDeclaration, p: PrintOutputCapture

): JS.JSMethodDeclaration { this.beforeSyntax(method, JsSpace.Location.JSMETHOD_DECLARATION_PREFIX, p); this.visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); this.visitNodes(method.leadingAnnotations, p); @@ -774,7 +774,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.MethodInvocation { + override visitMethodInvocation(method: J.MethodInvocation, p: PrintOutputCapture

): J.MethodInvocation { this.beforeSyntax(method, Space.Location.METHOD_INVOCATION_PREFIX, p); if (method.name.toString().length === 0) { @@ -791,7 +791,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.TypeParameter { + override visitTypeParameter(typeParameter: J.TypeParameter, p: PrintOutputCapture

): J.TypeParameter { this.beforeSyntax(typeParameter, Space.Location.TYPE_PARAMETERS_PREFIX, p); this.visitNodes(typeParameter.annotations, p); typeParameter.modifiers.forEach(m => this.visitModifier(m, p)); @@ -818,7 +818,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitArrowFunction(arrowFunction: JS.ArrowFunction, p: PrintOutputCapture

): J.J { this.beforeSyntax(arrowFunction, JsSpace.Location.ARROW_FUNCTION_PREFIX, p); this.visitNodes(arrowFunction.leadingAnnotations, p); arrowFunction.modifiers.forEach(m => this.visitModifier(m, p)); @@ -852,7 +852,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitConditionalType(conditionalType: JS.ConditionalType, p: PrintOutputCapture

): J.J { this.beforeSyntax(conditionalType, JsSpace.Location.CONDITIONAL_TYPE_PREFIX, p); this.visit(conditionalType.checkType, p); this.visitJsContainerLocal("extends", conditionalType.padding.condition, JsContainer.Location.CONDITIONAL_TYPE_CONDITION, "", "", p); @@ -860,7 +860,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitExpressionWithTypeArguments(type: JS.ExpressionWithTypeArguments, p: PrintOutputCapture

): J.J { this.beforeSyntax(type, JsSpace.Location.EXPRESSION_WITH_TYPE_ARGUMENTS_PREFIX, p); this.visit(type.clazz, p); this.visitJsContainerLocal("<", type.padding.typeArguments, JsContainer.Location.EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS, ",", ">", p); @@ -868,7 +868,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitImportType(importType: JS.ImportType, p: PrintOutputCapture

): J.J { this.beforeSyntax(importType, JsSpace.Location.IMPORT_TYPE_PREFIX, p); if (importType.hasTypeof) { @@ -885,7 +885,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitTypeDeclaration(typeDeclaration: JS.TypeDeclaration, p: PrintOutputCapture

): J.J { this.beforeSyntax(typeDeclaration, JsSpace.Location.TYPE_DECLARATION_PREFIX, p); typeDeclaration.modifiers.forEach(m => this.visitModifier(m, p)); @@ -908,21 +908,21 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitLiteralType(literalType: JS.LiteralType, p: PrintOutputCapture

): J.J { this.beforeSyntax(literalType, JsSpace.Location.LITERAL_TYPE_PREFIX, p); this.visit(literalType.literal, p); this.afterSyntax(literalType, p); return literalType; } - visitNamedImports(namedImports: JS.NamedImports, p: PrintOutputCapture

): J.J { + override visitNamedImports(namedImports: JS.NamedImports, p: PrintOutputCapture

): J.J { this.beforeSyntax(namedImports, JsSpace.Location.NAMED_IMPORTS_PREFIX, p); this.visitJsContainerLocal("{", namedImports.padding.elements, JsContainer.Location.NAMED_IMPORTS_ELEMENTS, ",", "}", p); this.afterSyntax(namedImports, p); return namedImports; } - visitJsImportSpecifier(jis: JS.JsImportSpecifier, p: PrintOutputCapture

): JS.JsImportSpecifier { + override visitJsImportSpecifier(jis: JS.JsImportSpecifier, p: PrintOutputCapture

): JS.JsImportSpecifier { this.beforeSyntax(jis, JsSpace.Location.JS_IMPORT_SPECIFIER_PREFIX, p); if (jis.importType) { @@ -935,7 +935,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.ExportDeclaration { + override visitExportDeclaration(ed: JS.ExportDeclaration, p: PrintOutputCapture

): JS.ExportDeclaration { this.beforeSyntax(ed, JsSpace.Location.EXPORT_DECLARATION_PREFIX, p); p.append("export"); ed.modifiers.forEach(it => this.visitModifier(it, p)); @@ -952,7 +952,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.ExportAssignment { + override visitExportAssignment(es: JS.ExportAssignment, p: PrintOutputCapture

): JS.ExportAssignment { this.beforeSyntax(es, JsSpace.Location.EXPORT_ASSIGNMENT_PREFIX, p); p.append("export"); es.modifiers.forEach(it => this.visitModifier(it, p)); @@ -966,7 +966,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.IndexedAccessType { + override visitIndexedAccessType(iat: JS.IndexedAccessType, p: PrintOutputCapture

): JS.IndexedAccessType { this.beforeSyntax(iat, JsSpace.Location.INDEXED_ACCESS_TYPE_PREFIX, p); this.visit(iat.objectType, p); @@ -978,7 +978,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.IndexedAccessType.IndexType { + override visitIndexedAccessTypeIndexType(iatit: JS.IndexedAccessType.IndexType, p: PrintOutputCapture

): JS.IndexedAccessType.IndexType { this.beforeSyntax(iatit, JsSpace.Location.INDEXED_ACCESS_TYPE_INDEX_TYPE_PREFIX, p); p.append("["); @@ -989,7 +989,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.WithStatement { + override visitWithStatement(withStatement: JS.WithStatement, p: PrintOutputCapture

): JS.WithStatement { this.beforeSyntax(withStatement, JsSpace.Location.WITH_STATEMENT_PREFIX, p); p.append("with"); this.visit(withStatement.expression, p); @@ -998,7 +998,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.ExportSpecifier { + override visitExportSpecifier(es: JS.ExportSpecifier, p: PrintOutputCapture

): JS.ExportSpecifier { this.beforeSyntax(es, JsSpace.Location.EXPORT_SPECIFIER_PREFIX, p); if (es.typeOnly) { this.visitJsLeftPaddedLocal("type", es.padding.typeOnly, JsLeftPadded.Location.EXPORT_SPECIFIER_TYPE_ONLY, p); @@ -1010,16 +1010,14 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitNamedExports(ne: JS.NamedExports, p: PrintOutputCapture

): J.J { this.beforeSyntax(ne, JsSpace.Location.NAMED_EXPORTS_PREFIX, p); this.visitJsContainerLocal("{", ne.padding.elements, JsContainer.Location.NAMED_EXPORTS_ELEMENTS, ",", "}", p); this.afterSyntax(ne, p); return ne; } - visitImportAttributes(importAttributes: JS.ImportAttributes, p: PrintOutputCapture

): J.J { + override visitImportAttributes(importAttributes: JS.ImportAttributes, p: PrintOutputCapture

): J.J { this.beforeSyntax(importAttributes, JsSpace.Location.IMPORT_ATTRIBUTES_PREFIX, p); p.append(JS.ImportAttributes.Token[importAttributes.token].toLowerCase()); @@ -1029,7 +1027,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitImportAttribute(importAttribute: JS.ImportAttribute, p: PrintOutputCapture

): J.J { this.beforeSyntax(importAttribute, JsSpace.Location.IMPORT_ATTRIBUTE_PREFIX, p); this.visit(importAttribute.name, p); @@ -1039,7 +1037,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitImportTypeAttributes(importAttributes: JS.ImportTypeAttributes, p: PrintOutputCapture

): J.J { this.beforeSyntax(importAttributes, JsSpace.Location.IMPORT_TYPE_ATTRIBUTES_PREFIX, p); p.append("{"); @@ -1053,7 +1051,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitArrayBindingPattern(abp: JS.ArrayBindingPattern, p: PrintOutputCapture

): J.J { this.beforeSyntax(abp, JsSpace.Location.ARRAY_BINDING_PATTERN_PREFIX, p); this.visitJsContainerLocal("[", abp.padding.elements, JsContainer.Location.ARRAY_BINDING_PATTERN_ELEMENTS, ",", "]", p); @@ -1062,7 +1060,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitMappedType(mappedType: JS.MappedType, p: PrintOutputCapture

): J.J { this.beforeSyntax(mappedType, JsSpace.Location.MAPPED_TYPE_PREFIX, p); p.append("{"); @@ -1092,7 +1090,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitMappedTypeKeysRemapping(mappedTypeKeys: JS.MappedType.KeysRemapping, p: PrintOutputCapture

): J.J { this.beforeSyntax(mappedTypeKeys, JsSpace.Location.MAPPED_TYPE_KEYS_REMAPPING_PREFIX, p); p.append("["); this.visitJsRightPadded(mappedTypeKeys.padding.typeParameter, JsRightPadded.Location.MAPPED_TYPE_KEYS_REMAPPING_TYPE_PARAMETER, p); @@ -1107,7 +1105,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitMappedTypeMappedTypeParameter(mappedTypeParameter: JS.MappedType.MappedTypeParameter, p: PrintOutputCapture

): J.J { this.beforeSyntax(mappedTypeParameter, JsSpace.Location.MAPPED_TYPE_MAPPED_TYPE_PARAMETER_PREFIX, p); this.visit(mappedTypeParameter.name, p); this.visitJsLeftPaddedLocal("in", mappedTypeParameter.padding.iterateType, JsLeftPadded.Location.MAPPED_TYPE_MAPPED_TYPE_PARAMETER_ITERATE_TYPE, p); @@ -1115,7 +1113,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitObjectBindingDeclarations(objectBindingDeclarations: JS.ObjectBindingDeclarations, p: PrintOutputCapture

): J.J { this.beforeSyntax(objectBindingDeclarations, JsSpace.Location.OBJECT_BINDING_DECLARATIONS_PREFIX, p); this.visitNodes(objectBindingDeclarations.leadingAnnotations, p); objectBindingDeclarations.modifiers.forEach(m => this.visitModifier(m, p)); @@ -1127,7 +1125,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitTaggedTemplateExpression(taggedTemplateExpression: JS.TaggedTemplateExpression, p: PrintOutputCapture

): J.J { this.beforeSyntax(taggedTemplateExpression, JsSpace.Location.TAGGED_TEMPLATE_EXPRESSION_PREFIX, p); this.visitJsRightPadded(taggedTemplateExpression.padding.tag, JsRightPadded.Location.TAGGED_TEMPLATE_EXPRESSION_TAG, p); this.visitJsContainerLocal("<", taggedTemplateExpression.padding.typeArguments, JsContainer.Location.TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS, ",", ">", p); @@ -1136,7 +1134,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TemplateExpression { + override visitTemplateExpression(templateExpression: JS.TemplateExpression, p: PrintOutputCapture

): JS.TemplateExpression { this.beforeSyntax(templateExpression, JsSpace.Location.TEMPLATE_EXPRESSION_PREFIX, p); this.visit(templateExpression.head, p); this.visitJsRightPaddedLocal(templateExpression.padding.templateSpans, JsRightPadded.Location.TEMPLATE_EXPRESSION_TEMPLATE_SPANS, "", p); @@ -1144,7 +1142,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TemplateExpression.TemplateSpan { + override visitTemplateExpressionTemplateSpan(value: JS.TemplateExpression.TemplateSpan, p: PrintOutputCapture

): JS.TemplateExpression.TemplateSpan { this.beforeSyntax(value, JsSpace.Location.TEMPLATE_EXPRESSION_TEMPLATE_SPAN_PREFIX, p); this.visit(value.expression, p); this.visit(value.tail, p); @@ -1152,14 +1150,14 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitTuple(tuple: JS.Tuple, p: PrintOutputCapture

): J.J { this.beforeSyntax(tuple, JsSpace.Location.TUPLE_PREFIX, p); this.visitJsContainerLocal("[", tuple.padding.elements, JsContainer.Location.TUPLE_ELEMENTS, ",", "]", p); this.afterSyntax(tuple, p); return tuple; } - visitTypeQuery(typeQuery: JS.TypeQuery, p: PrintOutputCapture

): J.J { + override visitTypeQuery(typeQuery: JS.TypeQuery, p: PrintOutputCapture

): J.J { this.beforeSyntax(typeQuery, JsSpace.Location.TYPE_QUERY_PREFIX, p); p.append("typeof"); this.visit(typeQuery.typeExpression, p); @@ -1168,7 +1166,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TypeOf { + override visitTypeOf(typeOf: JS.TypeOf, p: PrintOutputCapture

): JS.TypeOf { this.beforeSyntax(typeOf, JsSpace.Location.TYPE_OF_PREFIX, p); p.append("typeof"); this.visit(typeOf.expression, p); @@ -1176,7 +1174,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TypeOperator { + override visitTypeOperator(typeOperator: JS.TypeOperator, p: PrintOutputCapture

): JS.TypeOperator { this.beforeSyntax(typeOperator, JsSpace.Location.TYPE_OPERATOR_PREFIX, p); let keyword = ""; @@ -1196,7 +1194,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.TypePredicate { + override visitTypePredicate(typePredicate: JS.TypePredicate, p: PrintOutputCapture

): JS.TypePredicate { this.beforeSyntax(typePredicate, JsSpace.Location.TYPE_PREDICATE_PREFIX, p); if (typePredicate.asserts) { @@ -1210,7 +1208,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitIndexSignatureDeclaration(isd: JS.IndexSignatureDeclaration, p: PrintOutputCapture

): J.J { this.beforeSyntax(isd, JsSpace.Location.INDEX_SIGNATURE_DECLARATION_PREFIX, p); isd.modifiers.forEach(m => this.visitModifier(m, p)); @@ -1221,7 +1219,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitAnnotation(annotation: J.Annotation, p: PrintOutputCapture

): J.J { this.beforeSyntax(annotation, Space.Location.ANNOTATION_PREFIX, p); p.append("@"); @@ -1232,7 +1230,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitNewArray(newArray: J.NewArray, p: PrintOutputCapture

): J.J { this.beforeSyntax(newArray, Space.Location.NEW_ARRAY_PREFIX, p); this.visit(newArray.typeExpression, p); this.visitNodes(newArray.dimensions, p); @@ -1241,7 +1239,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitNewClass(newClass: J.NewClass, p: PrintOutputCapture

): J.J { this.beforeSyntax(newClass, Space.Location.NEW_CLASS_PREFIX, p); this.visitJRightPaddedLocalSingle(newClass.padding.enclosing, JRightPadded.Location.NEW_CLASS_ENCLOSING, ".", p); this.visitSpace(newClass.new, Space.Location.NEW_PREFIX, p); @@ -1260,7 +1258,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitSwitch(switch_: J.Switch, p: PrintOutputCapture

): J.J { this.beforeSyntax(switch_, Space.Location.SWITCH_PREFIX, p); p.append("switch"); this.visit(switch_.selector, p); @@ -1269,7 +1267,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitCase(case_: J.Case, p: PrintOutputCapture

): J.J { this.beforeSyntax(case_, Space.Location.CASE_PREFIX, p); const elem = case_.caseLabels[0]; @@ -1288,7 +1286,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Label { + override visitLabel(label: J.Label, p: PrintOutputCapture

): J.Label { this.beforeSyntax(label, Space.Location.LABEL_PREFIX, p); this.visitJRightPaddedLocalSingle(label.padding.label, JRightPadded.Location.LABEL, ":", p); this.visit(label.statement, p); @@ -1296,7 +1294,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Continue { + override visitContinue(continueStatement: J.Continue, p: PrintOutputCapture

): J.Continue { this.beforeSyntax(continueStatement, Space.Location.CONTINUE_PREFIX, p); p.append("continue"); this.visit(continueStatement.label, p); @@ -1304,7 +1302,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitBreak(breakStatement: J.Break, p: PrintOutputCapture

): J.J { this.beforeSyntax(breakStatement, Space.Location.BREAK_PREFIX, p); p.append("break"); this.visit(breakStatement.label, p); @@ -1312,18 +1310,16 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.FieldAccess { + override visitFieldAccess(fieldAccess: J.FieldAccess, p: PrintOutputCapture

): J.FieldAccess { this.beforeSyntax(fieldAccess, Space.Location.FIELD_ACCESS_PREFIX, p); this.visit(fieldAccess.target, p); - //const postFixOperator = fieldAccess.markers.findFirst(PostFixOperator).orElse(null); this.visitJLeftPaddedLocal(".", fieldAccess.padding.name, JLeftPadded.Location.FIELD_ACCESS_NAME, p); this.afterSyntax(fieldAccess, p); return fieldAccess; } - - visitTypeLiteral(tl: JS.TypeLiteral, p: PrintOutputCapture

): JS.TypeLiteral { + override visitTypeLiteral(tl: JS.TypeLiteral, p: PrintOutputCapture

): JS.TypeLiteral { this.beforeSyntax(tl, JsSpace.Location.TYPE_LITERAL_PREFIX, p); this.visit(tl.members, p); @@ -1332,7 +1328,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor(parens: J.Parentheses, p: PrintOutputCapture

): J.J { + override visitParentheses(parens: J.Parentheses, p: PrintOutputCapture

): J.J { this.beforeSyntax(parens, Space.Location.PARENTHESES_PREFIX, p); p.append('('); this.visitJRightPaddedLocalSingle(parens.padding.tree, JRightPadded.Location.PARENTHESES, ")", p); @@ -1340,7 +1336,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitParameterizedType(type: J.ParameterizedType, p: PrintOutputCapture

): J.J { this.beforeSyntax(type, Space.Location.PARAMETERIZED_TYPE_PREFIX, p); this.visit(type.clazz, p); this.visitJContainerLocal("<", type.padding.typeParameters, JContainer.Location.TYPE_PARAMETERS, ",", ">", p); @@ -1348,7 +1344,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitAssignment(assignment: J.Assignment, p: PrintOutputCapture

): J.J { this.beforeSyntax(assignment, Space.Location.ASSIGNMENT_PREFIX, p); this.visit(assignment.variable, p); this.visitJLeftPaddedLocal("=", assignment.padding.assignment, JLeftPadded.Location.ASSIGNMENT, p); @@ -1356,7 +1352,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitPropertyAssignment(propertyAssignment: JS.PropertyAssignment, p: PrintOutputCapture

): J.J { this.beforeSyntax(propertyAssignment, JsSpace.Location.PROPERTY_ASSIGNMENT_PREFIX, p); this.visitJsRightPadded(propertyAssignment.padding.name, JsRightPadded.Location.PROPERTY_ASSIGNMENT_NAME, p); @@ -1376,7 +1372,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitAssignmentOperation(assignOp: J.AssignmentOperation, p: PrintOutputCapture

): J.J { let keyword = ""; switch (assignOp.operator) { case J.AssignmentOperation.Type.Addition: @@ -1424,7 +1420,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitJsAssignmentOperation(assignOp: JS.JsAssignmentOperation, p: PrintOutputCapture

): J.J { let keyword = ""; switch (assignOp.operator) { case JS.JsAssignmentOperation.Type.QuestionQuestion: @@ -1454,7 +1450,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitEnumValue(enum_: J.EnumValue, p: PrintOutputCapture

): J.J { this.beforeSyntax(enum_, Space.Location.ENUM_VALUE_PREFIX, p); this.visit(enum_.name, p); @@ -1472,7 +1468,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitEnumValueSet(enums: J.EnumValueSet, p: PrintOutputCapture

): J.J { this.beforeSyntax(enums, Space.Location.ENUM_VALUE_SET_PREFIX, p); this.visitJRightPaddedLocal(enums.padding.enums, JRightPadded.Location.ENUM_VALUE, ",", p); @@ -1484,7 +1480,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitBinary(binary: J.Binary, p: PrintOutputCapture

): J.J { let keyword = ""; switch (binary.operator) { case J.Binary.Type.Addition: @@ -1539,7 +1535,6 @@ export class JavaScriptPrinter

extends JavaScriptVisitor marker instanceof Comma) ? "," : "||"; keyword = "||"; break; case J.Binary.Type.And: @@ -1557,7 +1552,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitJsBinary(binary: JS.JsBinary, p: PrintOutputCapture

): J.J { this.beforeSyntax(binary, JsSpace.Location.JS_BINARY_PREFIX, p); this.visit(binary.left, p); @@ -1593,7 +1588,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.Unary { + override visitUnary(unary: J.Unary, p: PrintOutputCapture

): J.Unary { this.beforeSyntax(unary, Space.Location.UNARY_PREFIX, p); switch (unary.operator) { case J.Unary.Type.PreIncrement: @@ -1635,7 +1630,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.J { + override visitJsUnary(unary: JS.Unary, p: PrintOutputCapture

): J.J { this.beforeSyntax(unary, JsSpace.Location.UNARY_PREFIX, p); switch (unary.operator) { @@ -1677,7 +1672,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.Union { + override visitUnion(union: JS.Union, p: PrintOutputCapture

): JS.Union { this.beforeSyntax(union, JsSpace.Location.UNION_PREFIX, p); this.visitJsRightPaddedLocal(union.padding.types, JsRightPadded.Location.UNION_TYPES, "|", p); @@ -1686,7 +1681,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.Intersection { + override visitIntersection(intersection: JS.Intersection, p: PrintOutputCapture

): JS.Intersection { this.beforeSyntax(intersection, JsSpace.Location.INTERSECTION_PREFIX, p); this.visitJsRightPaddedLocal(intersection.padding.types, JsRightPadded.Location.INTERSECTION_TYPES, "&", p); @@ -1695,7 +1690,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): J.ForLoop { + override visitForLoop(forLoop: J.ForLoop, p: PrintOutputCapture

): J.ForLoop { this.beforeSyntax(forLoop, Space.Location.FOR_PREFIX, p); p.append("for"); const ctrl = forLoop.control; @@ -1711,7 +1706,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.JSForOfLoop { + override visitJSForOfLoop(loop: JS.JSForOfLoop, p: PrintOutputCapture

): JS.JSForOfLoop { this.beforeSyntax(loop, JsSpace.Location.JSFOR_OF_LOOP_PREFIX, p); p.append("for"); if (loop.await) { @@ -1730,7 +1725,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): JS.JSForInLoop { + override visitJSForInLoop(loop: JS.JSForInLoop, p: PrintOutputCapture

): JS.JSForInLoop { this.beforeSyntax(loop, JsSpace.Location.JSFOR_IN_LOOP_PREFIX, p); p.append("for"); @@ -1745,7 +1740,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor[], location: JRightPadded.Location, p: PrintOutputCapture

) { @@ -1814,7 +1809,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor): Space { + override visitSpace(space: Space, loc: Space.Location | JsSpace.Location | null, p: PrintOutputCapture

): Space { p.append(space.whitespace!); const comments = space.comments; @@ -1960,7 +1955,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor(marker: M, p: PrintOutputCapture

): M { + override visitMarker(marker: M, p: PrintOutputCapture

): M { if (marker instanceof Semicolon) { p.append(';'); } @@ -1993,7 +1988,7 @@ export class JavaScriptPrinter

extends JavaScriptVisitor(controlParens: J.ControlParentheses, p: PrintOutputCapture

): J.J { + override visitControlParentheses(controlParens: J.ControlParentheses, p: PrintOutputCapture

): J.J { this.beforeSyntax(controlParens, Space.Location.CONTROL_PARENTHESES_PREFIX, p); if (this.getParentCursor(1)?.value() instanceof J.TypeCast) { diff --git a/openrewrite/test/javascript/parser/for.test.ts b/openrewrite/test/javascript/parser/for.test.ts index 37a6deb0..9034f9de 100644 --- a/openrewrite/test/javascript/parser/for.test.ts +++ b/openrewrite/test/javascript/parser/for.test.ts @@ -25,6 +25,13 @@ describe('for mapping', () => { ); }); + test('for with assigment condition', () => { + rewriteRun( + //language=typescript + typeScript('for(var r,a=0;r=t[a++];);') + ); + }); + test('for indexed multiple variables', () => { rewriteRun( //language=typescript