Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement TypeScript namespace support
This also fixes enum not adding the respective declaration to the scope during the typescript visitation.
- Loading branch information
1 parent
165ef29
commit 9915c4f
Showing
47 changed files
with
469 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
205 changes: 205 additions & 0 deletions
205
packages/babel-plugin-transform-typescript/src/namespace.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
const SHARED_NAMESPACE_ERRORS = { | ||
TSEnumDeclaration: "An enum may not share the name of its parent namespace.", | ||
FunctionDeclaration: | ||
"A function may not share the name of its parent namespace.", | ||
ClassDeclaration: "A class may not share the name of its parent namespace.", | ||
VariableDeclaration: | ||
"A variable may not share the name of its parent namespace.", | ||
TSModuleDeclaration: | ||
"A namespace may not share the name of its parent namespace.", | ||
}; | ||
|
||
export default function transpileNamespace(path, t) { | ||
if (path.node.declare || path.node.id.type === "StringLiteral") { | ||
path.remove(); | ||
return; | ||
} | ||
|
||
const name = path.node.id.name; | ||
const value = handleNested(path, t, JSON.parse(JSON.stringify(path.node))); | ||
const bound = path.scope.hasOwnBinding(name); | ||
if (path.parent.type === "ExportNamedDeclaration") { | ||
if (!bound) { | ||
path.parentPath.insertAfter(value); | ||
path.replaceWith(getDeclaration(t, name)); | ||
path.scope.registerDeclaration(path.parentPath); | ||
} else { | ||
path.parentPath.replaceWith(value); | ||
} | ||
} else if (bound) { | ||
path.replaceWith(value); | ||
} else { | ||
path.scope.registerDeclaration( | ||
path.replaceWithMultiple([getDeclaration(t, name), value])[0], | ||
); | ||
} | ||
} | ||
|
||
function getDeclaration(t, name) { | ||
return t.variableDeclaration("let", [ | ||
t.variableDeclarator(t.identifier(name)), | ||
]); | ||
} | ||
|
||
function getMemberExpression(t, name, itemName) { | ||
return t.memberExpression(t.identifier(name), t.identifier(itemName)); | ||
} | ||
|
||
function handleNested(path, t, node, parentExportName) { | ||
const names = []; | ||
const name = node.id.name; | ||
const namespaceTopLevel = node.body.body; | ||
for (let i = 0; i < namespaceTopLevel.length; i++) { | ||
const subNode = namespaceTopLevel[i]; | ||
switch (subNode.type) { | ||
case "TSModuleDeclaration": { | ||
const moduleName = subNode.id.name; | ||
if (moduleName === name) { | ||
throw path.hub.file.buildCodeFrameError( | ||
subNode, | ||
SHARED_NAMESPACE_ERRORS.TSModuleDeclaration, | ||
); | ||
} | ||
if (names[moduleName]) { | ||
namespaceTopLevel[i] = handleNested(path, t, subNode); | ||
} else { | ||
names[moduleName] = true; | ||
namespaceTopLevel.splice( | ||
i++, | ||
1, | ||
getDeclaration(t, moduleName), | ||
handleNested(path, t, subNode), | ||
); | ||
} | ||
continue; | ||
} | ||
case "TSEnumDeclaration": | ||
case "FunctionDeclaration": | ||
case "ClassDeclaration": { | ||
const itemName = subNode.id.name; | ||
if (itemName === name) { | ||
throw path.hub.file.buildCodeFrameError( | ||
subNode, | ||
SHARED_NAMESPACE_ERRORS[subNode.type], | ||
); | ||
} | ||
names[itemName] = true; | ||
continue; | ||
} | ||
case "VariableDeclaration": | ||
for (const variable of subNode.declarations) { | ||
const variableName = variable.id.name; | ||
if (variableName === name) { | ||
throw path.hub.file.buildCodeFrameError( | ||
variable, | ||
SHARED_NAMESPACE_ERRORS.VariableDeclaration, | ||
); | ||
} | ||
names[variableName] = true; | ||
} | ||
continue; | ||
default: | ||
continue; | ||
case "ExportNamedDeclaration": | ||
} | ||
switch (subNode.declaration.type) { | ||
case "TSEnumDeclaration": | ||
case "FunctionDeclaration": | ||
case "ClassDeclaration": { | ||
const itemName = subNode.declaration.id.name; | ||
if (itemName === name) { | ||
throw path.hub.file.buildCodeFrameError( | ||
subNode.declaration, | ||
SHARED_NAMESPACE_ERRORS[subNode.declaration.type], | ||
); | ||
} | ||
names[itemName] = true; | ||
namespaceTopLevel.splice( | ||
i++, | ||
1, | ||
subNode.declaration, | ||
t.expressionStatement( | ||
t.assignmentExpression( | ||
"=", | ||
getMemberExpression(t, name, itemName), | ||
t.identifier(itemName), | ||
), | ||
), | ||
); | ||
break; | ||
} | ||
case "VariableDeclaration": | ||
if (subNode.declaration.kind !== "const") { | ||
throw path.hub.file.buildCodeFrameError( | ||
subNode.declaration, | ||
"Namespaces exporting non-const are unsupported.", | ||
); | ||
} | ||
for (const variable of subNode.declaration.declarations) { | ||
const variableName = variable.id.name; | ||
if (variableName === name) { | ||
throw path.hub.file.buildCodeFrameError( | ||
variable, | ||
SHARED_NAMESPACE_ERRORS.VariableDeclaration, | ||
); | ||
} | ||
variable.init = t.assignmentExpression( | ||
"=", | ||
getMemberExpression(t, name, variableName), | ||
variable.init, | ||
); | ||
} | ||
namespaceTopLevel[i] = subNode.declaration; | ||
break; | ||
case "TSModuleDeclaration": { | ||
const moduleName = subNode.declaration.id.name; | ||
if (moduleName === name) { | ||
throw path.hub.file.buildCodeFrameError( | ||
subNode.declaration, | ||
SHARED_NAMESPACE_ERRORS.TSModuleDeclaration, | ||
); | ||
} | ||
if (names[moduleName]) { | ||
namespaceTopLevel[i] = handleNested( | ||
path, | ||
t, | ||
subNode.declaration, | ||
name, | ||
); | ||
} else { | ||
names[moduleName] = true; | ||
namespaceTopLevel.splice( | ||
i++, | ||
1, | ||
getDeclaration(t, moduleName), | ||
handleNested(path, t, subNode.declaration, name), | ||
); | ||
} | ||
} | ||
} | ||
} | ||
|
||
const derivedParameter = t.logicalExpression( | ||
"||", | ||
t.identifier(name), | ||
t.assignmentExpression("=", t.identifier(name), t.objectExpression([])), | ||
); | ||
return t.expressionStatement( | ||
t.callExpression( | ||
t.functionExpression( | ||
null, | ||
[t.identifier(name)], | ||
t.blockStatement(namespaceTopLevel), | ||
), | ||
[ | ||
parentExportName | ||
? t.assignmentExpression( | ||
"=", | ||
getMemberExpression(t, parentExportName, name), | ||
derivedParameter, | ||
) | ||
: derivedParameter, | ||
], | ||
), | ||
); | ||
} |
4 changes: 4 additions & 0 deletions
4
...s/babel-plugin-transform-typescript/test/fixtures/declarations/nested-namespace/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
; // Otherwise-empty file | ||
export declare namespace P { | ||
export namespace C {} | ||
} |
1 change: 1 addition & 0 deletions
1
.../babel-plugin-transform-typescript/test/fixtures/declarations/nested-namespace/output.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
; // Otherwise-empty file |
3 changes: 3 additions & 0 deletions
3
...es/babel-plugin-transform-typescript/test/fixtures/namespace-fails/class-export/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
export class N {} | ||
} |
3 changes: 3 additions & 0 deletions
3
...babel-plugin-transform-typescript/test/fixtures/namespace-fails/class-export/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "A class may not share the name of its parent namespace." | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/babel-plugin-transform-typescript/test/fixtures/namespace-fails/class/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
class N {} | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/babel-plugin-transform-typescript/test/fixtures/namespace-fails/class/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "A class may not share the name of its parent namespace." | ||
} |
3 changes: 3 additions & 0 deletions
3
...ges/babel-plugin-transform-typescript/test/fixtures/namespace-fails/enum-export/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
export enum N {} | ||
} |
3 changes: 3 additions & 0 deletions
3
.../babel-plugin-transform-typescript/test/fixtures/namespace-fails/enum-export/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "An enum may not share the name of its parent namespace." | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/babel-plugin-transform-typescript/test/fixtures/namespace-fails/enum/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
enum N {} | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/babel-plugin-transform-typescript/test/fixtures/namespace-fails/enum/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "An enum may not share the name of its parent namespace." | ||
} |
3 changes: 3 additions & 0 deletions
3
...babel-plugin-transform-typescript/test/fixtures/namespace-fails/function-export/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
export function N() {} | ||
} |
3 changes: 3 additions & 0 deletions
3
...el-plugin-transform-typescript/test/fixtures/namespace-fails/function-export/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "A function may not share the name of its parent namespace." | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/babel-plugin-transform-typescript/test/fixtures/namespace-fails/function/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
function N() {} | ||
} |
3 changes: 3 additions & 0 deletions
3
...ges/babel-plugin-transform-typescript/test/fixtures/namespace-fails/function/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "A function may not share the name of its parent namespace." | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/babel-plugin-transform-typescript/test/fixtures/namespace-fails/mutable/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
export let V; | ||
} |
3 changes: 3 additions & 0 deletions
3
...ages/babel-plugin-transform-typescript/test/fixtures/namespace-fails/mutable/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "Namespaces exporting non-const are unsupported." | ||
} |
3 changes: 3 additions & 0 deletions
3
...abel-plugin-transform-typescript/test/fixtures/namespace-fails/namespace-export/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
export namespace N {} | ||
} |
3 changes: 3 additions & 0 deletions
3
...l-plugin-transform-typescript/test/fixtures/namespace-fails/namespace-export/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "A namespace may not share the name of its parent namespace." | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/babel-plugin-transform-typescript/test/fixtures/namespace-fails/namespace/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
namespace N {} | ||
} |
3 changes: 3 additions & 0 deletions
3
...es/babel-plugin-transform-typescript/test/fixtures/namespace-fails/namespace/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "A namespace may not share the name of its parent namespace." | ||
} |
3 changes: 3 additions & 0 deletions
3
...babel-plugin-transform-typescript/test/fixtures/namespace-fails/variable-export/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
export const N; | ||
} |
3 changes: 3 additions & 0 deletions
3
...el-plugin-transform-typescript/test/fixtures/namespace-fails/variable-export/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "A variable may not share the name of its parent namespace." | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/babel-plugin-transform-typescript/test/fixtures/namespace-fails/variable/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace N { | ||
let N; | ||
} |
3 changes: 3 additions & 0 deletions
3
...ges/babel-plugin-transform-typescript/test/fixtures/namespace-fails/variable/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"throws": "A variable may not share the name of its parent namespace." | ||
} |
35 changes: 35 additions & 0 deletions
35
packages/babel-plugin-transform-typescript/test/fixtures/namespace/canonical/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
namespace Validation { | ||
export interface StringValidator { | ||
isAcceptable(s: string): boolean; | ||
} | ||
|
||
const lettersRegexp = /^[A-Za-z]+$/; | ||
const numberRegexp = /^[0-9]+$/; | ||
|
||
export class LettersOnlyValidator implements StringValidator { | ||
constructor() { | ||
console.log("1"); | ||
} | ||
isAcceptable(s: string) { | ||
return lettersRegexp.test(s); | ||
} | ||
} | ||
|
||
export class ZipCodeValidator implements StringValidator { | ||
isAcceptable(s: string) { | ||
return s.length === 5 && numberRegexp.test(s); | ||
} | ||
} | ||
} | ||
|
||
let strings = ["Hello", "98052", "101"]; | ||
|
||
let validators: { [s: string]: Validation.StringValidator; } = {}; | ||
validators["ZIP code"] = new Validation.ZipCodeValidator(); | ||
validators["Letters only"] = new Validation.LettersOnlyValidator(); | ||
|
||
for (let s of strings) { | ||
for (let name in validators) { | ||
console.log(`"${ s }" - ${ validators[name].isAcceptable(s) ? "matches" : "does not match" } ${ name }`); | ||
} | ||
} |
Oops, something went wrong.