-
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(bug): adds support for missing node types
- Loading branch information
Showing
124 changed files
with
1,366 additions
and
781 deletions.
There are no files selected for viewing
15 changes: 15 additions & 0 deletions
15
src/service/transformer/declaration-bundler/declaration-bundler.ts
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,15 @@ | ||
import {CustomTransformers} from "typescript"; | ||
import {IDeclarationBundlerOptions} from "./i-declaration-bundler-options"; | ||
import {updateExports} from "./update-exports/update-exports"; | ||
import {deconflict} from "./deconflict/deconflict"; | ||
|
||
/** | ||
* Will bundle declaration files | ||
* @param {IDeclarationBundlerOptions} options | ||
* @returns {CustomTransformers} | ||
*/ | ||
export function declarationBundler(options: IDeclarationBundlerOptions): CustomTransformers { | ||
return { | ||
afterDeclarations: [deconflict(options), updateExports(options)] | ||
}; | ||
} |
8 changes: 8 additions & 0 deletions
8
src/service/transformer/declaration-bundler/deconflict/deconflict-visitor-options.ts
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,8 @@ | ||
import {Identifier, Node, VisitResult} from "typescript"; | ||
|
||
export interface DeconflictVisitorOptions<T extends Node = Node> { | ||
node: T; | ||
|
||
updateIdentifierIfNeeded<U extends Identifier | undefined>(identifier: U): U extends undefined ? undefined : Identifier; | ||
continuation<U extends Node>(node: U): VisitResult<U>; | ||
} |
177 changes: 177 additions & 0 deletions
177
src/service/transformer/declaration-bundler/deconflict/deconflict.ts
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,177 @@ | ||
import { | ||
createIdentifier, | ||
Identifier, | ||
isArrayBindingPattern, | ||
isBindingElement, | ||
isClassDeclaration, | ||
isEnumDeclaration, | ||
isFunctionDeclaration, | ||
isIdentifier, | ||
isInterfaceDeclaration, | ||
isObjectBindingPattern, | ||
isOmittedExpression, | ||
isTypeAliasDeclaration, | ||
isVariableDeclaration, | ||
isVariableDeclarationList, | ||
isVariableStatement, | ||
Node, | ||
SourceFile, | ||
TransformerFactory, | ||
updateSourceFileNode, | ||
visitEachChild, | ||
VisitResult | ||
} from "typescript"; | ||
import {IDeclarationBundlerOptions} from "../i-declaration-bundler-options"; | ||
import {getChunkFilename} from "../util/get-chunk-filename/get-chunk-filename"; | ||
import {traceIdentifiersForClassDeclaration} from "./visitor/trace-identifiers/trace-identifiers-for-class-declaration"; | ||
import {traceIdentifiersForEnumDeclaration} from "./visitor/trace-identifiers/trace-identifiers-for-enum-declaration"; | ||
import {traceIdentifiersForFunctionDeclaration} from "./visitor/trace-identifiers/trace-identifiers-for-function-declaration"; | ||
import {traceIdentifiersForInterfaceDeclaration} from "./visitor/trace-identifiers/trace-identifiers-for-interface-declaration"; | ||
import {traceIdentifiersForTypeAliasDeclaration} from "./visitor/trace-identifiers/trace-identifiers-for-type-alias-declaration"; | ||
import {traceIdentifiersForVariableStatement} from "./visitor/trace-identifiers/trace-identifiers-for-variable-statement"; | ||
import {traceIdentifiersForBindingElement} from "./visitor/trace-identifiers/trace-identifiers-for-binding-element"; | ||
import {traceIdentifiersForBindingPattern} from "./visitor/trace-identifiers/trace-identifiers-for-binding-pattern"; | ||
import {traceIdentifiersForIdentifier} from "./visitor/trace-identifiers/trace-identifiers-for-identifier"; | ||
import {traceIdentifiersForOmittedExpression} from "./visitor/trace-identifiers/trace-identifiers-for-omitted-expression"; | ||
import {traceIdentifiersForVariableDeclaration} from "./visitor/trace-identifiers/trace-identifiers-for-variable-declaration"; | ||
import {traceIdentifiersForVariableDeclarationList} from "./visitor/trace-identifiers/trace-identifiers-for-variable-declaration-list"; | ||
import {TraceIdentifiersVisitorOptions} from "./trace-identifiers-visitor-options"; | ||
import {DeconflictVisitorOptions} from "./deconflict-visitor-options"; | ||
import {deconflictIdentifier} from "./visitor/deconflict/deconflict-identifier"; | ||
|
||
/** | ||
* Traces identifiers for the given Node, potentially generating new unique variable names for them | ||
* @param {Node} node | ||
* @param {TraceIdentifiersVisitorOptions} options | ||
* @returns {Node | undefined} | ||
*/ | ||
function traceIdentifiers({node, ...rest}: TraceIdentifiersVisitorOptions): void { | ||
if (isBindingElement(node)) return traceIdentifiersForBindingElement({...rest, node}); | ||
else if (isArrayBindingPattern(node) || isObjectBindingPattern(node)) return traceIdentifiersForBindingPattern({...rest, node}); | ||
else if (isClassDeclaration(node)) return traceIdentifiersForClassDeclaration({...rest, node}); | ||
else if (isEnumDeclaration(node)) return traceIdentifiersForEnumDeclaration({...rest, node}); | ||
else if (isFunctionDeclaration(node)) return traceIdentifiersForFunctionDeclaration({...rest, node}); | ||
else if (isIdentifier(node)) return traceIdentifiersForIdentifier({...rest, node}); | ||
else if (isInterfaceDeclaration(node)) return traceIdentifiersForInterfaceDeclaration({...rest, node}); | ||
else if (isOmittedExpression(node)) return traceIdentifiersForOmittedExpression({...rest, node}); | ||
else if (isTypeAliasDeclaration(node)) return traceIdentifiersForTypeAliasDeclaration({...rest, node}); | ||
else if (isVariableDeclaration(node)) return traceIdentifiersForVariableDeclaration({...rest, node}); | ||
else if (isVariableDeclarationList(node)) return traceIdentifiersForVariableDeclarationList({...rest, node}); | ||
else if (isVariableStatement(node)) return traceIdentifiersForVariableStatement({...rest, node}); | ||
} | ||
|
||
/** | ||
* Deconflicts the given Node | ||
* @param {DeconflictVisitorOptions} options | ||
* @return {boolean} | ||
*/ | ||
function deconflictNode({node, continuation, ...rest}: DeconflictVisitorOptions): VisitResult<Node> { | ||
if (isIdentifier(node)) return deconflictIdentifier({...rest, continuation, node}); | ||
else return continuation(node); | ||
} | ||
|
||
/** | ||
* Deconflicts local identifiers such that they won't interfere with identifiers across modules | ||
* for the same chunk | ||
* @param {IDeclarationBundlerOptions} options | ||
* @return {TransformerFactory<SourceFile>} | ||
*/ | ||
export function deconflict(options: IDeclarationBundlerOptions): TransformerFactory<SourceFile> { | ||
const updatedIdentifierNamesForModuleMap: Map<string, Map<string, string>> = new Map(); | ||
const rootLevelIdentifiersForModuleMap: Map<string, Set<string>> = new Map(); | ||
const generatedVariableNamesForChunkMap: Map<string, Set<string>> = new Map(); | ||
|
||
return context => { | ||
return sourceFile => { | ||
// If the SourceFile is not part of the local module names, remove all statements from it and return immediately | ||
if (!options.localModuleNames.includes(sourceFile.fileName)) return updateSourceFileNode(sourceFile, [], true); | ||
|
||
const chunkFilename = getChunkFilename(sourceFile.fileName, options.supportedExtensions, options.chunkToOriginalFileMap); | ||
|
||
let rootLevelIdentifiersForModule = rootLevelIdentifiersForModuleMap.get(sourceFile.fileName); | ||
let updatedIdentifierNamesForModule = updatedIdentifierNamesForModuleMap.get(sourceFile.fileName); | ||
let generatedVariableNamesForChunk = generatedVariableNamesForChunkMap.get(chunkFilename); | ||
|
||
if (rootLevelIdentifiersForModule == null) { | ||
rootLevelIdentifiersForModule = new Set(); | ||
rootLevelIdentifiersForModuleMap.set(sourceFile.fileName, rootLevelIdentifiersForModule); | ||
} | ||
|
||
if (updatedIdentifierNamesForModule == null) { | ||
updatedIdentifierNamesForModule = new Map(); | ||
updatedIdentifierNamesForModuleMap.set(sourceFile.fileName, updatedIdentifierNamesForModule); | ||
} | ||
|
||
if (generatedVariableNamesForChunk == null) { | ||
generatedVariableNamesForChunk = new Set(); | ||
generatedVariableNamesForChunkMap.set(chunkFilename, generatedVariableNamesForChunk); | ||
} | ||
|
||
// Prepare some VisitorOptions | ||
const sharedVisitorOptions = { | ||
...options | ||
}; | ||
|
||
// Prepare some VisitorOptions | ||
const traceIdentifiersVisitorOptions = { | ||
...sharedVisitorOptions, | ||
|
||
continuation: <U extends Node>(node: U): void => traceIdentifiers({...traceIdentifiersVisitorOptions, node}), | ||
|
||
isIdentifierFree(identifier: string): boolean { | ||
for (const module of options.localModuleNames) { | ||
// Skip the current module | ||
if (module === sourceFile.fileName) continue; | ||
|
||
const identifiersForModule = rootLevelIdentifiersForModuleMap.get(module); | ||
if (identifiersForModule != null && identifiersForModule.has(identifier)) return false; | ||
} | ||
return true; | ||
}, | ||
|
||
updateIdentifierName(oldName: string, newName: string): void { | ||
updatedIdentifierNamesForModule!.set(oldName, newName); | ||
}, | ||
|
||
addIdentifier(name: string): void { | ||
rootLevelIdentifiersForModule!.add(name); | ||
}, | ||
|
||
generateUniqueVariableName(candidate: string): string { | ||
const suffix = "_$"; | ||
let counter = 0; | ||
|
||
while (true) { | ||
let currentCandidate = candidate + suffix + counter; | ||
if (generatedVariableNamesForChunk!.has(currentCandidate)) { | ||
counter++; | ||
} else { | ||
generatedVariableNamesForChunk!.add(currentCandidate); | ||
return currentCandidate; | ||
} | ||
} | ||
} | ||
}; | ||
|
||
// Prepare some VisitorOptions | ||
const deconflictVisitorOptions = { | ||
...sharedVisitorOptions, | ||
continuation: <U extends Node>(node: U): U => visitEachChild(node, nextNode => deconflictNode({...deconflictVisitorOptions, node: nextNode}), context), | ||
|
||
updateIdentifierIfNeeded<T extends Identifier | undefined>(identifier: T): T extends undefined ? undefined : Identifier { | ||
// tslint:disable:no-any | ||
if (identifier == null) return undefined as any; | ||
const newName = updatedIdentifierNamesForModule!.get(identifier.text); | ||
return newName == null ? identifier : (createIdentifier(newName) as any); | ||
// tslint:enable:no-any | ||
} | ||
}; | ||
|
||
// Walk through all Statements of the SourceFile and trace identifiers for them | ||
for (const node of sourceFile.statements) traceIdentifiersVisitorOptions.continuation(node); | ||
|
||
// Now, deconflict the SourceFile | ||
return deconflictVisitorOptions.continuation(sourceFile); | ||
}; | ||
}; | ||
} |
13 changes: 13 additions & 0 deletions
13
src/service/transformer/declaration-bundler/deconflict/trace-identifiers-visitor-options.ts
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,13 @@ | ||
import {Node} from "typescript"; | ||
|
||
export interface TraceIdentifiersVisitorOptions<T extends Node = Node> { | ||
node: T; | ||
|
||
updateIdentifierName(oldName: string, newName: string): void; | ||
addIdentifier(name: string): void; | ||
|
||
continuation<U extends Node>(node: U): void; | ||
|
||
isIdentifierFree(identifier: string): boolean; | ||
generateUniqueVariableName(candidate: string): string; | ||
} |
11 changes: 11 additions & 0 deletions
11
...ce/transformer/declaration-bundler/deconflict/visitor/deconflict/deconflict-identifier.ts
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,11 @@ | ||
import {Identifier, VisitResult} from "typescript"; | ||
import {DeconflictVisitorOptions} from "../../deconflict-visitor-options"; | ||
|
||
/** | ||
* Deconflicts the given Identifier. | ||
* @param {DeconflictVisitorOptions<Identifier>} options | ||
* @returns {VisitResult<Identifier>} | ||
*/ | ||
export function deconflictIdentifier({node, updateIdentifierIfNeeded}: DeconflictVisitorOptions<Identifier>): VisitResult<Identifier> { | ||
return updateIdentifierIfNeeded(node); | ||
} |
27 changes: 27 additions & 0 deletions
27
...ion-bundler/deconflict/visitor/trace-identifiers/trace-identifiers-for-binding-element.ts
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,27 @@ | ||
import {BindingElement, isIdentifier} from "typescript"; | ||
import {TraceIdentifiersVisitorOptions} from "../../trace-identifiers-visitor-options"; | ||
|
||
/** | ||
* Deconflicts the given BindingElement. | ||
* @param {TraceIdentifiersVisitorOptions} options | ||
*/ | ||
export function traceIdentifiersForBindingElement({ | ||
node, | ||
isIdentifierFree, | ||
continuation, | ||
addIdentifier, | ||
updateIdentifierName, | ||
generateUniqueVariableName | ||
}: TraceIdentifiersVisitorOptions<BindingElement>): void { | ||
if (node.name == null) return; | ||
|
||
if (!isIdentifier(node.name)) return continuation(node.name); | ||
|
||
const newName = !isIdentifierFree(node.name.text) ? generateUniqueVariableName(node.name.text) : node.name.text; | ||
|
||
addIdentifier(newName); | ||
|
||
if (newName !== node.name.text) { | ||
updateIdentifierName(node.name.text, newName); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...ion-bundler/deconflict/visitor/trace-identifiers/trace-identifiers-for-binding-pattern.ts
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,12 @@ | ||
import {BindingPattern} from "typescript"; | ||
import {TraceIdentifiersVisitorOptions} from "../../trace-identifiers-visitor-options"; | ||
|
||
/** | ||
* Deconflicts the given BindingPattern. | ||
* @param {TraceIdentifiersVisitorOptions} options | ||
*/ | ||
export function traceIdentifiersForBindingPattern({node, continuation}: TraceIdentifiersVisitorOptions<BindingPattern>): void { | ||
for (const element of node.elements) { | ||
continuation(element); | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
...n-bundler/deconflict/visitor/trace-identifiers/trace-identifiers-for-class-declaration.ts
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,18 @@ | ||
import {ClassDeclaration} from "typescript"; | ||
import {TraceIdentifiersVisitorOptions} from "../../trace-identifiers-visitor-options"; | ||
|
||
/** | ||
* Traces identifiers for the given ClassDeclaration. | ||
* @param {TraceIdentifiersVisitorOptions} options | ||
* @returns {void} | ||
*/ | ||
export function traceIdentifiersForClassDeclaration({node, isIdentifierFree, updateIdentifierName, addIdentifier, generateUniqueVariableName}: TraceIdentifiersVisitorOptions<ClassDeclaration>): void { | ||
if (node.name == null) return; | ||
const newName = !isIdentifierFree(node.name.text) ? generateUniqueVariableName(node.name.text) : node.name.text; | ||
|
||
addIdentifier(newName); | ||
|
||
if (newName !== node.name.text) { | ||
updateIdentifierName(node.name.text, newName); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
...on-bundler/deconflict/visitor/trace-identifiers/trace-identifiers-for-enum-declaration.ts
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,17 @@ | ||
import {EnumDeclaration} from "typescript"; | ||
import {TraceIdentifiersVisitorOptions} from "../../trace-identifiers-visitor-options"; | ||
|
||
/** | ||
* Traces identifiers for the given EnumDeclaration. | ||
* @param {TraceIdentifiersVisitorOptions} options | ||
* @returns {void} | ||
*/ | ||
export function traceIdentifiersForEnumDeclaration({node, isIdentifierFree, addIdentifier, updateIdentifierName, generateUniqueVariableName}: TraceIdentifiersVisitorOptions<EnumDeclaration>): void { | ||
const newName = !isIdentifierFree(node.name.text) ? generateUniqueVariableName(node.name.text) : node.name.text; | ||
|
||
addIdentifier(newName); | ||
|
||
if (newName !== node.name.text) { | ||
updateIdentifierName(node.name.text, newName); | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
...undler/deconflict/visitor/trace-identifiers/trace-identifiers-for-function-declaration.ts
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,23 @@ | ||
import {FunctionDeclaration} from "typescript"; | ||
import {TraceIdentifiersVisitorOptions} from "../../trace-identifiers-visitor-options"; | ||
|
||
/** | ||
* Traces identifiers for the given FunctionDeclaration. | ||
* @param {TraceIdentifiersVisitorOptions} options | ||
*/ | ||
export function traceIdentifiersForFunctionDeclaration({ | ||
node, | ||
isIdentifierFree, | ||
updateIdentifierName, | ||
addIdentifier, | ||
generateUniqueVariableName | ||
}: TraceIdentifiersVisitorOptions<FunctionDeclaration>): void { | ||
if (node.name == null) return; | ||
const newName = !isIdentifierFree(node.name.text) ? generateUniqueVariableName(node.name.text) : node.name.text; | ||
|
||
addIdentifier(newName); | ||
|
||
if (newName !== node.name.text) { | ||
updateIdentifierName(node.name.text, newName); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
...laration-bundler/deconflict/visitor/trace-identifiers/trace-identifiers-for-identifier.ts
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,16 @@ | ||
import {Identifier} from "typescript"; | ||
import {TraceIdentifiersVisitorOptions} from "../../trace-identifiers-visitor-options"; | ||
|
||
/** | ||
* Deconflicts the given Identifier. | ||
* @param {TraceIdentifiersVisitorOptions} options | ||
*/ | ||
export function traceIdentifiersForIdentifier({node, isIdentifierFree, generateUniqueVariableName, addIdentifier, updateIdentifierName}: TraceIdentifiersVisitorOptions<Identifier>): void { | ||
const newName = !isIdentifierFree(node.text) ? generateUniqueVariableName(node.text) : node.text; | ||
|
||
addIdentifier(newName); | ||
|
||
if (newName !== node.text) { | ||
updateIdentifierName(node.text, newName); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
...ndler/deconflict/visitor/trace-identifiers/trace-identifiers-for-interface-declaration.ts
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,22 @@ | ||
import {InterfaceDeclaration} from "typescript"; | ||
import {TraceIdentifiersVisitorOptions} from "../../trace-identifiers-visitor-options"; | ||
|
||
/** | ||
* Traces identifiers for the given InterfaceDeclaration. | ||
* @param {TraceIdentifiersVisitorOptions} options | ||
*/ | ||
export function traceIdentifiersForInterfaceDeclaration({ | ||
node, | ||
isIdentifierFree, | ||
updateIdentifierName, | ||
addIdentifier, | ||
generateUniqueVariableName | ||
}: TraceIdentifiersVisitorOptions<InterfaceDeclaration>): void { | ||
const newName = !isIdentifierFree(node.name.text) ? generateUniqueVariableName(node.name.text) : node.name.text; | ||
|
||
addIdentifier(newName); | ||
|
||
if (newName !== node.name.text) { | ||
updateIdentifierName(node.name.text, newName); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
...-bundler/deconflict/visitor/trace-identifiers/trace-identifiers-for-omitted-expression.ts
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,8 @@ | ||
import {OmittedExpression} from "typescript"; | ||
import {TraceIdentifiersVisitorOptions} from "../../trace-identifiers-visitor-options"; | ||
|
||
/** | ||
* Deconflicts the given OmittedExpression. | ||
* @param {TraceIdentifiersVisitorOptions} _options | ||
*/ | ||
export function traceIdentifiersForOmittedExpression(_options: TraceIdentifiersVisitorOptions<OmittedExpression>): void {} |
Oops, something went wrong.