Skip to content

Commit

Permalink
- introduced JS.SatisfiesExpression
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrii Rodionov committed Nov 28, 2024
1 parent bc58313 commit df99153
Show file tree
Hide file tree
Showing 15 changed files with 331 additions and 5 deletions.
9 changes: 8 additions & 1 deletion openrewrite/src/javascript/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2254,7 +2254,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) {
Expand Down
23 changes: 22 additions & 1 deletion openrewrite/src/javascript/remote/receiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, InferType, JsImport, JsImportSpecifier, JsBinary, LiteralType, ObjectBindingDeclarations, PropertyAssignment, 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 {JS, JsLeftPadded, JsRightPadded, JsContainer, JsSpace, CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, InferType, 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";

Expand Down Expand Up @@ -217,6 +217,16 @@ class Visitor extends JavaScriptVisitor<ReceiverContext> {
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)!);
Expand Down Expand Up @@ -1387,6 +1397,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<J>(null, ctx.receiveTree)!,
ctx.receiveNode<JLeftPadded<Expression>>(null, receiveLeftPaddedTree)!,
ctx.receiveValue(null, ValueType.Object)
);
}

if (type === "org.openrewrite.javascript.tree.JS$ScopedVariableDeclarations") {
return new ScopedVariableDeclarations(
ctx.receiveValue(null, ValueType.UUID)!,
Expand Down
12 changes: 11 additions & 1 deletion openrewrite/src/javascript/remote/sender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, InferType, JsImport, JsImportSpecifier, JsBinary, LiteralType, ObjectBindingDeclarations, PropertyAssignment, 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 {JS, JsLeftPadded, JsRightPadded, JsContainer, JsSpace, CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, InferType, 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";

Expand Down Expand Up @@ -212,6 +212,16 @@ class Visitor extends JavaScriptVisitor<SenderContext> {
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);
Expand Down
2 changes: 2 additions & 0 deletions openrewrite/src/javascript/tree/support_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ export namespace JsSpace {
INFER_TYPE_PREFIX,
TYPE_PREDICATE_PREFIX,
LITERAL_TYPE_PREFIX,
SATISFIES_EXPRESSION_PREFIX,
}
}
export namespace JsLeftPadded {
Expand Down Expand Up @@ -272,6 +273,7 @@ export namespace JsLeftPadded {
INFER_TYPE_TYPE_PARAMETER,
TYPE_PREDICATE_ASSERTS,
TYPE_PREDICATE_EXPRESSION,
SATISFIES_EXPRESSION_SATISFIES_TYPE,
}
}
export namespace JsRightPadded {
Expand Down
90 changes: 90 additions & 0 deletions openrewrite/src/javascript/tree/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1713,6 +1713,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<Expression>, _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<Expression>;

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<P>(v: JavaScriptVisitor<P>, p: P): J | null {
return v.visitSatisfiesExpression(this, p);
}

get padding() {
const t = this;
return new class {
public get satisfiesType(): JLeftPadded<Expression> {
return t._satisfiesType;
}
public withSatisfiesType(satisfiesType: JLeftPadded<Expression>): 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<ScopedVariableDeclarations.Scope> | null, variables: JRightPadded<J>[]) {
Expand Down
16 changes: 15 additions & 1 deletion openrewrite/src/javascript/visitor.ts
Original file line number Diff line number Diff line change
@@ -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, InferType, JsImport, JsImportSpecifier, JsBinary, LiteralType, ObjectBindingDeclarations, PropertyAssignment, 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 {CompilationUnit, Alias, ArrowFunction, Await, ConditionalType, DefaultType, Delete, Export, ExpressionStatement, ExpressionWithTypeArguments, FunctionType, InferType, 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";
Expand Down Expand Up @@ -275,6 +275,20 @@ export class JavaScriptVisitor<P> extends JavaVisitor<P> {
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;
Expand Down
35 changes: 35 additions & 0 deletions openrewrite/test/javascript/parser/expressionStatement.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> = {
data: T;
status: "success" | "error";
};
const response = {
data: { userId: 1 },
status: "success",
} satisfies ApiResponse<{ userId: number }>;
`)
);
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,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));
Expand Down Expand Up @@ -1510,6 +1521,17 @@ public <T> T create(Class<T> 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),
Expand Down
Loading

0 comments on commit df99153

Please sign in to comment.