Skip to content

Commit

Permalink
Implemented support for ConstructSignature (#141)
Browse files Browse the repository at this point in the history
* Implemented support for ConstructSignature
  • Loading branch information
arodionov authored Nov 13, 2024
1 parent 79ea7e0 commit ac916bb
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 15 deletions.
48 changes: 39 additions & 9 deletions openrewrite/src/javascript/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
} from "../core";
import {binarySearch, compareTextSpans, getNextSibling, TextSpan} from "./parserUtils";
import {JavaScriptTypeMapping} from "./typeMapping";
import {SignatureDeclarationBase} from "typescript";

export class JavaScriptParser extends Parser {

Expand Down Expand Up @@ -820,7 +819,6 @@ export class JavaScriptParserVisitor {
Markers.EMPTY,
[], // no decorators allowed
[], // no modifiers allowed

this.mapTypeParametersAsObject(node),
this.mapTypeInfo(node),
this.getOptionalUnary(node),
Expand Down Expand Up @@ -894,7 +892,8 @@ 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.PropertySignature | ts.MethodSignature | ts.ArrowFunction | ts.CallSignatureDeclaration | ts.GetAccessorDeclaration
| ts.FunctionDeclaration | ts.ConstructSignatureDeclaration) {
return node.type ? new JS.TypeInfo(randomId(), this.prefix(node.getChildAt(node.getChildren().indexOf(node.type) - 1)), Markers.EMPTY, this.visit(node.type)) : null;
}

Expand All @@ -903,7 +902,7 @@ export class JavaScriptParserVisitor {
randomId(),
this.prefix(node),
Markers.EMPTY,
new JRightPadded(true,this.prefix(node.body.getChildren().find(v => v.kind === ts.SyntaxKind.OpenBraceToken)!), Markers.EMPTY),
new JRightPadded(true, this.prefix(this.findChildNode(node.body, ts.SyntaxKind.OpenBraceToken)!), Markers.EMPTY),
node.body.statements.map(ce => new JRightPadded(
this.convert(ce),
ce.getLastToken()?.kind === ts.SyntaxKind.SemicolonToken ? this.prefix(ce.getLastToken()!) : Space.EMPTY,
Expand Down Expand Up @@ -1004,7 +1003,32 @@ export class JavaScriptParserVisitor {
}

visitConstructSignature(node: ts.ConstructSignatureDeclaration) {
return this.visitUnknown(node);
return new J.MethodDeclaration(
randomId(),
this.prefix(node),
Markers.EMPTY,
[], // no decorators allowed
[], // no modifiers allowed
this.mapTypeParametersAsObject(node),
this.mapTypeInfo(node),
new J.MethodDeclaration.IdentifierWithAnnotations(
new J.Identifier(
randomId(),
Space.EMPTY,
Markers.EMPTY,
[],
'new',
null,
null
),
[]
),
this.mapCommaSeparatedList(this.getParameterListNodes(node)),
null,
null,
null,
this.mapMethodType(node)
);
}

visitIndexSignature(node: ts.IndexSignatureDeclaration) {
Expand Down Expand Up @@ -2559,10 +2583,16 @@ export class JavaScriptParserVisitor {
: null;
}

private mapTypeParametersAsObject(node: ts.MethodDeclaration | ts.MethodSignature | ts.FunctionDeclaration | ts.CallSignatureDeclaration) : J.TypeParameters | null {
return node.typeParameters
? new J.TypeParameters(randomId(), node.questionToken ? this.suffix(node.questionToken) : node.name ? this.suffix(node.name) : Space.EMPTY, Markers.EMPTY, [], node.typeParameters.map(tp => this.rightPadded(this.visit(tp), this.suffix(tp))))
: null;
private mapTypeParametersAsObject(node: ts.MethodDeclaration | ts.MethodSignature | ts.FunctionDeclaration | ts.CallSignatureDeclaration | ts.ConstructSignatureDeclaration) : J.TypeParameters | null {
if (!node.typeParameters) return null;

let ts_prefix;
if (ts.isConstructSignatureDeclaration(node)) {
ts_prefix = this.suffix(this.findChildNode(node, ts.SyntaxKind.NewKeyword)!);
} else {
ts_prefix = node.questionToken ? this.suffix(node.questionToken) : node.name ? this.suffix(node.name) : Space.EMPTY;
}
return new J.TypeParameters(randomId(), ts_prefix, Markers.EMPTY, [], node.typeParameters.map(tp => this.rightPadded(this.visit(tp), this.suffix(tp))));
}

private mapTypeParametersList(typeParamsNodeArray: ts.NodeArray<ts.TypeParameterDeclaration>) : JRightPadded<J.TypeParameter>[] {
Expand Down
23 changes: 17 additions & 6 deletions openrewrite/test/javascript/parser/interface.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {connect, disconnect, rewriteRun, typeScript} from '../testHarness';

describe('as mapping', () => {
describe('interface mapping', () => {
beforeAll(() => connect());
afterAll(() => disconnect());

Expand Down Expand Up @@ -186,7 +186,7 @@ describe('as mapping', () => {
);
});

test.skip('interface with constructor signature', () => {
test('interface with constructor signature', () => {
rewriteRun(
//language=typescript
typeScript(`
Expand All @@ -197,12 +197,23 @@ describe('as mapping', () => {
);
});

test.skip('interface with optional constructor signature', () => {
test('interface with constructor signature with type parameters', () => {
rewriteRun(
//language=typescript
typeScript(`
interface Constructible {
new? (name: string, age: number): Person; // Interface that defines a constructor signature
interface GenericConstructor {
new<R, T> (value: R, value: T): GenericClass;
}
`)
);
});

test('interface with constructor signature with type parameters and comments', () => {
rewriteRun(
//language=typescript
typeScript(`
interface GenericConstructor {
/*a*/new /*b*/</*c*/R/*d*/,/*e*/ T/*f*/>/*g*/ (value1: R, value2: T)/*e*/: GenericClass/*j*/;
}
`)
);
Expand Down Expand Up @@ -372,7 +383,7 @@ describe('as mapping', () => {
//language=typescript
typeScript(`
interface X {
find ? <R, T> (v1: R, v2: T): string;
find ? <R, T> (v1: R, v2: T): string;
}
`)
);
Expand Down

0 comments on commit ac916bb

Please sign in to comment.