Skip to content

Commit

Permalink
More class declaration support
Browse files Browse the repository at this point in the history
  • Loading branch information
knutwannheden committed Sep 27, 2024
1 parent 9a6ae6a commit 777319f
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 7 deletions.
46 changes: 41 additions & 5 deletions openrewrite/src/javascript/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
JRightPadded,
Space,
Statement,
TextComment
TextComment, TypeTree
} from '../java/tree';
import * as JS from './tree';
import {
Expand Down Expand Up @@ -259,14 +259,46 @@ export class JavaScriptParserVisitor {
node.name ? this.convert(node.name) : this.mapIdentifier(node, ""),
this.mapTypeParameters(node),
null, // FIXME primary constructor
node.heritageClauses ? this.visit(node.heritageClauses[0]) : null,
node.heritageClauses ? this.visit(node.heritageClauses[1]) : null,
this.mapExtends(node),
this.mapImplements(node),
null,
this.convertBlock(node.getChildren().slice(-3)),
this.mapType(node)
);
}

private mapExtends(node: ts.ClassDeclaration): JLeftPadded<TypeTree> | null {
if (node.heritageClauses == undefined || node.heritageClauses.length == 0) {
return null;
}
for (let heritageClause of node.heritageClauses) {
if (heritageClause.token == ts.SyntaxKind.ExtendsKeyword) {
return this.leftPadded(this.prefix(heritageClause.getFirstToken()!), this.visit(heritageClause.types[0]));
}
}
return null;
}

private mapImplements(node: ts.ClassDeclaration): JContainer<TypeTree> | null {
if (node.heritageClauses == undefined || node.heritageClauses.length == 0) {
return null;
}
for (let heritageClause of node.heritageClauses) {
if (heritageClause.token == ts.SyntaxKind.ImplementsKeyword) {
const _implements: JRightPadded<TypeTree>[] = [];
for (let type of heritageClause.types) {
_implements.push(this.rightPadded(this.visit(type), this.suffix(type)));
}
return _implements.length > 0 ? new JContainer(
this.prefix(heritageClause.getFirstToken()!),
_implements,
Markers.EMPTY
) : null;
}
}
return null;
}

visitNumericLiteral(node: ts.NumericLiteral) {
return this.mapLiteral(node, node.text); // FIXME value not in AST
}
Expand Down Expand Up @@ -927,7 +959,11 @@ export class JavaScriptParserVisitor {
}

visitExpressionWithTypeArguments(node: ts.ExpressionWithTypeArguments) {
return this.visitUnknown(node);
if (node.typeArguments) {
// FIXME
return this.visitUnknown(node);
}
return this.visit(node.expression);
}

visitAsExpression(node: ts.AsExpression) {
Expand Down Expand Up @@ -1244,7 +1280,7 @@ export class JavaScriptParserVisitor {
}

visitHeritageClause(node: ts.HeritageClause) {
return this.visitUnknown(node);
return this.convert(node.types[0]);
}

visitCatchClause(node: ts.CatchClause) {
Expand Down
6 changes: 5 additions & 1 deletion openrewrite/src/javascript/parserUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ export function getNextSibling(node: ts.Node): ts.Node | null {
}

// If the node is the last child in the SyntaxList, recursively check the parent's next sibling
if (nodeIndex === 0) {
if (nodeIndex === children.length - 1) {
const syntaxListIndex = parent.getChildren().indexOf(syntaxList);
if (parent.getChildCount() > syntaxListIndex + 1) {
return parent.getChildAt(syntaxListIndex + 1);
}
const parentNextSibling = getNextSibling(parent);
if (!parentNextSibling) {
return null;
Expand Down
25 changes: 24 additions & 1 deletion openrewrite/test/javascript/parser/class.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,34 @@ describe('class mapping', () => {
typeScript('class A {}')
);
});

test('body', () => {
rewriteRun(
//language=typescript
typeScript('class A { foo: number; }')
);
});
test('extends', () => {
rewriteRun(
//language=typescript
typeScript('class A extends Object {}')
);
});
test('implements single', () => {
rewriteRun(
//language=typescript
typeScript('class A implements B {}')
);
});
test('implements multiple', () => {
rewriteRun(
//language=typescript
typeScript('class A implements B , C,D {}')
);
});
test('extends and implements', () => {
rewriteRun(
//language=typescript
typeScript('class A extends Object implements B , C,D {}')
);
});
});

0 comments on commit 777319f

Please sign in to comment.