-
Notifications
You must be signed in to change notification settings - Fork 13k
Closed
Labels
APIRelates to the public API for TypeScriptRelates to the public API for TypeScriptBugA bug in TypeScriptA bug in 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
APIRelates to the public API for TypeScriptRelates to the public API for TypeScriptBugA bug in TypeScriptA bug in TypeScriptHelp WantedYou can do thisYou can do this