diff --git a/openrewrite/src/javascript/parser.ts b/openrewrite/src/javascript/parser.ts index 00753af4..605239c7 100644 --- a/openrewrite/src/javascript/parser.ts +++ b/openrewrite/src/javascript/parser.ts @@ -485,6 +485,14 @@ export class JavaScriptParserVisitor { return this.mapIdentifier(node, 'undefined'); } + visitAnyKeyword(node: ts.Node) { + return this.mapIdentifier(node, 'any'); + } + + visitUnknownKeyword(node: ts.Node) { + return this.mapIdentifier(node, 'unknown'); + } + visitVoidKeyword(node: ts.Node) { return this.mapIdentifier(node, 'void'); } @@ -1566,11 +1574,50 @@ export class JavaScriptParserVisitor { } visitThrowStatement(node: ts.ThrowStatement) { - return this.visitUnknown(node); + return new J.Throw( + randomId(), + this.prefix(node), + Markers.EMPTY, + this.visit(node.expression) + ); } visitTryStatement(node: ts.TryStatement) { - return this.visitUnknown(node); + return new J.Try( + randomId(), + this.prefix(node), + Markers.EMPTY, + null, + this.visit(node.tryBlock), + node.catchClause ? + [new J.Try.Catch( + randomId(), + this.prefix(node.catchClause.getFirstToken()!), + Markers.EMPTY, + new J.ControlParentheses( + randomId(), + this.suffix(node.catchClause.getFirstToken()!), + Markers.EMPTY, + this.rightPadded( + new J.VariableDeclarations( + randomId(), + this.prefix(node.catchClause.variableDeclaration!), + Markers.EMPTY, + [], + [], + this.mapTypeInfo(node.catchClause.variableDeclaration!), + null, + [], + [this.rightPadded(this.visit(node.catchClause.variableDeclaration!), Space.EMPTY)] + ), + this.suffix(node.catchClause.variableDeclaration!)) + ), + this.visit(node.catchClause?.block!) + )] : [], + node.finallyBlock ? this.leftPadded( + this.prefix(node.getChildren().find(n => n.kind === ts.SyntaxKind.FinallyKeyword)!), this.visit(node.finallyBlock)) + : null + ); } visitDebuggerStatement(node: ts.DebuggerStatement) { diff --git a/openrewrite/test/javascript/parser/throw.test.ts b/openrewrite/test/javascript/parser/throw.test.ts new file mode 100644 index 00000000..e8d3f362 --- /dev/null +++ b/openrewrite/test/javascript/parser/throw.test.ts @@ -0,0 +1,40 @@ +import {connect, disconnect, rewriteRun, typeScript} from '../testHarness'; + +describe('throw mapping', () => { + beforeAll(() => connect()); + afterAll(() => disconnect()); + + test('simple throw', () => { + rewriteRun( + //language=typescript + typeScript(` + throw new Error("Cannot divide by zero!"); + `) + ); + }); + + test('simple throw with comments', () => { + rewriteRun( + //language=typescript + typeScript(` + /*a*/ throw /*b*/ new /*c*/ Error/*d*/(/*e*/'Cannot divide by zero!'/*f*/)/*g*/; + `) + ); + }); + + test('re-throwing', () => { + rewriteRun( + //language=typescript + typeScript(` + function riskyOperation() { + try { + throw new Error("An error occurred during risky operation."); + } catch (error) { + console.error("Logging Error:", (error as Error).message); + throw error; // Re-throw the error to be handled at a higher level + } + } + `) + ); + }); +}); diff --git a/openrewrite/test/javascript/parser/try-catch.test.ts b/openrewrite/test/javascript/parser/try-catch.test.ts new file mode 100644 index 00000000..75a00021 --- /dev/null +++ b/openrewrite/test/javascript/parser/try-catch.test.ts @@ -0,0 +1,128 @@ +import {connect, disconnect, rewriteRun, typeScript} from '../testHarness'; + +describe('try-catch mapping', () => { + beforeAll(() => connect()); + afterAll(() => disconnect()); + + test('try-catch empty', () => { + rewriteRun( + //language=typescript + typeScript(` + try { + } catch (error) { + } + `) + ); + }); + + test('try-finally empty', () => { + rewriteRun( + //language=typescript + typeScript(` + try { + } finally { + } + `) + ); + }); + + test('try-catch-finally empty', () => { + rewriteRun( + //language=typescript + typeScript(` + try { + } catch (error) { + } finally { + } + `) + ); + }); + + test('try-catch-finally empty comments', () => { + rewriteRun( + //language=typescript + typeScript(` + /*a*/ try /*b*/ { + } /*c*/ catch /*d*/ ( /*e*/ error /*f*/) { /*g*/ + } /*h*/ finally /*i*/ { /*j*/ + } /*k*/ + `) + ); + }); + + test('try-catch with typed unknown error', () => { + rewriteRun( + //language=typescript + typeScript(` + try { + // error + } catch (error: unknown) { + // handel error + } + `) + ); + }); + + test('try-catch with typed any error', () => { + rewriteRun( + //language=typescript + typeScript(` + try { + // error + } catch (error: any) { + // handel error + } + `) + ); + }); + + test('try-catch with typed error and comments', () => { + rewriteRun( + //language=typescript + typeScript(` + try { + // error + } catch (/*a*/ error /*b*/: /*c*/ unknown /*d*/) { + // handel error + } + `) + ); + }); + + test('try-catch-finally with body', () => { + rewriteRun( + //language=typescript + typeScript(` + try { + // Try to parse JSON string + const data = JSON.parse('{ "name": "Alice" }'); + console.log(data.name); // Output: "Alice" + } catch (error: unknown) { + if (error instanceof Error) { + console.error("Caught an error:", error.message); + } else { + console.error("An unknown error occurred"); + } + } finally { + console.log("Parsing attempt finished."); + } + `) + ); + }); + + test('try-catch-finally with throw', () => { + rewriteRun( + //language=typescript + typeScript(` + try { + throw new Error("Failed to perform database operation."); + } catch (error) { + console.error("Database Error:", (error as Error).message); + } finally { + console.log("Clean."); + } + `) + ); + }); + +}); diff --git a/openrewrite/test/javascript/parser/variableDeclarations.test.ts b/openrewrite/test/javascript/parser/variableDeclarations.test.ts index 4e9dcb92..c3a39879 100644 --- a/openrewrite/test/javascript/parser/variableDeclarations.test.ts +++ b/openrewrite/test/javascript/parser/variableDeclarations.test.ts @@ -54,6 +54,18 @@ describe('variable declaration mapping', () => { typeScript('let a : number =2') ); }); + test('typed unknown', () => { + rewriteRun( + //language=typescript + typeScript('const a : unknown') + ); + }); + test('typed any', () => { + rewriteRun( + //language=typescript + typeScript('let a : any = 2;') + ); + }); test('multi', () => { rewriteRun( //language=typescript