diff --git a/openrewrite/src/javascript/parser.ts b/openrewrite/src/javascript/parser.ts index 2305480d..6f1facad 100644 --- a/openrewrite/src/javascript/parser.ts +++ b/openrewrite/src/javascript/parser.ts @@ -534,6 +534,10 @@ export class JavaScriptParserVisitor { return this.mapLiteral(node, null); } + visitNeverKeyword(node: ts.Node) { + return this.mapIdentifier(node, 'never'); + } + private mapLiteral(node: ts.LiteralExpression | ts.TrueLiteral | ts.FalseLiteral | ts.NullLiteral | ts.Identifier | ts.TemplateHead | ts.TemplateMiddle | ts.TemplateTail, value: any): J.Literal { return new J.Literal( @@ -1029,7 +1033,7 @@ export class JavaScriptParserVisitor { private mapTypeInfo(node: ts.MethodDeclaration | ts.PropertyDeclaration | ts.VariableDeclaration | ts.ParameterDeclaration | ts.PropertySignature | ts.MethodSignature | ts.ArrowFunction | ts.CallSignatureDeclaration | ts.GetAccessorDeclaration - | ts.FunctionDeclaration | ts.ConstructSignatureDeclaration | ts.FunctionExpression) { + | ts.FunctionDeclaration | ts.ConstructSignatureDeclaration | ts.FunctionExpression | ts.NamedTupleMember) { return node.type ? new JS.TypeInfo(randomId(), this.prefix(node.getChildAt(node.getChildren().indexOf(node.type) - 1)), Markers.EMPTY, this.visit(node.type)) : null; } @@ -1180,7 +1184,15 @@ export class JavaScriptParserVisitor { } visitTypePredicate(node: ts.TypePredicateNode) { - return this.visitUnknown(node); + return new JS.TypePredicate( + randomId(), + this.prefix(node), + Markers.EMPTY, + node.assertsModifier ? this.leftPadded(this.prefix(node.assertsModifier), true) : this.leftPadded(Space.EMPTY, false), + this.visit(node.parameterName), + node.type ? this.leftPadded(this.suffix(node.parameterName), this.convert(node.type)) : null, + this.mapType(node) + ); } visitTypeReference(node: ts.TypeReferenceNode) { @@ -1362,15 +1374,32 @@ export class JavaScriptParserVisitor { } visitInferType(node: ts.InferTypeNode) { - return this.visitUnknown(node); + return new JS.InferType( + randomId(), + this.prefix(node), + Markers.EMPTY, + this.leftPadded(Space.EMPTY, this.convert(node.typeParameter)), + this.mapType(node) + ); } visitParenthesizedType(node: ts.ParenthesizedTypeNode) { - return this.visitUnknown(node); + return new J.ParenthesizedTypeTree( + randomId(), + Space.EMPTY, + Markers.EMPTY, + [], + new J.Parentheses( + randomId(), + this.prefix(node), + Markers.EMPTY, + this.rightPadded(this.convert(node.type), this.prefix(node.getLastToken()!)) + ) + ); } visitThisType(node: ts.ThisTypeNode) { - return this.visitUnknown(node); + return this.mapIdentifier(node, 'this'); } visitTypeOperator(node: ts.TypeOperatorNode) { @@ -1393,7 +1422,19 @@ export class JavaScriptParserVisitor { } visitIndexedAccessType(node: ts.IndexedAccessTypeNode) { - return this.visitUnknown(node); + return new J.ArrayAccess( + randomId(), + this.prefix(node), + Markers.EMPTY, + this.convert(node.objectType), + new J.ArrayDimension( + randomId(), + this.prefix(this.findChildNode(node, ts.SyntaxKind.OpenBracketToken)!), + Markers.EMPTY, + this.rightPadded(this.convert(node.indexType), this.suffix(node.indexType)) + ), + this.mapType(node) + ); } visitMappedType(node: ts.MappedTypeNode) { @@ -1401,11 +1442,93 @@ export class JavaScriptParserVisitor { } visitLiteralType(node: ts.LiteralTypeNode) { - return this.visit(node.literal); + return new JS.LiteralType( + randomId(), + this.prefix(node), + Markers.EMPTY, + this.visit(node.literal), + this.mapType(node)! + ); } visitNamedTupleMember(node: ts.NamedTupleMember) { - return this.visitUnknown(node); + if (node.questionToken) { + return new JS.JSVariableDeclarations( + randomId(), + this.prefix(node), + Markers.EMPTY, + [], + [], + this.mapTypeInfo(node), + null, + [this.rightPadded( + new JS.JSVariableDeclarations.JSNamedVariable( + randomId(), + this.prefix(node.name), + Markers.EMPTY, + this.getOptionalUnary(node), + [], + null, + this.mapVariableType(node) + ), + this.suffix(node.name) + )] + ); + } + + if (node.dotDotDotToken) { + return new JS.JSVariableDeclarations( + randomId(), + this.prefix(node), + Markers.EMPTY, + [], + [], + this.mapTypeInfo(node), + null, + [this.rightPadded( + new JS.JSVariableDeclarations.JSNamedVariable( + randomId(), + Space.EMPTY, + Markers.EMPTY, + new JS.Unary( + randomId(), + Space.EMPTY, + Markers.EMPTY, + this.leftPadded(Space.EMPTY, JS.Unary.Type.Spread), + this.visit(node.name), + this.mapType(node) + ), + [], + null, + this.mapVariableType(node) + ), + this.suffix(node.name) + )] + ); + } + + return new J.VariableDeclarations( + randomId(), + this.prefix(node), + Markers.EMPTY, + [], + [], + this.mapTypeInfo(node), + null, + [], + [this.rightPadded( + new J.VariableDeclarations.NamedVariable( + randomId(), + this.prefix(node.name), + Markers.EMPTY, + this.visit(node.name), + [], + null, + this.mapVariableType(node) + ), + this.suffix(node.name) + )] + ); } visitTemplateLiteralType(node: ts.TemplateLiteralTypeNode) { @@ -1430,7 +1553,27 @@ export class JavaScriptParserVisitor { } visitImportType(node: ts.ImportTypeNode) { - return this.visitUnknown(node); + return new JS.ImportType( + randomId(), + this.prefix(node), + Markers.EMPTY, + node.isTypeOf ? this.rightPadded(true, this.suffix(this.findChildNode(node, ts.SyntaxKind.TypeOfKeyword)!)) : this.rightPadded(false, Space.EMPTY), + new J.ParenthesizedTypeTree( + randomId(), + this.suffix(this.findChildNode(node, ts.SyntaxKind.ImportKeyword)!), + Markers.EMPTY, + [], + new J.Parentheses( + randomId(), + Space.EMPTY, + Markers.EMPTY, + this.rightPadded(this.visit(node.argument), this.suffix(node.argument)) + ) + ), + node.qualifier ? this.leftPadded(this.prefix(this.findChildNode(node, ts.SyntaxKind.DotToken)!), this.visit(node.qualifier)): null, + node.typeArguments ? this.mapTypeArguments(this.suffix(node.qualifier!), node.typeArguments) : null, + this.mapType(node) + ); } visitObjectBindingPattern(node: ts.ObjectBindingPattern) { @@ -2131,7 +2274,14 @@ export class JavaScriptParserVisitor { } visitSatisfiesExpression(node: ts.SatisfiesExpression) { - return this.visitUnknown(node); + return new JS.SatisfiesExpression( + randomId(), + this.prefix(node), + Markers.EMPTY, + this.visit(node.expression), + this.leftPadded(this.suffix(node.expression), this.visit(node.type)), + this.mapType(node) + ); } visitTemplateSpan(node: ts.TemplateSpan) { @@ -3367,7 +3517,7 @@ export class JavaScriptParserVisitor { return new J.Empty(randomId(), prefix, markers ?? Markers.EMPTY); } - private getOptionalUnary(node: ts.MethodSignature | ts.MethodDeclaration | ts.ParameterDeclaration | ts.PropertySignature | ts.PropertyDeclaration) { + private getOptionalUnary(node: ts.MethodSignature | ts.MethodDeclaration | ts.ParameterDeclaration | ts.PropertySignature | ts.PropertyDeclaration | ts.NamedTupleMember) { return new JS.Unary( randomId(), Space.EMPTY, diff --git a/openrewrite/src/javascript/remote/receiver.ts b/openrewrite/src/javascript/remote/receiver.ts index 5df47b72..0b771462 100644 --- a/openrewrite/src/javascript/remote/receiver.ts +++ b/openrewrite/src/javascript/remote/receiver.ts @@ -2,7 +2,7 @@ import * as extensions from "./remote_extensions"; import {Checksum, Cursor, FileAttributes, ListUtils, Tree} from '../../core'; import {DetailsReceiver, Receiver, ReceiverContext, ReceiverFactory, ValueType} from '@openrewrite/rewrite-remote'; import {JavaScriptVisitor} from '..'; -import {JS, JsLeftPadded, JsRightPadded, JsContainer, JsSpace, CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, JsImport, JsImportSpecifier, JsBinary, ObjectBindingDeclarations, PropertyAssignment, ScopedVariableDeclarations, StatementExpression, TaggedTemplateExpression, TemplateExpression, Tuple, TypeDeclaration, TypeOf, TypeQuery, TypeOperator, Unary, Union, Intersection, Void, Yield, TypeInfo, JSVariableDeclarations, JSMethodDeclaration, JSForOfLoop, JSForInLoop, JSForInOfLoopControl, NamespaceDeclaration, FunctionDeclaration, TypeLiteral, IndexSignatureDeclaration, ArrayBindingPattern, BindingElement} from '../tree'; +import {JS, JsLeftPadded, JsRightPadded, JsContainer, JsSpace, CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, InferType, ImportType, JsImport, JsImportSpecifier, JsBinary, LiteralType, ObjectBindingDeclarations, PropertyAssignment, SatisfiesExpression, ScopedVariableDeclarations, StatementExpression, TaggedTemplateExpression, TemplateExpression, Tuple, TypeDeclaration, TypeOf, TypeQuery, TypeOperator, TypePredicate, Unary, Union, Intersection, Void, Yield, TypeInfo, JSVariableDeclarations, JSMethodDeclaration, JSForOfLoop, JSForInLoop, JSForInOfLoopControl, NamespaceDeclaration, FunctionDeclaration, TypeLiteral, IndexSignatureDeclaration, ArrayBindingPattern, BindingElement} from '../tree'; import {Expression, J, JContainer, JLeftPadded, JRightPadded, NameTree, Space, Statement, TypeTree, TypedTree} from "../../java"; import * as Java from "../../java/tree"; @@ -144,6 +144,27 @@ class Visitor extends JavaScriptVisitor { return functionType; } + public visitInferType(inferType: InferType, ctx: ReceiverContext): J { + inferType = inferType.withId(ctx.receiveValue(inferType.id, ValueType.UUID)!); + inferType = inferType.withPrefix(ctx.receiveNode(inferType.prefix, receiveSpace)!); + inferType = inferType.withMarkers(ctx.receiveNode(inferType.markers, ctx.receiveMarkers)!); + inferType = inferType.padding.withTypeParameter(ctx.receiveNode(inferType.padding.typeParameter, receiveLeftPaddedTree)!); + inferType = inferType.withType(ctx.receiveValue(inferType.type, ValueType.Object)); + return inferType; + } + + public visitImportType(importType: ImportType, ctx: ReceiverContext): J { + importType = importType.withId(ctx.receiveValue(importType.id, ValueType.UUID)!); + importType = importType.withPrefix(ctx.receiveNode(importType.prefix, receiveSpace)!); + importType = importType.withMarkers(ctx.receiveNode(importType.markers, ctx.receiveMarkers)!); + importType = importType.padding.withHasTypeof(ctx.receiveNode(importType.padding.hasTypeof, rightPaddedValueReceiver(ValueType.Primitive))!); + importType = importType.withImportArgument(ctx.receiveNode(importType.importArgument, ctx.receiveTree)!); + importType = importType.padding.withQualifier(ctx.receiveNode(importType.padding.qualifier, receiveLeftPaddedTree)); + importType = importType.padding.withTypeArguments(ctx.receiveNode(importType.padding.typeArguments, receiveContainer)); + importType = importType.withType(ctx.receiveValue(importType.type, ValueType.Object)); + return importType; + } + public visitJsImport(jsImport: JsImport, ctx: ReceiverContext): J { jsImport = jsImport.withId(ctx.receiveValue(jsImport.id, ValueType.UUID)!); jsImport = jsImport.withPrefix(ctx.receiveNode(jsImport.prefix, receiveSpace)!); @@ -178,6 +199,15 @@ class Visitor extends JavaScriptVisitor { return jsBinary; } + public visitLiteralType(literalType: LiteralType, ctx: ReceiverContext): J { + literalType = literalType.withId(ctx.receiveValue(literalType.id, ValueType.UUID)!); + literalType = literalType.withPrefix(ctx.receiveNode(literalType.prefix, receiveSpace)!); + literalType = literalType.withMarkers(ctx.receiveNode(literalType.markers, ctx.receiveMarkers)!); + literalType = literalType.withLiteral(ctx.receiveNode(literalType.literal, ctx.receiveTree)!); + literalType = literalType.withType(ctx.receiveValue(literalType.type, ValueType.Object)!); + return literalType; + } + public visitObjectBindingDeclarations(objectBindingDeclarations: ObjectBindingDeclarations, ctx: ReceiverContext): J { objectBindingDeclarations = objectBindingDeclarations.withId(ctx.receiveValue(objectBindingDeclarations.id, ValueType.UUID)!); objectBindingDeclarations = objectBindingDeclarations.withPrefix(ctx.receiveNode(objectBindingDeclarations.prefix, receiveSpace)!); @@ -199,6 +229,16 @@ class Visitor extends JavaScriptVisitor { return propertyAssignment; } + public visitSatisfiesExpression(satisfiesExpression: SatisfiesExpression, ctx: ReceiverContext): J { + satisfiesExpression = satisfiesExpression.withId(ctx.receiveValue(satisfiesExpression.id, ValueType.UUID)!); + satisfiesExpression = satisfiesExpression.withPrefix(ctx.receiveNode(satisfiesExpression.prefix, receiveSpace)!); + satisfiesExpression = satisfiesExpression.withMarkers(ctx.receiveNode(satisfiesExpression.markers, ctx.receiveMarkers)!); + satisfiesExpression = satisfiesExpression.withExpression(ctx.receiveNode(satisfiesExpression.expression, ctx.receiveTree)!); + satisfiesExpression = satisfiesExpression.padding.withSatisfiesType(ctx.receiveNode(satisfiesExpression.padding.satisfiesType, receiveLeftPaddedTree)!); + satisfiesExpression = satisfiesExpression.withType(ctx.receiveValue(satisfiesExpression.type, ValueType.Object)); + return satisfiesExpression; + } + public visitScopedVariableDeclarations(scopedVariableDeclarations: ScopedVariableDeclarations, ctx: ReceiverContext): J { scopedVariableDeclarations = scopedVariableDeclarations.withId(ctx.receiveValue(scopedVariableDeclarations.id, ValueType.UUID)!); scopedVariableDeclarations = scopedVariableDeclarations.withPrefix(ctx.receiveNode(scopedVariableDeclarations.prefix, receiveSpace)!); @@ -293,6 +333,17 @@ class Visitor extends JavaScriptVisitor { return typeOperator; } + public visitTypePredicate(typePredicate: TypePredicate, ctx: ReceiverContext): J { + typePredicate = typePredicate.withId(ctx.receiveValue(typePredicate.id, ValueType.UUID)!); + typePredicate = typePredicate.withPrefix(ctx.receiveNode(typePredicate.prefix, receiveSpace)!); + typePredicate = typePredicate.withMarkers(ctx.receiveNode(typePredicate.markers, ctx.receiveMarkers)!); + typePredicate = typePredicate.padding.withAsserts(ctx.receiveNode(typePredicate.padding.asserts, leftPaddedValueReceiver(ValueType.Primitive))!); + typePredicate = typePredicate.withParameterName(ctx.receiveNode(typePredicate.parameterName, ctx.receiveTree)!); + typePredicate = typePredicate.padding.withExpression(ctx.receiveNode(typePredicate.padding.expression, receiveLeftPaddedTree)); + typePredicate = typePredicate.withType(ctx.receiveValue(typePredicate.type, ValueType.Object)); + return typePredicate; + } + public visitJsUnary(unary: Unary, ctx: ReceiverContext): J { unary = unary.withId(ctx.receiveValue(unary.id, ValueType.UUID)!); unary = unary.withPrefix(ctx.receiveNode(unary.prefix, receiveSpace)!); @@ -1278,6 +1329,29 @@ class Factory implements ReceiverFactory { ); } + if (type === "org.openrewrite.javascript.tree.JS$InferType") { + return new InferType( + ctx.receiveValue(null, ValueType.UUID)!, + ctx.receiveNode(null, receiveSpace)!, + ctx.receiveNode(null, ctx.receiveMarkers)!, + ctx.receiveNode>(null, receiveLeftPaddedTree)!, + ctx.receiveValue(null, ValueType.Object) + ); + } + + if (type === "org.openrewrite.javascript.tree.JS$ImportType") { + return new ImportType( + ctx.receiveValue(null, ValueType.UUID)!, + ctx.receiveNode(null, receiveSpace)!, + ctx.receiveNode(null, ctx.receiveMarkers)!, + ctx.receiveNode>(null, rightPaddedValueReceiver(ValueType.Primitive))!, + ctx.receiveNode(null, ctx.receiveTree)!, + ctx.receiveNode>(null, receiveLeftPaddedTree), + ctx.receiveNode>(null, receiveContainer), + ctx.receiveValue(null, ValueType.Object) + ); + } + if (type === "org.openrewrite.javascript.tree.JS$JsImport") { return new JsImport( ctx.receiveValue(null, ValueType.UUID)!, @@ -1315,6 +1389,16 @@ class Factory implements ReceiverFactory { ); } + if (type === "org.openrewrite.javascript.tree.JS$LiteralType") { + return new LiteralType( + ctx.receiveValue(null, ValueType.UUID)!, + ctx.receiveNode(null, receiveSpace)!, + ctx.receiveNode(null, ctx.receiveMarkers)!, + ctx.receiveNode(null, ctx.receiveTree)!, + ctx.receiveValue(null, ValueType.Object)! + ); + } + if (type === "org.openrewrite.javascript.tree.JS$ObjectBindingDeclarations") { return new ObjectBindingDeclarations( ctx.receiveValue(null, ValueType.UUID)!, @@ -1338,6 +1422,17 @@ class Factory implements ReceiverFactory { ); } + if (type === "org.openrewrite.javascript.tree.JS$SatisfiesExpression") { + return new SatisfiesExpression( + ctx.receiveValue(null, ValueType.UUID)!, + ctx.receiveNode(null, receiveSpace)!, + ctx.receiveNode(null, ctx.receiveMarkers)!, + ctx.receiveNode(null, ctx.receiveTree)!, + ctx.receiveNode>(null, receiveLeftPaddedTree)!, + ctx.receiveValue(null, ValueType.Object) + ); + } + if (type === "org.openrewrite.javascript.tree.JS$ScopedVariableDeclarations") { return new ScopedVariableDeclarations( ctx.receiveValue(null, ValueType.UUID)!, @@ -1442,6 +1537,18 @@ class Factory implements ReceiverFactory { ); } + if (type === "org.openrewrite.javascript.tree.JS$TypePredicate") { + return new TypePredicate( + ctx.receiveValue(null, ValueType.UUID)!, + ctx.receiveNode(null, receiveSpace)!, + ctx.receiveNode(null, ctx.receiveMarkers)!, + ctx.receiveNode>(null, leftPaddedValueReceiver(ValueType.Primitive))!, + ctx.receiveNode(null, ctx.receiveTree)!, + ctx.receiveNode>(null, receiveLeftPaddedTree), + ctx.receiveValue(null, ValueType.Object) + ); + } + if (type === "org.openrewrite.javascript.tree.JS$Unary") { return new Unary( ctx.receiveValue(null, ValueType.UUID)!, diff --git a/openrewrite/src/javascript/remote/sender.ts b/openrewrite/src/javascript/remote/sender.ts index 056b86bb..cc365e0e 100644 --- a/openrewrite/src/javascript/remote/sender.ts +++ b/openrewrite/src/javascript/remote/sender.ts @@ -2,7 +2,7 @@ import * as extensions from "./remote_extensions"; import {Cursor, ListUtils, Tree} from '../../core'; import {Sender, SenderContext, ValueType} from '@openrewrite/rewrite-remote'; import {JavaScriptVisitor} from '..'; -import {JS, JsLeftPadded, JsRightPadded, JsContainer, JsSpace, CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, JsImport, JsImportSpecifier, JsBinary, ObjectBindingDeclarations, PropertyAssignment, ScopedVariableDeclarations, StatementExpression, TaggedTemplateExpression, TemplateExpression, Tuple, TypeDeclaration, TypeOf, TypeQuery, TypeOperator, Unary, Union, Intersection, Void, Yield, TypeInfo, JSVariableDeclarations, JSMethodDeclaration, JSForOfLoop, JSForInLoop, JSForInOfLoopControl, NamespaceDeclaration, FunctionDeclaration, TypeLiteral, IndexSignatureDeclaration, ArrayBindingPattern, BindingElement} from '../tree'; +import {JS, JsLeftPadded, JsRightPadded, JsContainer, JsSpace, CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, InferType, ImportType, JsImport, JsImportSpecifier, JsBinary, LiteralType, ObjectBindingDeclarations, PropertyAssignment, SatisfiesExpression, ScopedVariableDeclarations, StatementExpression, TaggedTemplateExpression, TemplateExpression, Tuple, TypeDeclaration, TypeOf, TypeQuery, TypeOperator, TypePredicate, Unary, Union, Intersection, Void, Yield, TypeInfo, JSVariableDeclarations, JSMethodDeclaration, JSForOfLoop, JSForInLoop, JSForInOfLoopControl, NamespaceDeclaration, FunctionDeclaration, TypeLiteral, IndexSignatureDeclaration, ArrayBindingPattern, BindingElement} from '../tree'; import {Expression, J, JContainer, JLeftPadded, JRightPadded, Space, Statement} from "../../java"; import * as Java from "../../java/tree"; @@ -139,6 +139,27 @@ class Visitor extends JavaScriptVisitor { return functionType; } + public visitInferType(inferType: InferType, ctx: SenderContext): J { + ctx.sendValue(inferType, v => v.id, ValueType.UUID); + ctx.sendNode(inferType, v => v.prefix, Visitor.sendSpace); + ctx.sendNode(inferType, v => v.markers, ctx.sendMarkers); + ctx.sendNode(inferType, v => v.padding.typeParameter, Visitor.sendLeftPadded(ValueType.Tree)); + ctx.sendTypedValue(inferType, v => v.type, ValueType.Object); + return inferType; + } + + public visitImportType(importType: ImportType, ctx: SenderContext): J { + ctx.sendValue(importType, v => v.id, ValueType.UUID); + ctx.sendNode(importType, v => v.prefix, Visitor.sendSpace); + ctx.sendNode(importType, v => v.markers, ctx.sendMarkers); + ctx.sendNode(importType, v => v.padding.hasTypeof, Visitor.sendRightPadded(ValueType.Primitive)); + ctx.sendNode(importType, v => v.importArgument, ctx.sendTree); + ctx.sendNode(importType, v => v.padding.qualifier, Visitor.sendLeftPadded(ValueType.Tree)); + ctx.sendNode(importType, v => v.padding.typeArguments, Visitor.sendContainer(ValueType.Tree)); + ctx.sendTypedValue(importType, v => v.type, ValueType.Object); + return importType; + } + public visitJsImport(jsImport: JsImport, ctx: SenderContext): J { ctx.sendValue(jsImport, v => v.id, ValueType.UUID); ctx.sendNode(jsImport, v => v.prefix, Visitor.sendSpace); @@ -173,6 +194,15 @@ class Visitor extends JavaScriptVisitor { return jsBinary; } + public visitLiteralType(literalType: LiteralType, ctx: SenderContext): J { + ctx.sendValue(literalType, v => v.id, ValueType.UUID); + ctx.sendNode(literalType, v => v.prefix, Visitor.sendSpace); + ctx.sendNode(literalType, v => v.markers, ctx.sendMarkers); + ctx.sendNode(literalType, v => v.literal, ctx.sendTree); + ctx.sendTypedValue(literalType, v => v.type, ValueType.Object); + return literalType; + } + public visitObjectBindingDeclarations(objectBindingDeclarations: ObjectBindingDeclarations, ctx: SenderContext): J { ctx.sendValue(objectBindingDeclarations, v => v.id, ValueType.UUID); ctx.sendNode(objectBindingDeclarations, v => v.prefix, Visitor.sendSpace); @@ -194,6 +224,16 @@ class Visitor extends JavaScriptVisitor { return propertyAssignment; } + public visitSatisfiesExpression(satisfiesExpression: SatisfiesExpression, ctx: SenderContext): J { + ctx.sendValue(satisfiesExpression, v => v.id, ValueType.UUID); + ctx.sendNode(satisfiesExpression, v => v.prefix, Visitor.sendSpace); + ctx.sendNode(satisfiesExpression, v => v.markers, ctx.sendMarkers); + ctx.sendNode(satisfiesExpression, v => v.expression, ctx.sendTree); + ctx.sendNode(satisfiesExpression, v => v.padding.satisfiesType, Visitor.sendLeftPadded(ValueType.Tree)); + ctx.sendTypedValue(satisfiesExpression, v => v.type, ValueType.Object); + return satisfiesExpression; + } + public visitScopedVariableDeclarations(scopedVariableDeclarations: ScopedVariableDeclarations, ctx: SenderContext): J { ctx.sendValue(scopedVariableDeclarations, v => v.id, ValueType.UUID); ctx.sendNode(scopedVariableDeclarations, v => v.prefix, Visitor.sendSpace); @@ -288,6 +328,17 @@ class Visitor extends JavaScriptVisitor { return typeOperator; } + public visitTypePredicate(typePredicate: TypePredicate, ctx: SenderContext): J { + ctx.sendValue(typePredicate, v => v.id, ValueType.UUID); + ctx.sendNode(typePredicate, v => v.prefix, Visitor.sendSpace); + ctx.sendNode(typePredicate, v => v.markers, ctx.sendMarkers); + ctx.sendNode(typePredicate, v => v.padding.asserts, Visitor.sendLeftPadded(ValueType.Primitive)); + ctx.sendNode(typePredicate, v => v.parameterName, ctx.sendTree); + ctx.sendNode(typePredicate, v => v.padding.expression, Visitor.sendLeftPadded(ValueType.Tree)); + ctx.sendTypedValue(typePredicate, v => v.type, ValueType.Object); + return typePredicate; + } + public visitJsUnary(unary: Unary, ctx: SenderContext): J { ctx.sendValue(unary, v => v.id, ValueType.UUID); ctx.sendNode(unary, v => v.prefix, Visitor.sendSpace); diff --git a/openrewrite/src/javascript/tree/support_types.ts b/openrewrite/src/javascript/tree/support_types.ts index 5bc2ab19..cb606910 100644 --- a/openrewrite/src/javascript/tree/support_types.ts +++ b/openrewrite/src/javascript/tree/support_types.ts @@ -241,6 +241,11 @@ export namespace JsSpace { TEMPLATE_EXPRESSION_TEMPLATE_SPAN_PREFIX, TAGGED_TEMPLATE_EXPRESSION_PREFIX, CONDITIONAL_TYPE_PREFIX, + INFER_TYPE_PREFIX, + TYPE_PREDICATE_PREFIX, + LITERAL_TYPE_PREFIX, + SATISFIES_EXPRESSION_PREFIX, + IMPORT_TYPE_PREFIX, } } export namespace JsLeftPadded { @@ -266,6 +271,11 @@ export namespace JsLeftPadded { INDEX_SIGNATURE_DECLARATION_TYPE_EXPRESSION, JSFOR_OF_LOOP_AWAIT, BINDING_ELEMENT_INITIALIZER, + INFER_TYPE_TYPE_PARAMETER, + TYPE_PREDICATE_ASSERTS, + TYPE_PREDICATE_EXPRESSION, + SATISFIES_EXPRESSION_SATISFIES_TYPE, + IMPORT_TYPE_QUALIFIER, } } export namespace JsRightPadded { @@ -289,6 +299,7 @@ export namespace JsRightPadded { FUNCTION_TYPE_CONSTRUCTOR_TYPE, TEMPLATE_EXPRESSION_TEMPLATE_SPANS, TAGGED_TEMPLATE_EXPRESSION_TAG, + IMPORT_TYPE_HAS_TYPEOF, } } export namespace JsContainer { @@ -307,5 +318,6 @@ export namespace JsContainer { EXPRESSION_WITH_TYPE_ARGUMENTS_TYPE_ARGUMENTS, TAGGED_TEMPLATE_EXPRESSION_TYPE_ARGUMENTS, CONDITIONAL_TYPE_CONDITION, + IMPORT_TYPE_TYPE_ARGUMENTS, } } diff --git a/openrewrite/src/javascript/tree/tree.ts b/openrewrite/src/javascript/tree/tree.ts index 55021b8b..71ef8c51 100644 --- a/openrewrite/src/javascript/tree/tree.ts +++ b/openrewrite/src/javascript/tree/tree.ts @@ -1010,6 +1010,209 @@ export class FunctionType extends JSMixin(Object) implements Expression, TypeTre } +@LstType("org.openrewrite.javascript.tree.JS$InferType") +export class InferType extends JSMixin(Object) implements TypeTree, Expression { + public constructor(id: UUID, prefix: Space, markers: Markers, typeParameter: JLeftPadded, _type: JavaType | null) { + super(); + this._id = id; + this._prefix = prefix; + this._markers = markers; + this._typeParameter = typeParameter; + this._type = _type; + } + + private readonly _id: UUID; + + public get id(): UUID { + return this._id; + } + + public withId(id: UUID): InferType { + return id === this._id ? this : new InferType(id, this._prefix, this._markers, this._typeParameter, this._type); + } + + private readonly _prefix: Space; + + public get prefix(): Space { + return this._prefix; + } + + public withPrefix(prefix: Space): InferType { + return prefix === this._prefix ? this : new InferType(this._id, prefix, this._markers, this._typeParameter, this._type); + } + + private readonly _markers: Markers; + + public get markers(): Markers { + return this._markers; + } + + public withMarkers(markers: Markers): InferType { + return markers === this._markers ? this : new InferType(this._id, this._prefix, markers, this._typeParameter, this._type); + } + + private readonly _typeParameter: JLeftPadded; + + public get typeParameter(): J { + return this._typeParameter.element; + } + + public withTypeParameter(typeParameter: J): InferType { + return this.padding.withTypeParameter(this._typeParameter.withElement(typeParameter)); + } + + private readonly _type: JavaType | null; + + public get type(): JavaType | null { + return this._type; + } + + public withType(_type: JavaType | null): InferType { + return _type === this._type ? this : new InferType(this._id, this._prefix, this._markers, this._typeParameter, _type); + } + + public acceptJavaScript

(v: JavaScriptVisitor

, p: P): J | null { + return v.visitInferType(this, p); + } + + get padding() { + const t = this; + return new class { + public get typeParameter(): JLeftPadded { + return t._typeParameter; + } + public withTypeParameter(typeParameter: JLeftPadded): InferType { + return t._typeParameter === typeParameter ? t : new InferType(t._id, t._prefix, t._markers, typeParameter, t._type); + } + } + } + +} + +@LstType("org.openrewrite.javascript.tree.JS$ImportType") +export class ImportType extends JSMixin(Object) implements Expression, TypeTree { + public constructor(id: UUID, prefix: Space, markers: Markers, hasTypeof: JRightPadded, importArgument: Java.ParenthesizedTypeTree, qualifier: JLeftPadded | null, typeArguments: JContainer | null, _type: JavaType | null) { + super(); + this._id = id; + this._prefix = prefix; + this._markers = markers; + this._hasTypeof = hasTypeof; + this._importArgument = importArgument; + this._qualifier = qualifier; + this._typeArguments = typeArguments; + this._type = _type; + } + + private readonly _id: UUID; + + public get id(): UUID { + return this._id; + } + + public withId(id: UUID): ImportType { + return id === this._id ? this : new ImportType(id, this._prefix, this._markers, this._hasTypeof, this._importArgument, this._qualifier, this._typeArguments, this._type); + } + + private readonly _prefix: Space; + + public get prefix(): Space { + return this._prefix; + } + + public withPrefix(prefix: Space): ImportType { + return prefix === this._prefix ? this : new ImportType(this._id, prefix, this._markers, this._hasTypeof, this._importArgument, this._qualifier, this._typeArguments, this._type); + } + + private readonly _markers: Markers; + + public get markers(): Markers { + return this._markers; + } + + public withMarkers(markers: Markers): ImportType { + return markers === this._markers ? this : new ImportType(this._id, this._prefix, markers, this._hasTypeof, this._importArgument, this._qualifier, this._typeArguments, this._type); + } + + private readonly _hasTypeof: JRightPadded; + + public get hasTypeof(): boolean { + return this._hasTypeof.element; + } + + public withHasTypeof(hasTypeof: boolean): ImportType { + return this.padding.withHasTypeof(this._hasTypeof.withElement(hasTypeof)); + } + + private readonly _importArgument: Java.ParenthesizedTypeTree; + + public get importArgument(): Java.ParenthesizedTypeTree { + return this._importArgument; + } + + public withImportArgument(importArgument: Java.ParenthesizedTypeTree): ImportType { + return importArgument === this._importArgument ? this : new ImportType(this._id, this._prefix, this._markers, this._hasTypeof, importArgument, this._qualifier, this._typeArguments, this._type); + } + + private readonly _qualifier: JLeftPadded | null; + + public get qualifier(): Expression | null { + return this._qualifier === null ? null : this._qualifier.element; + } + + public withQualifier(qualifier: Expression | null): ImportType { + return this.padding.withQualifier(JLeftPadded.withElement(this._qualifier, qualifier)); + } + + private readonly _typeArguments: JContainer | null; + + public get typeArguments(): Expression[] | null { + return this._typeArguments === null ? null : this._typeArguments.elements; + } + + public withTypeArguments(typeArguments: Expression[] | null): ImportType { + return this.padding.withTypeArguments(JContainer.withElementsNullable(this._typeArguments, typeArguments)); + } + + private readonly _type: JavaType | null; + + public get type(): JavaType | null { + return this._type; + } + + public withType(_type: JavaType | null): ImportType { + return _type === this._type ? this : new ImportType(this._id, this._prefix, this._markers, this._hasTypeof, this._importArgument, this._qualifier, this._typeArguments, _type); + } + + public acceptJavaScript

(v: JavaScriptVisitor

, p: P): J | null { + return v.visitImportType(this, p); + } + + get padding() { + const t = this; + return new class { + public get hasTypeof(): JRightPadded { + return t._hasTypeof; + } + public withHasTypeof(hasTypeof: JRightPadded): ImportType { + return t._hasTypeof === hasTypeof ? t : new ImportType(t._id, t._prefix, t._markers, hasTypeof, t._importArgument, t._qualifier, t._typeArguments, t._type); + } + public get qualifier(): JLeftPadded | null { + return t._qualifier; + } + public withQualifier(qualifier: JLeftPadded | null): ImportType { + return t._qualifier === qualifier ? t : new ImportType(t._id, t._prefix, t._markers, t._hasTypeof, t._importArgument, qualifier, t._typeArguments, t._type); + } + public get typeArguments(): JContainer | null { + return t._typeArguments; + } + public withTypeArguments(typeArguments: JContainer | null): ImportType { + return t._typeArguments === typeArguments ? t : new ImportType(t._id, t._prefix, t._markers, t._hasTypeof, t._importArgument, t._qualifier, typeArguments, t._type); + } + } + } + +} + @LstType("org.openrewrite.javascript.tree.JS$JsImport") export class JsImport extends JSMixin(Object) implements Statement { public constructor(id: UUID, prefix: Space, markers: Markers, name: JRightPadded | null, importType: JLeftPadded, imports: JContainer | null, _from: Space | null, target: Java.Literal | null, initializer: JLeftPadded | null) { @@ -1354,6 +1557,73 @@ export namespace JsBinary { } +@LstType("org.openrewrite.javascript.tree.JS$LiteralType") +export class LiteralType extends JSMixin(Object) implements Expression, TypeTree { + public constructor(id: UUID, prefix: Space, markers: Markers, literal: Expression, _type: JavaType) { + super(); + this._id = id; + this._prefix = prefix; + this._markers = markers; + this._literal = literal; + this._type = _type; + } + + private readonly _id: UUID; + + public get id(): UUID { + return this._id; + } + + public withId(id: UUID): LiteralType { + return id === this._id ? this : new LiteralType(id, this._prefix, this._markers, this._literal, this._type); + } + + private readonly _prefix: Space; + + public get prefix(): Space { + return this._prefix; + } + + public withPrefix(prefix: Space): LiteralType { + return prefix === this._prefix ? this : new LiteralType(this._id, prefix, this._markers, this._literal, this._type); + } + + private readonly _markers: Markers; + + public get markers(): Markers { + return this._markers; + } + + public withMarkers(markers: Markers): LiteralType { + return markers === this._markers ? this : new LiteralType(this._id, this._prefix, markers, this._literal, this._type); + } + + private readonly _literal: Expression; + + public get literal(): Expression { + return this._literal; + } + + public withLiteral(literal: Expression): LiteralType { + return literal === this._literal ? this : new LiteralType(this._id, this._prefix, this._markers, literal, this._type); + } + + private readonly _type: JavaType; + + public get type(): JavaType { + return this._type; + } + + public withType(_type: JavaType): LiteralType { + return _type === this._type ? this : new LiteralType(this._id, this._prefix, this._markers, this._literal, _type); + } + + public acceptJavaScript

(v: JavaScriptVisitor

, p: P): J | null { + return v.visitLiteralType(this, p); + } + +} + @LstType("org.openrewrite.javascript.tree.JS$ObjectBindingDeclarations") export class ObjectBindingDeclarations extends JSMixin(Object) implements Expression, TypedTree { public constructor(id: UUID, prefix: Space, markers: Markers, leadingAnnotations: Java.Annotation[], modifiers: Java.Modifier[], typeExpression: TypeTree | null, bindings: JContainer, initializer: JLeftPadded | null) { @@ -1567,6 +1837,96 @@ export class PropertyAssignment extends JSMixin(Object) implements Statement, Ty } +@LstType("org.openrewrite.javascript.tree.JS$SatisfiesExpression") +export class SatisfiesExpression extends JSMixin(Object) implements Expression { + public constructor(id: UUID, prefix: Space, markers: Markers, expression: J, satisfiesType: JLeftPadded, _type: JavaType | null) { + super(); + this._id = id; + this._prefix = prefix; + this._markers = markers; + this._expression = expression; + this._satisfiesType = satisfiesType; + this._type = _type; + } + + private readonly _id: UUID; + + public get id(): UUID { + return this._id; + } + + public withId(id: UUID): SatisfiesExpression { + return id === this._id ? this : new SatisfiesExpression(id, this._prefix, this._markers, this._expression, this._satisfiesType, this._type); + } + + private readonly _prefix: Space; + + public get prefix(): Space { + return this._prefix; + } + + public withPrefix(prefix: Space): SatisfiesExpression { + return prefix === this._prefix ? this : new SatisfiesExpression(this._id, prefix, this._markers, this._expression, this._satisfiesType, this._type); + } + + private readonly _markers: Markers; + + public get markers(): Markers { + return this._markers; + } + + public withMarkers(markers: Markers): SatisfiesExpression { + return markers === this._markers ? this : new SatisfiesExpression(this._id, this._prefix, markers, this._expression, this._satisfiesType, this._type); + } + + private readonly _expression: J; + + public get expression(): J { + return this._expression; + } + + public withExpression(expression: J): SatisfiesExpression { + return expression === this._expression ? this : new SatisfiesExpression(this._id, this._prefix, this._markers, expression, this._satisfiesType, this._type); + } + + private readonly _satisfiesType: JLeftPadded; + + public get satisfiesType(): Expression { + return this._satisfiesType.element; + } + + public withSatisfiesType(satisfiesType: Expression): SatisfiesExpression { + return this.padding.withSatisfiesType(this._satisfiesType.withElement(satisfiesType)); + } + + private readonly _type: JavaType | null; + + public get type(): JavaType | null { + return this._type; + } + + public withType(_type: JavaType | null): SatisfiesExpression { + return _type === this._type ? this : new SatisfiesExpression(this._id, this._prefix, this._markers, this._expression, this._satisfiesType, _type); + } + + public acceptJavaScript

(v: JavaScriptVisitor

, p: P): J | null { + return v.visitSatisfiesExpression(this, p); + } + + get padding() { + const t = this; + return new class { + public get satisfiesType(): JLeftPadded { + return t._satisfiesType; + } + public withSatisfiesType(satisfiesType: JLeftPadded): SatisfiesExpression { + return t._satisfiesType === satisfiesType ? t : new SatisfiesExpression(t._id, t._prefix, t._markers, t._expression, satisfiesType, t._type); + } + } + } + +} + @LstType("org.openrewrite.javascript.tree.JS$ScopedVariableDeclarations") export class ScopedVariableDeclarations extends JSMixin(Object) implements Statement { public constructor(id: UUID, prefix: Space, markers: Markers, modifiers: Java.Modifier[], scope: JLeftPadded | null, variables: JRightPadded[]) { @@ -2367,6 +2727,113 @@ export namespace TypeOperator { } +@LstType("org.openrewrite.javascript.tree.JS$TypePredicate") +export class TypePredicate extends JSMixin(Object) implements Expression, TypeTree { + public constructor(id: UUID, prefix: Space, markers: Markers, asserts: JLeftPadded, parameterName: Java.Identifier, expression: JLeftPadded | null, _type: JavaType | null) { + super(); + this._id = id; + this._prefix = prefix; + this._markers = markers; + this._asserts = asserts; + this._parameterName = parameterName; + this._expression = expression; + this._type = _type; + } + + private readonly _id: UUID; + + public get id(): UUID { + return this._id; + } + + public withId(id: UUID): TypePredicate { + return id === this._id ? this : new TypePredicate(id, this._prefix, this._markers, this._asserts, this._parameterName, this._expression, this._type); + } + + private readonly _prefix: Space; + + public get prefix(): Space { + return this._prefix; + } + + public withPrefix(prefix: Space): TypePredicate { + return prefix === this._prefix ? this : new TypePredicate(this._id, prefix, this._markers, this._asserts, this._parameterName, this._expression, this._type); + } + + private readonly _markers: Markers; + + public get markers(): Markers { + return this._markers; + } + + public withMarkers(markers: Markers): TypePredicate { + return markers === this._markers ? this : new TypePredicate(this._id, this._prefix, markers, this._asserts, this._parameterName, this._expression, this._type); + } + + private readonly _asserts: JLeftPadded; + + public get asserts(): boolean { + return this._asserts.element; + } + + public withAsserts(asserts: boolean): TypePredicate { + return this.padding.withAsserts(this._asserts.withElement(asserts)); + } + + private readonly _parameterName: Java.Identifier; + + public get parameterName(): Java.Identifier { + return this._parameterName; + } + + public withParameterName(parameterName: Java.Identifier): TypePredicate { + return parameterName === this._parameterName ? this : new TypePredicate(this._id, this._prefix, this._markers, this._asserts, parameterName, this._expression, this._type); + } + + private readonly _expression: JLeftPadded | null; + + public get expression(): Expression | null { + return this._expression === null ? null : this._expression.element; + } + + public withExpression(expression: Expression | null): TypePredicate { + return this.padding.withExpression(JLeftPadded.withElement(this._expression, expression)); + } + + private readonly _type: JavaType | null; + + public get type(): JavaType | null { + return this._type; + } + + public withType(_type: JavaType | null): TypePredicate { + return _type === this._type ? this : new TypePredicate(this._id, this._prefix, this._markers, this._asserts, this._parameterName, this._expression, _type); + } + + public acceptJavaScript

(v: JavaScriptVisitor

, p: P): J | null { + return v.visitTypePredicate(this, p); + } + + get padding() { + const t = this; + return new class { + public get asserts(): JLeftPadded { + return t._asserts; + } + public withAsserts(asserts: JLeftPadded): TypePredicate { + return t._asserts === asserts ? t : new TypePredicate(t._id, t._prefix, t._markers, asserts, t._parameterName, t._expression, t._type); + } + public get expression(): JLeftPadded | null { + return t._expression; + } + public withExpression(expression: JLeftPadded | null): TypePredicate { + return t._expression === expression ? t : new TypePredicate(t._id, t._prefix, t._markers, t._asserts, t._parameterName, expression, t._type); + } + } + } + +} + @LstType("org.openrewrite.javascript.tree.JS$Unary") export class Unary extends JSMixin(Object) implements Statement, Expression, TypedTree { public constructor(id: UUID, prefix: Space, markers: Markers, operator: JLeftPadded, expression: Expression, _type: JavaType | null) { diff --git a/openrewrite/src/javascript/visitor.ts b/openrewrite/src/javascript/visitor.ts index fad3e942..1749579d 100644 --- a/openrewrite/src/javascript/visitor.ts +++ b/openrewrite/src/javascript/visitor.ts @@ -1,7 +1,7 @@ import * as extensions from "./extensions"; import {ListUtils, SourceFile, Tree, TreeVisitor} from "../core"; import {JS, isJavaScript, JsLeftPadded, JsRightPadded, JsContainer, JsSpace} from "./tree"; -import {CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, JsImport, JsImportSpecifier, JsBinary, ObjectBindingDeclarations, PropertyAssignment, ScopedVariableDeclarations, StatementExpression, TaggedTemplateExpression, TemplateExpression, Tuple, TypeDeclaration, TypeOf, TypeQuery, TypeOperator, Unary, Union, Intersection, Void, Yield, TypeInfo, JSVariableDeclarations, JSMethodDeclaration, JSForOfLoop, JSForInLoop, JSForInOfLoopControl, NamespaceDeclaration, FunctionDeclaration, TypeLiteral, IndexSignatureDeclaration, ArrayBindingPattern, BindingElement} from "./tree"; +import {CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, InferType, ImportType, JsImport, JsImportSpecifier, JsBinary, LiteralType, ObjectBindingDeclarations, PropertyAssignment, SatisfiesExpression, ScopedVariableDeclarations, StatementExpression, TaggedTemplateExpression, TemplateExpression, Tuple, TypeDeclaration, TypeOf, TypeQuery, TypeOperator, TypePredicate, Unary, Union, Intersection, Void, Yield, TypeInfo, JSVariableDeclarations, JSMethodDeclaration, JSForOfLoop, JSForInLoop, JSForInOfLoopControl, NamespaceDeclaration, FunctionDeclaration, TypeLiteral, IndexSignatureDeclaration, ArrayBindingPattern, BindingElement} from "./tree"; import {Expression, J, JContainer, JLeftPadded, JRightPadded, Space, Statement} from "../java/tree"; import {JavaVisitor} from "../java"; import * as Java from "../java/tree"; @@ -171,6 +171,35 @@ export class JavaScriptVisitor

extends JavaVisitor

{ return functionType; } + public visitInferType(inferType: InferType, p: P): J | null { + inferType = inferType.withPrefix(this.visitJsSpace(inferType.prefix, JsSpace.Location.INFER_TYPE_PREFIX, p)!); + let tempExpression = this.visitExpression(inferType, p) as Expression; + if (!(tempExpression instanceof InferType)) + { + return tempExpression; + } + inferType = tempExpression as InferType; + inferType = inferType.withMarkers(this.visitMarkers(inferType.markers, p)); + inferType = inferType.padding.withTypeParameter(this.visitJsLeftPadded(inferType.padding.typeParameter, JsLeftPadded.Location.INFER_TYPE_TYPE_PARAMETER, p)!); + return inferType; + } + + public visitImportType(importType: ImportType, p: P): J | null { + importType = importType.withPrefix(this.visitJsSpace(importType.prefix, JsSpace.Location.IMPORT_TYPE_PREFIX, p)!); + let tempExpression = this.visitExpression(importType, p) as Expression; + if (!(tempExpression instanceof ImportType)) + { + return tempExpression; + } + importType = tempExpression as ImportType; + importType = importType.withMarkers(this.visitMarkers(importType.markers, p)); + importType = importType.padding.withHasTypeof(this.visitJsRightPadded(importType.padding.hasTypeof, JsRightPadded.Location.IMPORT_TYPE_HAS_TYPEOF, p)!); + importType = importType.withImportArgument(this.visitAndCast(importType.importArgument, p)!); + importType = importType.padding.withQualifier(this.visitJsLeftPadded(importType.padding.qualifier, JsLeftPadded.Location.IMPORT_TYPE_QUALIFIER, p)); + importType = importType.padding.withTypeArguments(this.visitJsContainer(importType.padding.typeArguments, JsContainer.Location.IMPORT_TYPE_TYPE_ARGUMENTS, p)); + return importType; + } + public visitJsImport(jsImport: JsImport, p: P): J | null { jsImport = jsImport.withPrefix(this.visitJsSpace(jsImport.prefix, JsSpace.Location.JS_IMPORT_PREFIX, p)!); let tempStatement = this.visitStatement(jsImport, p) as Statement; @@ -218,6 +247,19 @@ export class JavaScriptVisitor

extends JavaVisitor

{ return jsBinary; } + public visitLiteralType(literalType: LiteralType, p: P): J | null { + literalType = literalType.withPrefix(this.visitJsSpace(literalType.prefix, JsSpace.Location.LITERAL_TYPE_PREFIX, p)!); + let tempExpression = this.visitExpression(literalType, p) as Expression; + if (!(tempExpression instanceof LiteralType)) + { + return tempExpression; + } + literalType = tempExpression as LiteralType; + literalType = literalType.withMarkers(this.visitMarkers(literalType.markers, p)); + literalType = literalType.withLiteral(this.visitAndCast(literalType.literal, p)!); + return literalType; + } + public visitObjectBindingDeclarations(objectBindingDeclarations: ObjectBindingDeclarations, p: P): J | null { objectBindingDeclarations = objectBindingDeclarations.withPrefix(this.visitJsSpace(objectBindingDeclarations.prefix, JsSpace.Location.OBJECT_BINDING_DECLARATIONS_PREFIX, p)!); let tempExpression = this.visitExpression(objectBindingDeclarations, p) as Expression; @@ -249,6 +291,20 @@ export class JavaScriptVisitor

extends JavaVisitor

{ return propertyAssignment; } + public visitSatisfiesExpression(satisfiesExpression: SatisfiesExpression, p: P): J | null { + satisfiesExpression = satisfiesExpression.withPrefix(this.visitJsSpace(satisfiesExpression.prefix, JsSpace.Location.SATISFIES_EXPRESSION_PREFIX, p)!); + let tempExpression = this.visitExpression(satisfiesExpression, p) as Expression; + if (!(tempExpression instanceof SatisfiesExpression)) + { + return tempExpression; + } + satisfiesExpression = tempExpression as SatisfiesExpression; + satisfiesExpression = satisfiesExpression.withMarkers(this.visitMarkers(satisfiesExpression.markers, p)); + satisfiesExpression = satisfiesExpression.withExpression(this.visitAndCast(satisfiesExpression.expression, p)!); + satisfiesExpression = satisfiesExpression.padding.withSatisfiesType(this.visitJsLeftPadded(satisfiesExpression.padding.satisfiesType, JsLeftPadded.Location.SATISFIES_EXPRESSION_SATISFIES_TYPE, p)!); + return satisfiesExpression; + } + public visitScopedVariableDeclarations(scopedVariableDeclarations: ScopedVariableDeclarations, p: P): J | null { scopedVariableDeclarations = scopedVariableDeclarations.withPrefix(this.visitJsSpace(scopedVariableDeclarations.prefix, JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_PREFIX, p)!); let tempStatement = this.visitStatement(scopedVariableDeclarations, p) as Statement; @@ -386,6 +442,21 @@ export class JavaScriptVisitor

extends JavaVisitor

{ return typeOperator; } + public visitTypePredicate(typePredicate: TypePredicate, p: P): J | null { + typePredicate = typePredicate.withPrefix(this.visitJsSpace(typePredicate.prefix, JsSpace.Location.TYPE_PREDICATE_PREFIX, p)!); + let tempExpression = this.visitExpression(typePredicate, p) as Expression; + if (!(tempExpression instanceof TypePredicate)) + { + return tempExpression; + } + typePredicate = tempExpression as TypePredicate; + typePredicate = typePredicate.withMarkers(this.visitMarkers(typePredicate.markers, p)); + typePredicate = typePredicate.padding.withAsserts(this.visitJsLeftPadded(typePredicate.padding.asserts, JsLeftPadded.Location.TYPE_PREDICATE_ASSERTS, p)!); + typePredicate = typePredicate.withParameterName(this.visitAndCast(typePredicate.parameterName, p)!); + typePredicate = typePredicate.padding.withExpression(this.visitJsLeftPadded(typePredicate.padding.expression, JsLeftPadded.Location.TYPE_PREDICATE_EXPRESSION, p)); + return typePredicate; + } + public visitJsUnary(unary: Unary, p: P): J | null { unary = unary.withPrefix(this.visitJsSpace(unary.prefix, JsSpace.Location.UNARY_PREFIX, p)!); let tempStatement = this.visitStatement(unary, p) as Statement; diff --git a/openrewrite/test/javascript/parser/class.test.ts b/openrewrite/test/javascript/parser/class.test.ts index 18214d8d..35382603 100644 --- a/openrewrite/test/javascript/parser/class.test.ts +++ b/openrewrite/test/javascript/parser/class.test.ts @@ -439,4 +439,17 @@ describe('class mapping', () => { ); }); + test('this type', () => { + rewriteRun( + //language=typescript + typeScript(` + class FluentAPI { + use_this(): this { + return this; // \`this\` refers to the current instance + } + } + `) + ); + }); + }); diff --git a/openrewrite/test/javascript/parser/expressionStatement.test.ts b/openrewrite/test/javascript/parser/expressionStatement.test.ts index 1a8cd79d..0ebfa2a7 100644 --- a/openrewrite/test/javascript/parser/expressionStatement.test.ts +++ b/openrewrite/test/javascript/parser/expressionStatement.test.ts @@ -145,7 +145,7 @@ describe('expression statement mapping', () => { ); }); - test.skip('optional chaining operator with ?. and custom type', () => { + test('optional chaining operator with ?. and custom type', () => { rewriteRun( //language=typescript typeScript(` @@ -155,4 +155,39 @@ describe('expression statement mapping', () => { ); }); + test('satisfies expression', () => { + rewriteRun( + //language=typescript + typeScript(` + type Person = { + name: string; + age: number; + }; + + const user = /*o*/ { + name: "Alice", + age: 25, + occupation: "Engineer" + } /*a*/ satisfies /*b*/ Person /*c*/; + `) + ); + }); + + test('atisfies expression with complex type ', () => { + rewriteRun( + //language=typescript + typeScript(` + type ApiResponse = { + data: T; + status: "success" | "error"; + }; + + const response = { + data: { userId: 1 }, + status: "success", + } satisfies ApiResponse<{ userId: number }>; + `) + ); + }); + }); diff --git a/openrewrite/test/javascript/parser/function.test.ts b/openrewrite/test/javascript/parser/function.test.ts index ad09148c..6d9c8bb0 100644 --- a/openrewrite/test/javascript/parser/function.test.ts +++ b/openrewrite/test/javascript/parser/function.test.ts @@ -343,7 +343,80 @@ describe('function mapping', () => { //language=typescript typeScript(` /*1*/ export /*2*/ default /*3*/ function /*4*/(/*5*/hljs/*6*/) /*7*/ { + } + `) + ); + }); + + test('function with type predicate simple', () => { + rewriteRun( + //language=typescript + typeScript(` + function isString(value: unknown): value is string { + return typeof value === 'string'; + } + `) + ); + }); + + test('function with type predicate simple with comments', () => { + rewriteRun( + //language=typescript + typeScript(` + function isString(value: unknown): /*a*/value /*b*/is/*c*/ string/*d*/ { + return typeof value === 'string'; + } + `) + ); + }); + + test('function with type predicate and asserts', () => { + rewriteRun( + //language=typescript + typeScript(` + function assertIsString(value: unknown): asserts value is string { + if (typeof value !== "string") { + throw new Error("Value is not a string"); + } + } + `) + ); + }); + + test('function with type predicate and asserts with comments', () => { + rewriteRun( + //language=typescript + typeScript(` + function assertIsString(value: unknown): /*a*/asserts/*b*/ value /*c*/is/*d*/ string /*e*/{ + if (typeof value !== "string") { + throw new Error("Value is not a string"); + } + } + `) + ); + }); + + test('function with type predicate, asserts and without type', () => { + rewriteRun( + //language=typescript + typeScript(` + function assert(value: unknown, message: string): asserts /*a*/value/*b*/ { + if (!value) { + throw new Error(message); + } + } + `) + ); + }); + + test('function with type predicate, asserts and complex type', () => { + rewriteRun( + //language=typescript + typeScript(` + type Animal = { kind: "dog"; bark(): void } | { kind: "cat"; purr(): void }; + function isDog(animal: Animal): animal is { kind: "dog"; bark(): void } { + return animal.kind === "dog"; } `) ); diff --git a/openrewrite/test/javascript/parser/import.test.ts b/openrewrite/test/javascript/parser/import.test.ts index ca4e4feb..fbcd0c25 100644 --- a/openrewrite/test/javascript/parser/import.test.ts +++ b/openrewrite/test/javascript/parser/import.test.ts @@ -93,4 +93,13 @@ describe('import mapping', () => { typeScript(`import type { Component } from "react";`) ); }); + + test.skip('experimental: import with import attributes', () => { + rewriteRun( + //language=typescript + typeScript(` + import foo from 'module-name' with { type: "json" }; + `) + ); + }); }); diff --git a/openrewrite/test/javascript/parser/importType.test.ts b/openrewrite/test/javascript/parser/importType.test.ts new file mode 100644 index 00000000..38e4e414 --- /dev/null +++ b/openrewrite/test/javascript/parser/importType.test.ts @@ -0,0 +1,111 @@ +import {connect, disconnect, rewriteRun, typeScript} from '../testHarness'; + +describe('import type mapping', () => { + beforeAll(() => connect()); + afterAll(() => disconnect()); + + test('simple import', () => { + rewriteRun( + //language=typescript + typeScript(`type ModuleType = import('fs');`) + ); + }); + + test('simple import with isTypeOf', () => { + rewriteRun( + //language=typescript + typeScript(`type MyType = typeof import("module-name");`) + ); + }); + + test('simple import with isTypeOf and comments', () => { + rewriteRun( + //language=typescript + typeScript(`type MyType = /*a*/typeof /*b*/ import/*c*/(/*d*/"module-name"/*e*/)/*f*/;`) + ); + }); + + test('import with qualifier', () => { + rewriteRun( + //language=typescript + typeScript(`type ReadStream = import("fs").ReadStream;`) + ); + }); + + test('import with qualifier and comments', () => { + rewriteRun( + //language=typescript + typeScript(`type ReadStream = import("fs")/*a*/./*b*/ReadStream/*c*/;`) + ); + }); + + test('import with sub qualifiers', () => { + rewriteRun( + //language=typescript + typeScript(` + export default class Utils { + static Tools = class { + static UtilityName = "Helper"; + }; + } + + // main.ts + type UtilityNameType = import("./module")/*a*/./*b*/default/*c*/./*d*/Tools/*e*/./*f*/UtilityName; + `) + ); + }); + + + test('function with import type', () => { + rewriteRun( + //language=typescript + typeScript(` + function useModule(module: import("fs")): void { + console.log(module); + } + `) + ); + }); + + test('import type with type argument', () => { + rewriteRun( + //language=typescript + typeScript(` + type AnotherType = import("module-name").GenericType; + `) + ); + }); + + test('import type with type argument adv1', () => { + rewriteRun( + //language=typescript + typeScript(` + export namespace Shapes { + export type Box = { value: T; size: number }; + export type Circle = { radius: number }; + } + + // main.ts + type CircleBox = import("./shapes").Shapes.Box; + `) + ); + }); + + test('import type with type argument adv2', () => { + rewriteRun( + //language=typescript + typeScript(` + export namespace Models { + export type Response = { + status: number; + data: T; + }; + } + + // main.ts + type UserResponse = import("./library").Models.Response<{ id: string; name: string }>; + `) + ); + }); + +}); diff --git a/openrewrite/test/javascript/parser/typeAlias.test.ts b/openrewrite/test/javascript/parser/typeAlias.test.ts index d7b33ec5..5461b9c2 100644 --- a/openrewrite/test/javascript/parser/typeAlias.test.ts +++ b/openrewrite/test/javascript/parser/typeAlias.test.ts @@ -193,7 +193,7 @@ describe('type alias mapping', () => { ); }); - test.skip('conditional type with parenthesized type', () => { + test('conditional type with parenthesized type', () => { rewriteRun( //language=typescript typeScript(` @@ -202,4 +202,31 @@ describe('type alias mapping', () => { ); }); + test('conditional type with parenthesized type and comments', () => { + rewriteRun( + //language=typescript + typeScript(` + type Flatten = T extends /*a*/(/*b*/infer/*c*/ R/*d*/)/*e*/[] ? Flatten : T; + `) + ); + }); + + test('conditional type with parenthesized type and never', () => { + rewriteRun( + //language=typescript + typeScript(` + type GetReturnType = T extends (...args: any[]) => infer R ? R : never; + `) + ); + }); + + test('named tuple member type', () => { + rewriteRun( + //language=typescript + typeScript(` + type Coordinate = [x: number, y: number, z?: number]; + type VariableArgs = [name: string, ...args: number[]]; + `) + ); + }); }); diff --git a/openrewrite/test/javascript/parser/typeLiteral.test.ts b/openrewrite/test/javascript/parser/typeLiteral.test.ts index 15cbfdea..0dce89ab 100644 --- a/openrewrite/test/javascript/parser/typeLiteral.test.ts +++ b/openrewrite/test/javascript/parser/typeLiteral.test.ts @@ -32,4 +32,13 @@ describe('type literal mapping', () => { `) ); }); + + test('type literal', () => { + rewriteRun( + //language=typescript + typeScript(` + type Animal = { kind: "dog"; bark(): void }; + `) + ); + }); }); diff --git a/openrewrite/test/javascript/parser/typeQuery.test.ts b/openrewrite/test/javascript/parser/typeQuery.test.ts index ab546f22..ed469b6c 100644 --- a/openrewrite/test/javascript/parser/typeQuery.test.ts +++ b/openrewrite/test/javascript/parser/typeQuery.test.ts @@ -78,7 +78,7 @@ describe('type-query operator mapping', () => { ); }); - test.skip('index access type', () => { + test('index access type', () => { rewriteRun( //language=typescript typeScript(` @@ -86,4 +86,30 @@ describe('type-query operator mapping', () => { `) ); }); + + test('index access type with comments', () => { + rewriteRun( + //language=typescript + typeScript(` + type DatabaseConfig = /*a*/typeof /*b*/ config/*c*/[/*d*/"database"/*e*/]/*f*/; + `) + ); + }); + + + test('index access type nested', () => { + rewriteRun( + //language=typescript + typeScript(` + interface Company { + employees: { + name: string; + age: number; + }[]; + } + + type EmployeeNameType = Company["employees"][number]["name"]; // Result: string + `) + ); + }); }); diff --git a/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptReceiver.java b/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptReceiver.java index d44ce6bd..38f5792b 100644 --- a/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptReceiver.java +++ b/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptReceiver.java @@ -201,6 +201,29 @@ public JS.FunctionType visitFunctionType(JS.FunctionType functionType, ReceiverC return functionType; } + @Override + public JS.InferType visitInferType(JS.InferType inferType, ReceiverContext ctx) { + inferType = inferType.withId(ctx.receiveNonNullValue(inferType.getId(), UUID.class)); + inferType = inferType.withPrefix(ctx.receiveNonNullNode(inferType.getPrefix(), JavaScriptReceiver::receiveSpace)); + inferType = inferType.withMarkers(ctx.receiveNonNullNode(inferType.getMarkers(), ctx::receiveMarkers)); + inferType = inferType.getPadding().withTypeParameter(ctx.receiveNonNullNode(inferType.getPadding().getTypeParameter(), JavaScriptReceiver::receiveLeftPaddedTree)); + inferType = inferType.withType(ctx.receiveValue(inferType.getType(), JavaType.class)); + return inferType; + } + + @Override + public JS.ImportType visitImportType(JS.ImportType importType, ReceiverContext ctx) { + importType = importType.withId(ctx.receiveNonNullValue(importType.getId(), UUID.class)); + importType = importType.withPrefix(ctx.receiveNonNullNode(importType.getPrefix(), JavaScriptReceiver::receiveSpace)); + importType = importType.withMarkers(ctx.receiveNonNullNode(importType.getMarkers(), ctx::receiveMarkers)); + importType = importType.getPadding().withHasTypeof(ctx.receiveNonNullNode(importType.getPadding().getHasTypeof(), rightPaddedValueReceiver(java.lang.Boolean.class))); + importType = importType.withImportArgument(ctx.receiveNonNullNode(importType.getImportArgument(), ctx::receiveTree)); + importType = importType.getPadding().withQualifier(ctx.receiveNode(importType.getPadding().getQualifier(), JavaScriptReceiver::receiveLeftPaddedTree)); + importType = importType.getPadding().withTypeArguments(ctx.receiveNode(importType.getPadding().getTypeArguments(), JavaScriptReceiver::receiveContainer)); + importType = importType.withType(ctx.receiveValue(importType.getType(), JavaType.class)); + return importType; + } + @Override public JS.JsImport visitJsImport(JS.JsImport jsImport, ReceiverContext ctx) { jsImport = jsImport.withId(ctx.receiveNonNullValue(jsImport.getId(), UUID.class)); @@ -238,6 +261,16 @@ public JS.JsBinary visitJsBinary(JS.JsBinary jsBinary, ReceiverContext ctx) { return jsBinary; } + @Override + public JS.LiteralType visitLiteralType(JS.LiteralType literalType, ReceiverContext ctx) { + literalType = literalType.withId(ctx.receiveNonNullValue(literalType.getId(), UUID.class)); + literalType = literalType.withPrefix(ctx.receiveNonNullNode(literalType.getPrefix(), JavaScriptReceiver::receiveSpace)); + literalType = literalType.withMarkers(ctx.receiveNonNullNode(literalType.getMarkers(), ctx::receiveMarkers)); + literalType = literalType.withLiteral(ctx.receiveNonNullNode(literalType.getLiteral(), ctx::receiveTree)); + literalType = literalType.withType(ctx.receiveValue(literalType.getType(), JavaType.class)); + return literalType; + } + @Override public JS.ObjectBindingDeclarations visitObjectBindingDeclarations(JS.ObjectBindingDeclarations objectBindingDeclarations, ReceiverContext ctx) { objectBindingDeclarations = objectBindingDeclarations.withId(ctx.receiveNonNullValue(objectBindingDeclarations.getId(), UUID.class)); @@ -261,6 +294,17 @@ public JS.PropertyAssignment visitPropertyAssignment(JS.PropertyAssignment prope return propertyAssignment; } + @Override + public JS.SatisfiesExpression visitSatisfiesExpression(JS.SatisfiesExpression satisfiesExpression, ReceiverContext ctx) { + satisfiesExpression = satisfiesExpression.withId(ctx.receiveNonNullValue(satisfiesExpression.getId(), UUID.class)); + satisfiesExpression = satisfiesExpression.withPrefix(ctx.receiveNonNullNode(satisfiesExpression.getPrefix(), JavaScriptReceiver::receiveSpace)); + satisfiesExpression = satisfiesExpression.withMarkers(ctx.receiveNonNullNode(satisfiesExpression.getMarkers(), ctx::receiveMarkers)); + satisfiesExpression = satisfiesExpression.withExpression(ctx.receiveNonNullNode(satisfiesExpression.getExpression(), ctx::receiveTree)); + satisfiesExpression = satisfiesExpression.getPadding().withSatisfiesType(ctx.receiveNonNullNode(satisfiesExpression.getPadding().getSatisfiesType(), JavaScriptReceiver::receiveLeftPaddedTree)); + satisfiesExpression = satisfiesExpression.withType(ctx.receiveValue(satisfiesExpression.getType(), JavaType.class)); + return satisfiesExpression; + } + @Override public JS.ScopedVariableDeclarations visitScopedVariableDeclarations(JS.ScopedVariableDeclarations scopedVariableDeclarations, ReceiverContext ctx) { scopedVariableDeclarations = scopedVariableDeclarations.withId(ctx.receiveNonNullValue(scopedVariableDeclarations.getId(), UUID.class)); @@ -365,6 +409,18 @@ public JS.TypeOperator visitTypeOperator(JS.TypeOperator typeOperator, ReceiverC return typeOperator; } + @Override + public JS.TypePredicate visitTypePredicate(JS.TypePredicate typePredicate, ReceiverContext ctx) { + typePredicate = typePredicate.withId(ctx.receiveNonNullValue(typePredicate.getId(), UUID.class)); + typePredicate = typePredicate.withPrefix(ctx.receiveNonNullNode(typePredicate.getPrefix(), JavaScriptReceiver::receiveSpace)); + typePredicate = typePredicate.withMarkers(ctx.receiveNonNullNode(typePredicate.getMarkers(), ctx::receiveMarkers)); + typePredicate = typePredicate.getPadding().withAsserts(ctx.receiveNonNullNode(typePredicate.getPadding().getAsserts(), leftPaddedValueReceiver(java.lang.Boolean.class))); + typePredicate = typePredicate.withParameterName(ctx.receiveNonNullNode(typePredicate.getParameterName(), ctx::receiveTree)); + typePredicate = typePredicate.getPadding().withExpression(ctx.receiveNode(typePredicate.getPadding().getExpression(), JavaScriptReceiver::receiveLeftPaddedTree)); + typePredicate = typePredicate.withType(ctx.receiveValue(typePredicate.getType(), JavaType.class)); + return typePredicate; + } + @Override public JS.Unary visitUnary(JS.Unary unary, ReceiverContext ctx) { unary = unary.withId(ctx.receiveNonNullValue(unary.getId(), UUID.class)); @@ -1398,6 +1454,29 @@ public T create(Class type, ReceiverContext ctx) { ); } + if (type == JS.InferType.class) { + return (T) new JS.InferType( + ctx.receiveNonNullValue(null, UUID.class), + ctx.receiveNonNullNode(null, JavaScriptReceiver::receiveSpace), + ctx.receiveNonNullNode(null, ctx::receiveMarkers), + ctx.receiveNonNullNode(null, JavaScriptReceiver::receiveLeftPaddedTree), + ctx.receiveValue(null, JavaType.class) + ); + } + + if (type == JS.ImportType.class) { + return (T) new JS.ImportType( + ctx.receiveNonNullValue(null, UUID.class), + ctx.receiveNonNullNode(null, JavaScriptReceiver::receiveSpace), + ctx.receiveNonNullNode(null, ctx::receiveMarkers), + ctx.receiveNonNullNode(null, rightPaddedValueReceiver(java.lang.Boolean.class)), + ctx.receiveNonNullNode(null, ctx::receiveTree), + ctx.receiveNode(null, JavaScriptReceiver::receiveLeftPaddedTree), + ctx.receiveNode(null, JavaScriptReceiver::receiveContainer), + ctx.receiveValue(null, JavaType.class) + ); + } + if (type == JS.JsImport.class) { return (T) new JS.JsImport( ctx.receiveNonNullValue(null, UUID.class), @@ -1435,6 +1514,16 @@ public T create(Class type, ReceiverContext ctx) { ); } + if (type == JS.LiteralType.class) { + return (T) new JS.LiteralType( + ctx.receiveNonNullValue(null, UUID.class), + ctx.receiveNonNullNode(null, JavaScriptReceiver::receiveSpace), + ctx.receiveNonNullNode(null, ctx::receiveMarkers), + ctx.receiveNonNullNode(null, ctx::receiveTree), + ctx.receiveValue(null, JavaType.class) + ); + } + if (type == JS.ObjectBindingDeclarations.class) { return (T) new JS.ObjectBindingDeclarations( ctx.receiveNonNullValue(null, UUID.class), @@ -1458,6 +1547,17 @@ public T create(Class type, ReceiverContext ctx) { ); } + if (type == JS.SatisfiesExpression.class) { + return (T) new JS.SatisfiesExpression( + ctx.receiveNonNullValue(null, UUID.class), + ctx.receiveNonNullNode(null, JavaScriptReceiver::receiveSpace), + ctx.receiveNonNullNode(null, ctx::receiveMarkers), + ctx.receiveNonNullNode(null, ctx::receiveTree), + ctx.receiveNonNullNode(null, JavaScriptReceiver::receiveLeftPaddedTree), + ctx.receiveValue(null, JavaType.class) + ); + } + if (type == JS.ScopedVariableDeclarations.class) { return (T) new JS.ScopedVariableDeclarations( ctx.receiveNonNullValue(null, UUID.class), @@ -1562,6 +1662,18 @@ public T create(Class type, ReceiverContext ctx) { ); } + if (type == JS.TypePredicate.class) { + return (T) new JS.TypePredicate( + ctx.receiveNonNullValue(null, UUID.class), + ctx.receiveNonNullNode(null, JavaScriptReceiver::receiveSpace), + ctx.receiveNonNullNode(null, ctx::receiveMarkers), + ctx.receiveNonNullNode(null, leftPaddedValueReceiver(java.lang.Boolean.class)), + ctx.receiveNonNullNode(null, ctx::receiveTree), + ctx.receiveNode(null, JavaScriptReceiver::receiveLeftPaddedTree), + ctx.receiveValue(null, JavaType.class) + ); + } + if (type == JS.Unary.class) { return (T) new JS.Unary( ctx.receiveNonNullValue(null, UUID.class), diff --git a/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptSender.java b/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptSender.java index a61d78b1..02ad28d5 100644 --- a/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptSender.java +++ b/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptSender.java @@ -184,6 +184,29 @@ public JS.FunctionType visitFunctionType(JS.FunctionType functionType, SenderCon return functionType; } + @Override + public JS.InferType visitInferType(JS.InferType inferType, SenderContext ctx) { + ctx.sendValue(inferType, JS.InferType::getId); + ctx.sendNode(inferType, JS.InferType::getPrefix, JavaScriptSender::sendSpace); + ctx.sendNode(inferType, JS.InferType::getMarkers, ctx::sendMarkers); + ctx.sendNode(inferType, e -> e.getPadding().getTypeParameter(), JavaScriptSender::sendLeftPadded); + ctx.sendTypedValue(inferType, JS.InferType::getType); + return inferType; + } + + @Override + public JS.ImportType visitImportType(JS.ImportType importType, SenderContext ctx) { + ctx.sendValue(importType, JS.ImportType::getId); + ctx.sendNode(importType, JS.ImportType::getPrefix, JavaScriptSender::sendSpace); + ctx.sendNode(importType, JS.ImportType::getMarkers, ctx::sendMarkers); + ctx.sendNode(importType, e -> e.getPadding().getHasTypeof(), JavaScriptSender::sendRightPadded); + ctx.sendNode(importType, JS.ImportType::getImportArgument, ctx::sendTree); + ctx.sendNode(importType, e -> e.getPadding().getQualifier(), JavaScriptSender::sendLeftPadded); + ctx.sendNode(importType, e -> e.getPadding().getTypeArguments(), JavaScriptSender::sendContainer); + ctx.sendTypedValue(importType, JS.ImportType::getType); + return importType; + } + @Override public JS.JsImport visitJsImport(JS.JsImport jsImport, SenderContext ctx) { ctx.sendValue(jsImport, JS.JsImport::getId); @@ -221,6 +244,16 @@ public JS.JsBinary visitJsBinary(JS.JsBinary jsBinary, SenderContext ctx) { return jsBinary; } + @Override + public JS.LiteralType visitLiteralType(JS.LiteralType literalType, SenderContext ctx) { + ctx.sendValue(literalType, JS.LiteralType::getId); + ctx.sendNode(literalType, JS.LiteralType::getPrefix, JavaScriptSender::sendSpace); + ctx.sendNode(literalType, JS.LiteralType::getMarkers, ctx::sendMarkers); + ctx.sendNode(literalType, JS.LiteralType::getLiteral, ctx::sendTree); + ctx.sendTypedValue(literalType, JS.LiteralType::getType); + return literalType; + } + @Override public JS.ObjectBindingDeclarations visitObjectBindingDeclarations(JS.ObjectBindingDeclarations objectBindingDeclarations, SenderContext ctx) { ctx.sendValue(objectBindingDeclarations, JS.ObjectBindingDeclarations::getId); @@ -244,6 +277,17 @@ public JS.PropertyAssignment visitPropertyAssignment(JS.PropertyAssignment prope return propertyAssignment; } + @Override + public JS.SatisfiesExpression visitSatisfiesExpression(JS.SatisfiesExpression satisfiesExpression, SenderContext ctx) { + ctx.sendValue(satisfiesExpression, JS.SatisfiesExpression::getId); + ctx.sendNode(satisfiesExpression, JS.SatisfiesExpression::getPrefix, JavaScriptSender::sendSpace); + ctx.sendNode(satisfiesExpression, JS.SatisfiesExpression::getMarkers, ctx::sendMarkers); + ctx.sendNode(satisfiesExpression, JS.SatisfiesExpression::getExpression, ctx::sendTree); + ctx.sendNode(satisfiesExpression, e -> e.getPadding().getSatisfiesType(), JavaScriptSender::sendLeftPadded); + ctx.sendTypedValue(satisfiesExpression, JS.SatisfiesExpression::getType); + return satisfiesExpression; + } + @Override public JS.ScopedVariableDeclarations visitScopedVariableDeclarations(JS.ScopedVariableDeclarations scopedVariableDeclarations, SenderContext ctx) { ctx.sendValue(scopedVariableDeclarations, JS.ScopedVariableDeclarations::getId); @@ -348,6 +392,18 @@ public JS.TypeOperator visitTypeOperator(JS.TypeOperator typeOperator, SenderCon return typeOperator; } + @Override + public JS.TypePredicate visitTypePredicate(JS.TypePredicate typePredicate, SenderContext ctx) { + ctx.sendValue(typePredicate, JS.TypePredicate::getId); + ctx.sendNode(typePredicate, JS.TypePredicate::getPrefix, JavaScriptSender::sendSpace); + ctx.sendNode(typePredicate, JS.TypePredicate::getMarkers, ctx::sendMarkers); + ctx.sendNode(typePredicate, e -> e.getPadding().getAsserts(), JavaScriptSender::sendLeftPadded); + ctx.sendNode(typePredicate, JS.TypePredicate::getParameterName, ctx::sendTree); + ctx.sendNode(typePredicate, e -> e.getPadding().getExpression(), JavaScriptSender::sendLeftPadded); + ctx.sendTypedValue(typePredicate, JS.TypePredicate::getType); + return typePredicate; + } + @Override public JS.Unary visitUnary(JS.Unary unary, SenderContext ctx) { ctx.sendValue(unary, JS.Unary::getId); diff --git a/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptValidator.java b/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptValidator.java index cb5d3540..0b0c650e 100644 --- a/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptValidator.java +++ b/rewrite-javascript-remote/src/main/java/org/openrewrite/javascript/remote/JavaScriptValidator.java @@ -127,6 +127,20 @@ public JS.FunctionType visitFunctionType(JS.FunctionType functionType, P p) { return functionType; } + @Override + public JS.InferType visitInferType(JS.InferType inferType, P p) { + visitAndValidate(inferType.getTypeParameter(), J.class, p); + return inferType; + } + + @Override + public JS.ImportType visitImportType(JS.ImportType importType, P p) { + visitAndValidate(importType.getImportArgument(), J.ParenthesizedTypeTree.class, p); + visitAndValidate(importType.getQualifier(), Expression.class, p); + visitAndValidate(importType.getTypeArguments(), Expression.class, p); + return importType; + } + @Override public JS.JsImport visitJsImport(JS.JsImport jsImport, P p) { visitAndValidate(jsImport.getName(), J.Identifier.class, p); @@ -149,6 +163,12 @@ public JS.JsBinary visitJsBinary(JS.JsBinary jsBinary, P p) { return jsBinary; } + @Override + public JS.LiteralType visitLiteralType(JS.LiteralType literalType, P p) { + visitAndValidate(literalType.getLiteral(), Expression.class, p); + return literalType; + } + @Override public JS.ObjectBindingDeclarations visitObjectBindingDeclarations(JS.ObjectBindingDeclarations objectBindingDeclarations, P p) { ListUtils.map(objectBindingDeclarations.getLeadingAnnotations(), el -> visitAndValidate(el, J.Annotation.class, p)); @@ -166,6 +186,13 @@ public JS.PropertyAssignment visitPropertyAssignment(JS.PropertyAssignment prope return propertyAssignment; } + @Override + public JS.SatisfiesExpression visitSatisfiesExpression(JS.SatisfiesExpression satisfiesExpression, P p) { + visitAndValidate(satisfiesExpression.getExpression(), J.class, p); + visitAndValidate(satisfiesExpression.getSatisfiesType(), Expression.class, p); + return satisfiesExpression; + } + @Override public JS.ScopedVariableDeclarations visitScopedVariableDeclarations(JS.ScopedVariableDeclarations scopedVariableDeclarations, P p) { ListUtils.map(scopedVariableDeclarations.getModifiers(), el -> visitAndValidate(el, J.Modifier.class, p)); @@ -234,6 +261,13 @@ public JS.TypeOperator visitTypeOperator(JS.TypeOperator typeOperator, P p) { return typeOperator; } + @Override + public JS.TypePredicate visitTypePredicate(JS.TypePredicate typePredicate, P p) { + visitAndValidate(typePredicate.getParameterName(), J.Identifier.class, p); + visitAndValidate(typePredicate.getExpression(), Expression.class, p); + return typePredicate; + } + @Override public JS.Unary visitUnary(JS.Unary unary, P p) { visitAndValidate(unary.getExpression(), Expression.class, p); 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 a1400a99..589579dc 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/JavaScriptVisitor.java @@ -237,7 +237,6 @@ public J visitExpressionWithTypeArguments(JS.ExpressionWithTypeArguments express if (ta.getPadding().getTypeArguments() != null) { ta = ta.getPadding().withTypeArguments(visitContainer(ta.getPadding().getTypeArguments(), JsContainer.Location.EXPR_WITH_TYPE_ARG_PARAMETERS, p)); } - ta = ta.getPadding().withTypeArguments(visitTypeNames(ta.getPadding().getTypeArguments(), p)); ta = ta.withType(visitType(ta.getType(), p)); return ta; } @@ -261,6 +260,22 @@ public J visitFunctionType(JS.FunctionType functionType, P p) { return f; } + + public J visitInferType(JS.InferType inferType, P p) { + JS.InferType t = inferType; + t = t.withPrefix(visitSpace(t.getPrefix(), JsSpace.Location.INFER_TYPE_PREFIX, p)); + t = t.withMarkers(visitMarkers(t.getMarkers(), p)); + Expression temp = (Expression) visitExpression(t, p); + if (!(temp instanceof JS.InferType)) { + return temp; + } else { + t = (JS.InferType) temp; + } + t = t.getPadding().withTypeParameter(visitLeftPadded(t.getPadding().getTypeParameter(), JsLeftPadded.Location.INFER_TYPE_PARAMETER, p)); + t = t.withType(visitType(t.getType(), p)); + return t; + } + public J visitJsBinary(JS.JsBinary binary, P p) { JS.JsBinary b = binary; b = b.withPrefix(visitSpace(b.getPrefix(), JsSpace.Location.BINARY_PREFIX, p)); @@ -320,6 +335,14 @@ public J visitJsImportSpecifier(JS.JsImportSpecifier jis, P p) { return i; } + public J visitLiteralType(JS.LiteralType literalType, P p) { + JS.LiteralType type = literalType; + type = type.withPrefix(visitSpace(type.getPrefix(), JsSpace.Location.LITERAL_TYPE_PREFIX, p)); + type = type.withMarkers(visitMarkers(type.getMarkers(), p)); + type = type.withLiteral(visitAndCast(type.getLiteral(), p)); + return type; + } + public J visitObjectBindingDeclarations(JS.ObjectBindingDeclarations objectBindingDeclarations, P p) { JS.ObjectBindingDeclarations o = objectBindingDeclarations; o = o.withPrefix(visitSpace(o.getPrefix(), JsSpace.Location.OBJECT_BINDING_DECLARATIONS_PREFIX, p)); @@ -361,6 +384,21 @@ public J visitPropertyAssignment(JS.PropertyAssignment propertyAssignment, P p) return pa; } + public J visitSatisfiesExpression(JS.SatisfiesExpression satisfiesExpression, P p) { + JS.SatisfiesExpression sa = satisfiesExpression; + sa = sa.withPrefix(visitSpace(sa.getPrefix(), JsSpace.Location.SATISFIES_EXPRESSION_PREFIX, p)); + sa = sa.withMarkers(visitMarkers(sa.getMarkers(), p)); + Expression temp = (Expression) visitExpression(sa, p); + if (!(temp instanceof JS.SatisfiesExpression)) { + return temp; + } else { + sa = (JS.SatisfiesExpression) temp; + } + sa = sa.withExpression(visitAndCast(sa.getExpression(), p)); + sa = sa.getPadding().withSatisfiesType(visitLeftPadded(sa.getPadding().getSatisfiesType(), JsLeftPadded.Location.SATISFIES_EXPRESSION_TYPE, p)); + return sa; + } + public J visitScopedVariableDeclarations(JS.ScopedVariableDeclarations scopedVariableDeclarations, P p) { JS.ScopedVariableDeclarations vd = scopedVariableDeclarations; vd = vd.withPrefix(visitSpace(vd.getPrefix(), JsSpace.Location.SCOPED_VARIABLE_DECLARATIONS_PREFIX, p)); @@ -488,6 +526,22 @@ public J visitTypeOperator(JS.TypeOperator typeOperator, P p) { return t; } + public J visitTypePredicate(JS.TypePredicate typePredicate, P p) { + JS.TypePredicate t = typePredicate; + t = t.withPrefix(visitSpace(t.getPrefix(), JsSpace.Location.TYPE_PREDICATE_PREFIX, p)); + t = t.withMarkers(visitMarkers(t.getMarkers(), p)); + Expression temp = (Expression) visitExpression(t, p); + if (!(temp instanceof JS.TypePredicate)) { + return temp; + } else { + t = (JS.TypePredicate) temp; + } + t = t.getPadding().withAsserts(visitLeftPadded(t.getPadding().getAsserts(), JsLeftPadded.Location.TYPE_PREDICATE_ASSERTS, p)); + t = t.withParameterName(visitAndCast(t.getParameterName(), p)); + t = t.getPadding().withExpression(visitLeftPadded(t.getPadding().getExpression(), JsLeftPadded.Location.TYPE_PREDICATE_EXPRESSION, p)); + return t; + } + public J visitUnary(JS.Unary unary, P p) { JS.Unary u = unary; u = u.withPrefix(visitSpace(u.getPrefix(), Space.Location.UNARY_PREFIX, p)); @@ -809,6 +863,25 @@ public J visitTypeLiteral(JS.TypeLiteral typeLiteral, P p) { return t; } + public J visitImportType(JS.ImportType importType, P p) { + JS.ImportType t = importType; + t = t.withPrefix(visitSpace(t.getPrefix(), JsSpace.Location.IMPORT_TYPE_PREFIX, p)); + t = t.withMarkers(visitMarkers(t.getMarkers(), p)); + Expression temp = (Expression) visitExpression(t, p); + if (!(temp instanceof JS.ImportType)) { + return temp; + } else { + t = (JS.ImportType) temp; + } + t = t.getPadding().withHasTypeof(visitRightPadded(t.getPadding().getHasTypeof(), JsRightPadded.Location.IMPORT_TYPE_TYPEOF, p)); + t = t.withImportArgument(visitAndCast(t.getImportArgument(), p)); + t = t.getPadding().withQualifier(visitLeftPadded(t.getPadding().getQualifier(), JsLeftPadded.Location.IMPORT_TYPE_QUALIFIER, p)); + if (t.getPadding().getTypeArguments() != null) { + t = t.getPadding().withTypeArguments(visitContainer(t.getPadding().getTypeArguments(), JsContainer.Location.IMPORT_TYPE_TYPE_ARGUMENTS, p)); + } + return t; + } + public J visitIndexSignatureDeclaration(JS.IndexSignatureDeclaration indexSignatureDeclaration, P p) { JS.IndexSignatureDeclaration isd = indexSignatureDeclaration; isd = isd.withPrefix(visitSpace(isd.getPrefix(), JsSpace.Location.INDEXED_SIGNATURE_DECLARATION_PREFIX, p)); 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 27d421a8..8ccccc85 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 @@ -203,6 +203,29 @@ public J visitFunctionType(JS.FunctionType functionType, PrintOutputCapture

p return functionType; } + @Override + public J visitInferType(JS.InferType inferType, PrintOutputCapture

p) { + beforeSyntax(inferType, JsSpace.Location.INFER_TYPE_PREFIX, p); + visitLeftPadded("infer", inferType.getPadding().getTypeParameter(), JsLeftPadded.Location.INFER_TYPE_PARAMETER, p); + afterSyntax(inferType, p); + return inferType; + } + + @Override + public J visitImportType(JS.ImportType importType, PrintOutputCapture

p) { + beforeSyntax(importType, JsSpace.Location.IMPORT_TYPE_PREFIX, p); + if (importType.isHasTypeof()) { + p.append("typeof"); + visitRightPadded(importType.getPadding().getHasTypeof(), JsRightPadded.Location.IMPORT_TYPE_TYPEOF, p); + } + p.append("import"); + visit(importType.getImportArgument(), p); + visitLeftPadded(".", importType.getPadding().getQualifier(), JsLeftPadded.Location.IMPORT_TYPE_QUALIFIER, p); + visitContainer("<", importType.getPadding().getTypeArguments(), JsContainer.Location.IMPORT_TYPE_TYPE_ARGUMENTS, ",", ">", p); + afterSyntax(importType, p); + return importType; + } + @Override public J visitJsImport(JS.JsImport jsImport, PrintOutputCapture

p) { beforeSyntax(jsImport, JsSpace.Location.EXPORT_PREFIX, p); @@ -343,6 +366,14 @@ public J visitScopedVariableDeclarations(JS.ScopedVariableDeclarations variableD return variableDeclarations; } + @Override + public J visitLiteralType(JS.LiteralType literalType, PrintOutputCapture

p) { + beforeSyntax(literalType, JsSpace.Location.LITERAL_TYPE_PREFIX, p); + visit(literalType.getLiteral(), p); + afterSyntax(literalType, p); + return literalType; + } + @Override public J visitObjectBindingDeclarations(JS.ObjectBindingDeclarations objectBindingDeclarations, PrintOutputCapture

p) { beforeSyntax(objectBindingDeclarations, Space.Location.VARIABLE_DECLARATIONS_PREFIX, p); @@ -356,6 +387,15 @@ public J visitObjectBindingDeclarations(JS.ObjectBindingDeclarations objectBindi return objectBindingDeclarations; } + @Override + public J visitSatisfiesExpression(JS.SatisfiesExpression satisfiesExpression, PrintOutputCapture

p) { + beforeSyntax(satisfiesExpression, JsSpace.Location.SATISFIES_EXPRESSION_PREFIX, p); + visit(satisfiesExpression.getExpression(), p); + visitLeftPadded("satisfies", satisfiesExpression.getPadding().getSatisfiesType(), JsLeftPadded.Location.SATISFIES_EXPRESSION_TYPE, p); + afterSyntax(satisfiesExpression, p); + return satisfiesExpression; + } + @Override public J visitTaggedTemplateExpression(JS.TaggedTemplateExpression taggedTemplateExpression, PrintOutputCapture

p) { beforeSyntax(taggedTemplateExpression, JsSpace.Location.TEMPLATE_EXPRESSION_PREFIX, p); @@ -449,6 +489,18 @@ public J visitTypeOperator(JS.TypeOperator typeOperator, PrintOutputCapture

p return typeOperator; } + @Override + public J visitTypePredicate(JS.TypePredicate typePredicate, PrintOutputCapture

p) { + beforeSyntax(typePredicate, JsSpace.Location.TYPE_PREDICATE_PREFIX, p); + if (typePredicate.isAsserts()) { + visitLeftPaddedBoolean("asserts", typePredicate.getPadding().getAsserts(), JsLeftPadded.Location.TYPE_PREDICATE_ASSERTS, p); + } + visit(typePredicate.getParameterName(), p); + visitLeftPadded("is", typePredicate.getPadding().getExpression(), JsLeftPadded.Location.TYPE_PREDICATE_EXPRESSION, p); + afterSyntax(typePredicate, p); + return typePredicate; + } + @Override public J visitUnary(JS.Unary unary, PrintOutputCapture

p) { beforeSyntax(unary, Space.Location.UNARY_PREFIX, p); diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JS.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JS.java index f14f65a3..087b25f1 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JS.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JS.java @@ -961,6 +961,201 @@ public FunctionType withParameters(JContainer parameters) { } } + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) + @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) + @RequiredArgsConstructor + @AllArgsConstructor(access = AccessLevel.PRIVATE) + final class InferType implements JS, TypeTree, Expression { + @Nullable + @NonFinal + transient WeakReference padding; + + @With + @EqualsAndHashCode.Include + @Getter + UUID id; + + @With + @Getter + Space prefix; + + @With + @Getter + Markers markers; + + JLeftPadded typeParameter; + + public J getTypeParameter() { + return typeParameter.getElement(); + } + + public InferType withTypeParameter(J typeParameter) { + return getPadding().withTypeParameter(JLeftPadded.withElement(this.typeParameter, typeParameter)); + } + + @Getter + @With + @Nullable + JavaType type; + + @Override + public

J acceptJavaScript(JavaScriptVisitor

v, P p) { + return v.visitInferType(this, p); + } + + @Override + public CoordinateBuilder.Expression getCoordinates() { + return new CoordinateBuilder.Expression(this); + } + + public InferType.Padding getPadding() { + InferType.Padding p; + if (this.padding == null) { + p = new InferType.Padding(this); + this.padding = new WeakReference<>(p); + } else { + p = this.padding.get(); + if (p == null || p.t != this) { + p = new InferType.Padding(this); + this.padding = new WeakReference<>(p); + } + } + return p; + } + + @RequiredArgsConstructor + public static class Padding { + private final InferType t; + + public JLeftPadded getTypeParameter() { + return t.typeParameter; + } + + public InferType withTypeParameter(JLeftPadded typeParameter) { + return t.typeParameter == typeParameter ? t : new InferType(t.id, t.prefix, t.markers, typeParameter, t.type); + } + } + } + + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) + @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) + @RequiredArgsConstructor + @AllArgsConstructor(access = AccessLevel.PRIVATE) + class ImportType implements JS, Expression, TypeTree { + + @Nullable + @NonFinal + transient WeakReference padding; + + @Getter + @With + @EqualsAndHashCode.Include + UUID id; + + @Getter + @With + Space prefix; + + @Getter + @With + Markers markers; + + JRightPadded hasTypeof; + + public boolean isHasTypeof() { + return hasTypeof.getElement(); + } + + public ImportType withHasTypeof(boolean hasTypeof) { + return getPadding().withHasTypeof(this.hasTypeof.withElement(hasTypeof)); + } + + @Getter + @With + J.ParenthesizedTypeTree importArgument; + + @Nullable + JLeftPadded qualifier; + + public @Nullable Expression getQualifier() { + return qualifier == null ? null : qualifier.getElement(); + } + + public ImportType withQualifier(@Nullable Expression qualifier) { + return getPadding().withQualifier(JLeftPadded.withElement(this.qualifier, qualifier)); + } + + @Nullable + JContainer typeArguments; + + public @Nullable List getTypeArguments() { + return typeArguments == null ? null : typeArguments.getElements(); + } + + public ImportType withTypeArguments(@Nullable List typeArguments) { + return getPadding().withTypeArguments(JContainer.withElementsNullable(this.typeArguments, typeArguments)); + } + + @Getter + @With + @Nullable + JavaType type; + + @Override + public

J acceptJavaScript(JavaScriptVisitor

v, P p) { + return v.visitImportType(this, p); + } + + @Override + public CoordinateBuilder.Expression getCoordinates() { + return new CoordinateBuilder.Expression(this); + } + + public ImportType.Padding getPadding() { + ImportType.Padding p; + if (this.padding == null) { + p = new ImportType.Padding(this); + this.padding = new WeakReference<>(p); + } else { + p = this.padding.get(); + if (p == null || p.t != this) { + p = new ImportType.Padding(this); + this.padding = new WeakReference<>(p); + } + } + return p; + } + + @RequiredArgsConstructor + public static class Padding { + private final ImportType t; + + public JRightPadded getHasTypeof() { + return t.hasTypeof; + } + + public ImportType withHasTypeof(JRightPadded hasTypeof) { + return t.hasTypeof == hasTypeof ? t : new ImportType(t.id, t.prefix, t.markers, hasTypeof, t.importArgument, t.qualifier, t.typeArguments, t.type); + } + + public @Nullable JLeftPadded getQualifier() { + return t.qualifier; + } + + public ImportType withQualifier(@Nullable JLeftPadded qualifier) { + return t.qualifier == qualifier ? t : new ImportType(t.id, t.prefix, t.markers, t.hasTypeof, t.importArgument, qualifier, t.typeArguments, t.type); + } + + public @Nullable JContainer getTypeArguments() { + return t.typeArguments; + } + + public ImportType withTypeArguments(@Nullable JContainer typeArguments) { + return t.typeArguments == typeArguments ? t : new ImportType(t.id, t.prefix, t.markers, t.hasTypeof, t.importArgument, t.qualifier, typeArguments, t.type); + } + } + } + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) @RequiredArgsConstructor @@ -1266,6 +1461,39 @@ public JS.JsBinary withOperator(JLeftPadded operator) { } } + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) + @EqualsAndHashCode(callSuper = false) + @Data + @RequiredArgsConstructor + final class LiteralType implements JS, Expression, TypeTree { + @With + @EqualsAndHashCode.Include + UUID id; + + @With + Space prefix; + + @With + Markers markers; + + // Not `J.Literal` so that also literals like `-1` are captured + @With + Expression literal; + + @With + JavaType type; + + @Override + public

J acceptJavaScript(JavaScriptVisitor

v, P p) { + return v.visitLiteralType(this, p); + } + + @Override + public CoordinateBuilder.Expression getCoordinates() { + return new CoordinateBuilder.Expression(this); + } + } + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) @RequiredArgsConstructor @@ -1494,6 +1722,86 @@ public PropertyAssignment withName(JRightPadded target) { } } + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) + @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) + @RequiredArgsConstructor + @AllArgsConstructor(access = AccessLevel.PRIVATE) + final class SatisfiesExpression implements JS, Expression { + @Nullable + @NonFinal + transient WeakReference padding; + + @With + @EqualsAndHashCode.Include + @Getter + UUID id; + + @With + @Getter + Space prefix; + + @With + @Getter + Markers markers; + + @With + @Getter + J expression; + + JLeftPadded satisfiesType; + + public Expression getSatisfiesType() { + return satisfiesType.getElement(); + } + + public SatisfiesExpression withSatisfiesType(Expression expression) { + return getPadding().withSatisfiesType(this.satisfiesType.withElement(expression)); + } + + @Getter + @With + @Nullable + JavaType type; + + @Override + public

J acceptJavaScript(JavaScriptVisitor

v, P p) { + return v.visitSatisfiesExpression(this, p); + } + + @Override + public CoordinateBuilder.Expression getCoordinates() { + return new CoordinateBuilder.Expression(this); + } + + public SatisfiesExpression.Padding getPadding() { + SatisfiesExpression.Padding p; + if (this.padding == null) { + p = new SatisfiesExpression.Padding(this); + this.padding = new WeakReference<>(p); + } else { + p = this.padding.get(); + if (p == null || p.t != this) { + p = new SatisfiesExpression.Padding(this); + this.padding = new WeakReference<>(p); + } + } + return p; + } + + @RequiredArgsConstructor + public static class Padding { + private final SatisfiesExpression t; + + public @Nullable JLeftPadded getSatisfiesType() { + return t.satisfiesType; + } + + public SatisfiesExpression withSatisfiesType(@Nullable JLeftPadded satisfiesType) { + return t.satisfiesType == satisfiesType ? t : new SatisfiesExpression(t.id, t.prefix, t.markers, t.expression, satisfiesType, t.type); + } + } + } + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) @RequiredArgsConstructor @@ -2191,6 +2499,106 @@ public JS.TypeOperator withExpression(JLeftPadded expression) { } } + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) + @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) + @RequiredArgsConstructor + @AllArgsConstructor(access = AccessLevel.PRIVATE) + final class TypePredicate implements JS, Expression, TypeTree { + @Nullable + @NonFinal + transient WeakReference padding; + + @With + @EqualsAndHashCode.Include + @Getter + UUID id; + + @With + @Getter + Space prefix; + + @With + @Getter + Markers markers; + + JLeftPadded asserts; + + public boolean isAsserts() { + return asserts.getElement(); + } + + public TypePredicate withAsserts(boolean asserts) { + return getPadding().withAsserts(this.asserts.withElement(asserts)); + } + + @With + @Getter + J.Identifier parameterName; + + @Nullable + JLeftPadded expression; + + @Nullable + public Expression getExpression() { + return expression != null ? expression.getElement() : null; + } + + public TypePredicate withExpression(@Nullable Expression expression) { + return getPadding().withExpression(this.expression.withElement(expression)); + } + + @Getter + @With + @Nullable + JavaType type; + + @Override + public

J acceptJavaScript(JavaScriptVisitor

v, P p) { + return v.visitTypePredicate(this, p); + } + + @Override + public CoordinateBuilder.Expression getCoordinates() { + return new CoordinateBuilder.Expression(this); + } + + public TypePredicate.Padding getPadding() { + TypePredicate.Padding p; + if (this.padding == null) { + p = new TypePredicate.Padding(this); + this.padding = new WeakReference<>(p); + } else { + p = this.padding.get(); + if (p == null || p.t != this) { + p = new TypePredicate.Padding(this); + this.padding = new WeakReference<>(p); + } + } + return p; + } + + @RequiredArgsConstructor + public static class Padding { + private final TypePredicate t; + + public JLeftPadded getAsserts() { + return t.asserts; + } + + public TypePredicate withAsserts(JLeftPadded asserts) { + return t.asserts == asserts ? t : new TypePredicate(t.id, t.prefix, t.markers, asserts, t.parameterName, t.expression, t.type); + } + + public @Nullable JLeftPadded getExpression() { + return t.expression; + } + + public TypePredicate withExpression(@Nullable JLeftPadded expression) { + return t.expression == expression ? t : new TypePredicate(t.id, t.prefix, t.markers, t.asserts, t.parameterName, expression, t.type); + } + } + } + @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true) @RequiredArgsConstructor diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsContainer.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsContainer.java index d21d3da2..2210ef45 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsContainer.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsContainer.java @@ -32,7 +32,8 @@ public enum Location { ARRAY_BINDING_PATTERN_ELEMENTS(JsSpace.Location.ARRAY_BINDING_PATTERN_ELEMENTS_PREFIX, JsRightPadded.Location.ARRAY_BINDING_PATTERN_ELEMENTS), EXPR_WITH_TYPE_ARG_PARAMETERS(JsSpace.Location.EXPR_WITH_TYPE_ARG_PARAMETERS, JsRightPadded.Location.EXPR_WITH_TYPE_ARG_PARAMETERS_SUFFIX), TEMPLATE_EXPRESSION_TYPE_ARG_PARAMETERS(JsSpace.Location.TEMPLATE_EXPRESSION_TYPE_ARG_PARAMETERS, JsRightPadded.Location.TEMPLATE_EXPRESSION_TYPE_ARG_PARAMETERS_SUFFIX), - CONDITIONAL_TYPE_CONDITION(JsSpace.Location.CONDITIONAL_TYPE_CONDITION, JsRightPadded.Location.CONDITIONAL_TYPE_CONDITION); + CONDITIONAL_TYPE_CONDITION(JsSpace.Location.CONDITIONAL_TYPE_CONDITION, JsRightPadded.Location.CONDITIONAL_TYPE_CONDITION), + IMPORT_TYPE_TYPE_ARGUMENTS(JsSpace.Location.IMPORT_TYPE_TYPE_ARGUMENTS, JsRightPadded.Location.IMPORT_TYPE_TYPE_ARGUMENTS); private final JsSpace.Location beforeLocation; private final JsRightPadded.Location elementLocation; 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 666bd6b9..de46a0f7 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 @@ -34,7 +34,11 @@ public enum Location { JS_IMPORT_SPECIFIER_IMPORT_TYPE(JsSpace.Location.JS_IMPORT_SPECIFIER_IMPORT_TYPE_PREFIX), INDEXED_SIGNATURE_DECLARATION_TYPE_EXPRESSION(JsSpace.Location.INDEXED_SIGNATURE_DECLARATION_TYPE_EXPRESSION_PREFIX), FOR_OF_AWAIT(JsSpace.Location.FOR_OF_AWAIT_PREFIX), - ; + INFER_TYPE_PARAMETER(JsSpace.Location.INFER_TYPE_PARAMETER_PREFIX), + TYPE_PREDICATE_ASSERTS(JsSpace.Location.TYPE_PREDICATE_ASSERTS_PREFIX), + TYPE_PREDICATE_EXPRESSION(JsSpace.Location.TYPE_PREDICATE_EXPRESSION_PREFIX), + SATISFIES_EXPRESSION_TYPE(JsSpace.Location.SATISFIES_EXPRESSION_TYPE_PREFIX), + IMPORT_TYPE_QUALIFIER(JsSpace.Location.IMPORT_TYPE_QUALIFIER_PREFIX); private final JsSpace.Location beforeLocation; diff --git a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsRightPadded.java b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsRightPadded.java index d8c1a117..7d9baf43 100644 --- a/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsRightPadded.java +++ b/rewrite-javascript/src/main/java/org/openrewrite/javascript/tree/JsRightPadded.java @@ -48,7 +48,9 @@ public enum Location { TEMPLATE_EXPRESSION_TAG(JsSpace.Location.TEMPLATE_EXPRESSION_TAG_SUFFIX), TEMPLATE_EXPRESSION_TYPE_ARG_PARAMETERS_SUFFIX(JsSpace.Location.TEMPLATE_EXPRESSION_TYPE_ARG_PARAMETERS_SUFFIX), TEMPLATE_EXPRESSION_TEMPLATE_SPAN(JsSpace.Location.TEMPLATE_EXPRESSION_TEMPLATE_SPAN_SUFFIX), - CONDITIONAL_TYPE_CONDITION(JsSpace.Location.CONDITIONAL_TYPE_CONDITION_SUFFIX); + CONDITIONAL_TYPE_CONDITION(JsSpace.Location.CONDITIONAL_TYPE_CONDITION_SUFFIX), + IMPORT_TYPE_TYPEOF(JsSpace.Location.IMPORT_TYPE_TYPEOF_SUFFIX), + IMPORT_TYPE_TYPE_ARGUMENTS(JsSpace.Location.IMPORT_TYPE_TYPE_ARGUMENTS_SUFFIX); private final JsSpace.Location afterLocation; 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 858d10fb..78e19bc2 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 @@ -119,6 +119,19 @@ public enum Location { CONDITIONAL_TYPE_PREFIX, CONDITIONAL_TYPE_CONDITION, CONDITIONAL_TYPE_CONDITION_SUFFIX, + INFER_TYPE_PREFIX, + INFER_TYPE_PARAMETER_PREFIX, + TYPE_PREDICATE_PREFIX, + TYPE_PREDICATE_ASSERTS_PREFIX, + TYPE_PREDICATE_EXPRESSION_PREFIX, + LITERAL_TYPE_PREFIX, + SATISFIES_EXPRESSION_PREFIX, + SATISFIES_EXPRESSION_TYPE_PREFIX, + IMPORT_TYPE_PREFIX, + IMPORT_TYPE_TYPEOF_SUFFIX, + IMPORT_TYPE_QUALIFIER_PREFIX, + IMPORT_TYPE_TYPE_ARGUMENTS, + IMPORT_TYPE_TYPE_ARGUMENTS_SUFFIX, } }