-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Closed
Labels
BugA bug in TypeScriptA bug in TypeScriptDomain: APIRelates to the public API for TypeScriptRelates to the public API for TypeScriptHelp WantedYou can do thisYou can do this
Milestone
Description
TypeScript Version: 3.0.0-dev.20180605
Same in 2.9.1 and earlier.
Search Terms: getOrCreateEmitNode, annotatedNodes
Code
Quick summary: we create TS file, apply a transform which changes a method name, and compile the final AST.
import * as ts from "typescript";
import { readFileSync } from "fs";
import { join } from "path";
const options: ts.CompilerOptions = {
target: ts.ScriptTarget.ES3,
module: ts.ModuleKind.None,
noLib: true,
};
const sourceFile = transform(
ts.createSourceFile(
"input.ts",
"class X { hello(userName: string) { return `Hello, ${userName}!`; } }",
ts.ScriptTarget.ES2017,
true,
ts.ScriptKind.TS,
),
);
// console.log(ts.createPrinter().printFile(sourceFile));
const host: ts.CompilerHost = {
getSourceFile(
fileName: string,
languageVersion: ts.ScriptTarget,
): ts.SourceFile {
if (fileName === sourceFile.fileName) {
return sourceFile;
}
throw new Error(`File not found: ${fileName}`);
},
getDefaultLibFileName: () => "lib.d.ts",
writeFile: (_fileName, _content) => {
throw new Error("Unsupported!");
},
getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
getCanonicalFileName: fileName =>
ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
getNewLine: () => ts.sys.newLine,
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
fileExists: (fileName: string) => fileName === sourceFile.fileName,
readFile(fileName: string): string {
if (fileName === sourceFile.fileName) {
return sourceFile.getText();
}
return "";
},
resolveModuleNames(
_moduleNames: string[],
_containingFile: string,
): ts.ResolvedModule[] {
throw new Error("Unsupported!");
},
getDirectories(_path: string): string[] {
throw new Error("Unsupported!");
},
};
const program = ts.createProgram(["input.ts"], options, host);
function transformSourceFile(
context: ts.TransformationContext,
): ts.Transformer<ts.SourceFile> {
return (sourceFile: ts.SourceFile) => {
function visit(node: ts.Node) {
if (ts.isMethodDeclaration(node)) {
return ts.updateMethod(
node,
node.decorators,
node.modifiers,
node.asteriskToken,
ts.createIdentifier("foobar"),
node.questionToken,
node.typeParameters,
node.parameters,
node.type,
node.body,
);
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitEachChild(sourceFile, visit, context);
};
}
function transform(source: ts.SourceFile): ts.SourceFile {
const result = ts.transform(source, [transformSourceFile]);
const transformedSource = result.transformed[0];
result.dispose();
return transformedSource;
}
program.emit(sourceFile, (fileName, source) => {
console.log(source);
});Expected behavior:
No exceptions.
Actual behavior:
/Users/test/transform-test/node_modules/typescript/lib/typescript.js:55251
getOrCreateEmitNode(sourceFile).annotatedNodes.push(node);
^
TypeError: Cannot read property 'push' of undefined
at getOrCreateEmitNode (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:55251:63)
at Object.setEmitFlags (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:55270:9)
at visitParameter (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:60754:16)
at visitTypeScript (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:59155:28)
at visitorWorker (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:58892:24)
at saveStateAndInvoke (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:58836:27)
at visitor (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:58882:20)
at visitNodes (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:57074:48)
at visitParameterList (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:57122:23)
at Object.visitEachChild (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:57172:395)
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptDomain: APIRelates to the public API for TypeScriptRelates to the public API for TypeScriptHelp WantedYou can do thisYou can do this