From 67984deabe1fd840965bafcf9c1f80c2d30afdaf Mon Sep 17 00:00:00 2001 From: Reyad Attiyat Date: Tue, 23 May 2017 23:33:32 -0500 Subject: [PATCH 1/2] Fix: Only set optional property on certain node property (fixes #289) --- lib/convert.js | 30 +- ...with-optional-property-undefined.result.js | 319 ++++++++++++++++++ ...ss-with-optional-property-undefined.src.ts | 4 + 3 files changed, 344 insertions(+), 9 deletions(-) create mode 100644 tests/fixtures/typescript/basics/class-with-optional-property-undefined.result.js create mode 100644 tests/fixtures/typescript/basics/class-with-optional-property-undefined.src.ts diff --git a/lib/convert.js b/lib/convert.js index 8bd3cf7..f080880 100644 --- a/lib/convert.js +++ b/lib/convert.js @@ -342,15 +342,6 @@ module.exports = function convert(config) { type: AST_NODE_TYPES.Identifier, name: nodeUtils.unescapeIdentifier(node.text) }); - if (node.parent.questionToken && ( - SyntaxKind.Parameter === node.parent.kind || - SyntaxKind.PropertyDeclaration === node.parent.kind || - SyntaxKind.PropertySignature === node.parent.kind || - SyntaxKind.MethodDeclaration === node.parent.kind || - SyntaxKind.MethodSignature === node.parent.kind - )) { - result.optional = true; - } break; case SyntaxKind.WithStatement: @@ -691,6 +682,10 @@ module.exports = function convert(config) { decorators: convertDecorators(node.decorators), typeAnnotation: (node.type) ? convertTypeAnnotation(node.type) : null }); + + if (node.name.kind === SyntaxKind.Identifier && node.questionToken) { + result.key.optional = true; + } break; } @@ -769,6 +764,10 @@ module.exports = function convert(config) { } + if (result.key.type === AST_NODE_TYPES.Identifier && node.questionToken) { + result.key.optional = true; + } + if (node.kind === SyntaxKind.GetAccessor) { result.kind = "get"; } else if (node.kind === SyntaxKind.SetAccessor) { @@ -1113,6 +1112,10 @@ module.exports = function convert(config) { }); } + if (node.questionToken) { + parameter.optional = true; + } + if (node.modifiers) { return { type: AST_NODE_TYPES.TSParameterProperty, @@ -1767,6 +1770,15 @@ module.exports = function convert(config) { }); break; + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodSignature: + deeplyCopy(); + + if (node.questionToken) { + result.name.optional = true; + } + break; + default: deeplyCopy(); } diff --git a/tests/fixtures/typescript/basics/class-with-optional-property-undefined.result.js b/tests/fixtures/typescript/basics/class-with-optional-property-undefined.result.js new file mode 100644 index 0000000..efbe484 --- /dev/null +++ b/tests/fixtures/typescript/basics/class-with-optional-property-undefined.result.js @@ -0,0 +1,319 @@ +module.exports = { + "type": "Program", + "range": [ + 0, + 39 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "body": [ + { + "type": "ClassDeclaration", + "range": [ + 0, + 39 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "range": [ + 6, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "name": "X" + }, + "body": { + "type": "ClassBody", + "body": [ + { + "type": "ClassProperty", + "range": [ + 12, + 37 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 27 + } + }, + "key": { + "type": "Identifier", + "range": [ + 20, + 23 + ], + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "name": "foo", + "optional": true + }, + "value": { + "type": "Identifier", + "range": [ + 27, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 26 + } + }, + "name": "undefined" + }, + "computed": false, + "static": false, + "accessibility": "private", + "decorators": [], + "typeAnnotation": null + } + ], + "range": [ + 8, + 39 + ], + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 3, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "decorators": [] + } + ], + "sourceType": "script", + "tokens": [ + { + "type": "Keyword", + "value": "class", + "range": [ + 0, + 5 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 5 + } + } + }, + { + "type": "Identifier", + "value": "X", + "range": [ + 6, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 8, + 9 + ], + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 9 + } + } + }, + { + "type": "Keyword", + "value": "private", + "range": [ + 12, + 19 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 9 + } + } + }, + { + "type": "Identifier", + "value": "foo", + "range": [ + 20, + 23 + ], + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 13 + } + } + }, + { + "type": "Punctuator", + "value": "?", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 2, + "column": 13 + }, + "end": { + "line": 2, + "column": 14 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 25, + 26 + ], + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 2, + "column": 16 + } + } + }, + { + "type": "Keyword", + "value": "undefined", + "range": [ + 27, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 26 + } + } + }, + { + "type": "Punctuator", + "value": ";", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 2, + "column": 26 + }, + "end": { + "line": 2, + "column": 27 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 38, + 39 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + } + } + ] +}; + diff --git a/tests/fixtures/typescript/basics/class-with-optional-property-undefined.src.ts b/tests/fixtures/typescript/basics/class-with-optional-property-undefined.src.ts new file mode 100644 index 0000000..126d595 --- /dev/null +++ b/tests/fixtures/typescript/basics/class-with-optional-property-undefined.src.ts @@ -0,0 +1,4 @@ +class X { + private foo? = undefined; +} + From d168ec85c8e22559fc39d3fb5b5c2514cf02ac17 Mon Sep 17 00:00:00 2001 From: Reyad Attiyat Date: Fri, 26 May 2017 09:57:06 -0500 Subject: [PATCH 2/2] Add optional flag for computed properties --- lib/convert.js | 4 + ...-with-optional-computed-property.result.js | 355 ++++++++++++++++++ ...ass-with-optional-computed-property.src.ts | 3 + 3 files changed, 362 insertions(+) create mode 100644 tests/fixtures/typescript/basics/class-with-optional-computed-property.result.js create mode 100644 tests/fixtures/typescript/basics/class-with-optional-computed-property.src.ts diff --git a/lib/convert.js b/lib/convert.js index f080880..9931e49 100644 --- a/lib/convert.js +++ b/lib/convert.js @@ -686,6 +686,10 @@ module.exports = function convert(config) { if (node.name.kind === SyntaxKind.Identifier && node.questionToken) { result.key.optional = true; } + + if (result.key.type === AST_NODE_TYPES.Literal && node.questionToken) { + result.optional = true; + } break; } diff --git a/tests/fixtures/typescript/basics/class-with-optional-computed-property.result.js b/tests/fixtures/typescript/basics/class-with-optional-computed-property.result.js new file mode 100644 index 0000000..a679aef --- /dev/null +++ b/tests/fixtures/typescript/basics/class-with-optional-computed-property.result.js @@ -0,0 +1,355 @@ +module.exports = { + "type": "Program", + "range": [ + 0, + 45 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "body": [ + { + "type": "ClassDeclaration", + "range": [ + 0, + 45 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "range": [ + 6, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "name": "X" + }, + "body": { + "type": "ClassBody", + "body": [ + { + "type": "ClassProperty", + "range": [ + 14, + 43 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 33 + } + }, + "key": { + "type": "Literal", + "range": [ + 23, + 28 + ], + "loc": { + "start": { + "line": 2, + "column": 13 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "value": "foo", + "raw": "'foo'" + }, + "value": { + "type": "Identifier", + "range": [ + 33, + 42 + ], + "loc": { + "start": { + "line": 2, + "column": 23 + }, + "end": { + "line": 2, + "column": 32 + } + }, + "name": "undefined" + }, + "computed": true, + "static": false, + "accessibility": "private", + "decorators": [], + "typeAnnotation": null, + "optional": true + } + ], + "range": [ + 8, + 45 + ], + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 3, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "decorators": [] + } + ], + "sourceType": "script", + "tokens": [ + { + "type": "Keyword", + "value": "class", + "range": [ + 0, + 5 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 5 + } + } + }, + { + "type": "Identifier", + "value": "X", + "range": [ + 6, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 8, + 9 + ], + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 9 + } + } + }, + { + "type": "Keyword", + "value": "private", + "range": [ + 14, + 21 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 11 + } + } + }, + { + "type": "Punctuator", + "value": "[", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "line": 2, + "column": 12 + }, + "end": { + "line": 2, + "column": 13 + } + } + }, + { + "type": "String", + "value": "'foo'", + "range": [ + 23, + 28 + ], + "loc": { + "start": { + "line": 2, + "column": 13 + }, + "end": { + "line": 2, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "]", + "range": [ + 28, + 29 + ], + "loc": { + "start": { + "line": 2, + "column": 18 + }, + "end": { + "line": 2, + "column": 19 + } + } + }, + { + "type": "Punctuator", + "value": "?", + "range": [ + 29, + 30 + ], + "loc": { + "start": { + "line": 2, + "column": 19 + }, + "end": { + "line": 2, + "column": 20 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 31, + 32 + ], + "loc": { + "start": { + "line": 2, + "column": 21 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + { + "type": "Keyword", + "value": "undefined", + "range": [ + 33, + 42 + ], + "loc": { + "start": { + "line": 2, + "column": 23 + }, + "end": { + "line": 2, + "column": 32 + } + } + }, + { + "type": "Punctuator", + "value": ";", + "range": [ + 42, + 43 + ], + "loc": { + "start": { + "line": 2, + "column": 32 + }, + "end": { + "line": 2, + "column": 33 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 44, + 45 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + } + } + ] +}; diff --git a/tests/fixtures/typescript/basics/class-with-optional-computed-property.src.ts b/tests/fixtures/typescript/basics/class-with-optional-computed-property.src.ts new file mode 100644 index 0000000..5dd15f3 --- /dev/null +++ b/tests/fixtures/typescript/basics/class-with-optional-computed-property.src.ts @@ -0,0 +1,3 @@ +class X { + private ['foo']? = undefined; +}