Add tests for exceptions in user-code

This commit is contained in:
Ron Buckton
2019-11-19 14:39:16 -08:00
parent 2d2329bc66
commit 4b1b651424
30 changed files with 980 additions and 82 deletions
+211
View File
@@ -371,5 +371,216 @@ namespace ts {
const deprecation = createDeprecation(getFunctionName(func), options);
return wrapFunction(deprecation, func);
}
export interface FilterStackOptions {
stackTraceLimit?: number;
exclude?: (frame: StackFrame) => boolean;
excludeNode?: boolean;
excludeTypeScript?: boolean;
excludeMocha?: boolean;
excludeBuiltin?: boolean;
rewriteFrame?: (frame: StackFrame) => StackFrame;
}
export interface StackFrame {
typeName?: string;
functionName?: string;
methodName?: string;
fileName?: string;
lineNumber?: number;
columnNumber?: number;
evalOrigin?: StackFrame;
isConstructor?: boolean;
isAsync?: boolean;
}
export function filterStack(stack: string, options: FilterStackOptions): string;
export function filterStack(error: Error, options: FilterStackOptions): Error;
export function filterStack(error: Error | string, { stackTraceLimit = Infinity, exclude, excludeBuiltin, excludeNode, excludeMocha, excludeTypeScript, rewriteFrame = filterStack.defaultRewriteFrame }: FilterStackOptions) {
const stack = typeof error === "string" ? error : error.stack;
if (stack) {
const lines = stack.split(/\r\n?|\n/g);
const filtered: string[] = [];
let frameCount = 0;
let lastFrameWasExcluded = false;
let excludedFrameCount = 0;
let lastExcludedFrame: string | undefined;
for (let line of lines) {
let frame = parseStackFrame(line);
if (frame) {
if (frame.fileName && frame.fileName !== "native" && frame.fileName !== "unknown location" && frame.fileName !== "<anonymous>") {
frame.fileName = frame.fileName.replace(/\bfile:\/\/\/(.*?)(?=(:\d+)*($|\)))/, (_, path) => ts.sys.resolvePath(path));
if (rewriteFrame) {
frame = rewriteFrame(frame);
}
}
if (frameCount >= stackTraceLimit ||
excludeNode && isNodeStackFrame(frame) ||
excludeMocha && isMochaStackFrame(frame) ||
excludeTypeScript && isTypeScriptStackFrame(frame) ||
excludeBuiltin && isBuiltinStackFrame(frame) ||
exclude && exclude(frame)) {
if (lastFrameWasExcluded) {
excludedFrameCount++;
lastExcludedFrame = formatStackFrame(frame);
continue;
}
lastFrameWasExcluded = true;
}
else {
if (excludedFrameCount > 0) {
filtered.push(` ... skipping ${excludedFrameCount} frame${excludedFrameCount > 1 ? "s" : ""} ...`);
excludedFrameCount = 0;
}
lastFrameWasExcluded = false;
}
frameCount++;
line = formatStackFrame(frame);
}
filtered.push(line);
}
if (excludedFrameCount > 0) {
excludedFrameCount--;
if (excludedFrameCount > 0) {
filtered.push(` ... skipping ${excludedFrameCount} frame${excludedFrameCount > 1 ? "s" : ""} ...`);
}
if (lastExcludedFrame) {
filtered.push(lastExcludedFrame);
}
}
if (typeof error === "string") {
error = filtered.join("\n");
}
else {
error.stack = filtered.join("\n");
}
}
return error;
}
export namespace filterStack {
export let defaultRewriteFrame = (frame: StackFrame) => frame;
}
const evalLocationRegExp = /^eval at (.*)$/;
const fileLocationRegExp = /^(native|unknown location|<anonymous>|(?:(?:[a-zA-Z]|file|https?):)?[^:]+)(?::(\d+)(?::(\d+))?)?$/;
const positionRegExp = /^(async )?(new )?((?:[^.]+\.)+)?((?:(?! [\[(]).)*)(?: \[as ([^\]]+)\])? \((.*)\)$/;
function parseStackFrameLocation(location: string): StackFrame | undefined {
// location format:
// fileName:lineNumber:columnNumber
// native
// unknown location
// <anonymous>
let match: RegExpExecArray | null;
if (match = evalLocationRegExp.exec(location)) {
const evalOrigin = parseStackFrame(match[1]);
return evalOrigin && { evalOrigin };
}
if (match = fileLocationRegExp.exec(location)) {
const [, fileName, line, character] = match;
return {
fileName,
lineNumber: line !== undefined ? parseInt(line, 10) - 1 : undefined,
columnNumber: character !== undefined ? parseInt(character, 10) - 1 : undefined
};
}
}
function parseStackFrame(line: string): StackFrame | undefined {
// https://v8.dev/docs/stack-trace-api
//
// frame format:
// at {position}
// position format:
// {async |new }{thisType.}{functionName}{ [as methodName]} ({location})
// {location}
let match = /^ at (.*)$/.exec(line);
if (!match) return undefined;
const position = match[1];
if (match = positionRegExp.exec(position)) {
const [, asyncModifier, newModifier, typeName, functionName, methodName, locationPart] = match;
const isAsync = !!asyncModifier;
const isConstructor = !!newModifier;
const location = parseStackFrameLocation(locationPart);
return { typeName: typeName && typeName.slice(0, -1), functionName, methodName, ...location, isConstructor, isAsync };
}
const location = parseStackFrameLocation(position);
if (location && (location.evalOrigin || location.fileName && isRootedDiskPath(location.fileName))) {
return location;
}
}
function formatStackFrame(frame: StackFrame) {
let s = " at ";
if (frame.functionName) {
if (frame.isAsync) {
s += "async ";
}
else if (frame.isConstructor) {
s += "new ";
}
if (frame.typeName) {
s += `${frame.typeName}.`;
}
s += frame.functionName;
if (frame.methodName) {
s += ` [as ${frame.methodName}]`;
}
s += ` (${formatLocation(frame)})`;
}
else {
s += formatLocation(frame);
}
return s;
}
function formatLocation(frame: StackFrame) {
if (frame.fileName) {
let s = frame.fileName;
if (frame.lineNumber !== undefined) {
s += `:${frame.lineNumber + 1}`;
if (frame.columnNumber !== undefined) {
s += `:${frame.columnNumber + 1}`;
}
}
return s;
}
else if (frame.evalOrigin) {
return `eval at ${formatStackFrame(frame.evalOrigin)}`;
}
else {
return "unknown location";
}
}
function isMochaStackFrame(frame: StackFrame) {
return !!frame.fileName && /[/](node_modules|components)[/]mocha(js)?[/]|[/]mocha\.js$/.test(normalizeSlashes(frame.fileName));
}
function isNodeStackFrame(frame: StackFrame) {
return !!frame.fileName && /(timers|events|node|module)\.js$/.test(frame.fileName);
}
function isTypeScriptStackFrame(frame: StackFrame) {
if (frame.fileName) {
const file = normalizeSlashes(frame.fileName);
if (/([/]|^)(built[/]local|lib)[/](cancellationToken|tsc|tsserver(library)?|typescript(Services)?|typingsInstaller|watchGuard|run)\.js/.test(file)) {
return true;
}
if (/([/]|^)src[/](compat|compiler|harness|server|services|shims|testRunner|tsc|tsserver|tsserverlibrary|typescriptServices|typingsInstaller(Core)?|watchGuard)[/]/.test(file)) {
return true;
}
}
return false;
}
function isBuiltinStackFrame(frame: StackFrame) {
return (frame.fileName === "native" || frame.fileName === "<anonymous>") && !!frame.functionName;
}
}
}
+6 -2
View File
@@ -3192,7 +3192,7 @@
"category": "Error",
"code": 5078
},
"Plugin '{0}' could not be loaded": {
"Plugin '{0}' could not be loaded: {1}": {
"category": "Error",
"code": 5079
},
@@ -3200,10 +3200,14 @@
"category": "Error",
"code": 5080
},
"Plugins are not supported in the current host environment.": {
"Plugin '{0}' failed while executing a transformer provided by the '{1}' hook: {2}": {
"category": "Error",
"code": 5081
},
"Plugins are not supported in the current host environment.": {
"category": "Error",
"code": 5082
},
"Generates a sourcemap for each corresponding '.d.ts' file.": {
"category": "Message",
+7
View File
@@ -313,6 +313,13 @@ namespace ts {
}
// Transform the source files
const transform = transformNodes(resolver, host, factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false);
if (transform.diagnostics) {
emitterDiagnostics.addRange(transform.diagnostics);
}
if (transform.compilerDiagnostics) {
emitterDiagnostics.addRange(transform.compilerDiagnostics);
}
const printerOptions: PrinterOptions = {
removeComments: compilerOptions.removeComments,
+101 -10
View File
@@ -10,7 +10,7 @@ namespace ts {
type HookReturnType<K extends Hook> = HookReturnTypes[K];
type HostHook = Exclude<Hook, "activate" | "deactivate">;
type HostHookReturnType<K extends Hook> = Replace<HookReturnType<K>, void, CompilerPluginResult>;
type HostHookAggregate<K extends HostHook> = (state: HostHookReturnType<K>, userCodeResult: HookReturnType<K>, args: ArgumentsHolder<K>) => HostHookReturnType<K>;
type HostHookAggregate<K extends HostHook> = (state: HostHookReturnType<K>, userCodeResult: HookReturnType<K>, args: ArgumentsHolder<K>, compilerPlugin: CompilerPlugin, hook: HostHook) => HostHookReturnType<K>;
interface ArgumentsHolder<K extends Hook> {
arguments: HookParameters<K>;
@@ -37,7 +37,7 @@ namespace ts {
/**
* Resolves the supplied plugins (and their dependencies) relative to an initial directory.
*/
export function getPlugins(host: ModuleLoaderHost, initialDir: string, plugins: ReadonlyArray<string | [string, any?]>) {
export function getPlugins(host: ModuleLoaderHost, initialDir: string, plugins: ReadonlyArray<string | [string, any?]>): GetPluginsResult {
interface ResolvedModule {
getModule(): RequireResult;
moduleName: string;
@@ -220,7 +220,10 @@ namespace ts {
* Creates a `CompilerPluginHost` used to manage plugin lifetime.
*/
export function createPluginHost(compilerPlugins: ReadonlyArray<CompilerPlugin>, compilerHost: CompilerHost, compilerOptions: CompilerOptions): CompilerPluginHost {
interface Plugin {
/**
* Wrap a user-defined `TransformerFactory` so that we can catch errors during transformation and measure execution time.
*/
interface Plugin {
state: "unloaded" | "inactive" | "active" | "active-failed" | "failed"; // Tracks whether the plugin has been activated.
compilerPlugin: CompilerPlugin;
context: CompilerPluginContext;
@@ -237,11 +240,11 @@ namespace ts {
return {
deactivate,
preParse: (...args) => executeHostHook("preParse", args, (state, result, argsHolder) => {
preParse: (...args) => executeHostHook("preParse", args, (state, result, argsHolder, compilerPlugin) => {
state.diagnostics = concatenate(state.diagnostics, result.diagnostics);
state.rootNames = result.rootNames || state.rootNames;
state.projectReferences = result.projectReferences || state.projectReferences;
state.preprocessors = concatenate(state.preprocessors, result.preprocessors);
state.preprocessors = concatenate(state.preprocessors, map(result.preprocessors, preprocessor => wrapTransformerFactory(preprocessor, compilerPlugin, "preParse")));
const previousArgs = argsHolder.arguments[0];
if (state.projectReferences !== previousArgs.projectReferences ||
state.rootNames !== previousArgs.rootNames) {
@@ -252,9 +255,9 @@ namespace ts {
}
return state;
}, {}),
preEmit: (...args) => executeHostHook("preEmit", args, (state, result) => {
preEmit: (...args) => executeHostHook("preEmit", args, (state, result, _, compilerPlugin) => {
state.diagnostics = concatenate(state.diagnostics, result.diagnostics);
state.customTransformers = combineCustomTransformers(state.customTransformers, result.customTransformers);
state.customTransformers = combineCustomTransformers(state.customTransformers, result.customTransformers && wrapCustomTransformers(result.customTransformers, compilerPlugin, "preEmit"));
return state;
}, {})
};
@@ -402,20 +405,108 @@ namespace ts {
state.diagnostics = concatenate(state.diagnostics, [userCodeResult.error]);
}
else if (userCodeResult.result) {
state = aggregate(state, userCodeResult.result, argsHolder);
state = aggregate(state, userCodeResult.result, argsHolder, plugin.compilerPlugin, hook);
}
}
return state;
}
}
function formatPluginError(error: { message?: string, stack?: string }) {
return error.stack ? Debug.filterStack(error.stack, { excludeTypeScript: true, excludeMocha: true, excludeBuiltin: true, excludeNode: true }) :
error.message || error.toString();
}
function createLoadDiagnostic(compilerPlugin: CompilerPlugin, error: { message?: string, stack?: string }) {
debugger;
return createCompilerDiagnostic(Diagnostics.Plugin_0_could_not_be_loaded, compilerPlugin.name, error.stack || error.message || error.toString());
return createCompilerDiagnostic(Diagnostics.Plugin_0_could_not_be_loaded_Colon_1, compilerPlugin.name, formatPluginError(error));
}
function createUserCodeDiagnostic(compilerPlugin: CompilerPlugin, hook: Hook, error: { message?: string, stack?: string }) {
debugger;
return createCompilerDiagnostic(Diagnostics.Plugin_0_failed_while_executing_the_1_hook_Colon_2, compilerPlugin.name, hook, error.stack || error.message || error.toString());
return createCompilerDiagnostic(Diagnostics.Plugin_0_failed_while_executing_the_1_hook_Colon_2, compilerPlugin.name, hook, formatPluginError(error));
}
function createTransformerDiagnostic(compilerPlugin: CompilerPlugin, hook: Hook, error: { message?: string, stack?: string }) {
debugger;
return createCompilerDiagnostic(Diagnostics.Plugin_0_failed_while_executing_a_transformer_provided_by_the_1_hook_Colon_2, compilerPlugin.name, hook, formatPluginError(error));
}
/**
* Wrap a user-defined `CustomTransformers` so that we can catch errors during transformation and measure execution time.
*/
function wrapCustomTransformers(customTransformers: CustomTransformers, compilerPlugin: CompilerPlugin, hook: Hook): CustomTransformers {
const result: CustomTransformers = {};
if (customTransformers.before) {
result.before = customTransformers.before.map(transformer => wrapTransformerFactory(transformer, compilerPlugin, hook));
}
if (customTransformers.after) {
result.after = customTransformers.after.map(transformer => wrapTransformerFactory(transformer, compilerPlugin, hook));
}
if (customTransformers.afterDeclarations) {
result.afterDeclarations = customTransformers.afterDeclarations.map(transformer => wrapTransformerFactory(transformer, compilerPlugin, hook));
}
return result;
}
/**
* Wrap a user-defined `TransformerFactory` so that we can catch errors during transformation and measure execution time.
*/
function wrapTransformerFactory<T extends Node>(factory: TransformerFactory<T>, compilerPlugin: CompilerPlugin, hook: Hook): TransformerFactory<T>;
function wrapTransformerFactory<T extends Node>(factory: TransformerFactory<T> | CustomTransformerFactory, compilerPlugin: CompilerPlugin, hook: Hook): TransformerFactory<T> | CustomTransformerFactory;
function wrapTransformerFactory<T extends Node>(factory: TransformerFactory<T> | CustomTransformerFactory, compilerPlugin: CompilerPlugin, hook: Hook) {
return (context: TransformationContext): Transformer<T> | CustomTransformer => {
try {
const transformer = factory(context);
return typeof transformer === "function"
? wrapTransformer(transformer, context, compilerPlugin, hook)
: wrapCustomTransformer(transformer, context, compilerPlugin, hook);
}
catch (e) {
context.addCompilerDiagnostic(createTransformerDiagnostic(compilerPlugin, hook, e));
return identity;
}
};
}
/**
* Wrap a user-defined `Transformer` so that we can catch errors during transformation and measure execution time.
*/
function wrapTransformer<T extends Node>(transformer: Transformer<T>, context: TransformationContext, compilerPlugin: CompilerPlugin, hook: Hook): Transformer<T> {
return node => {
try {
return transformer(node);
}
catch (e) {
context.addCompilerDiagnostic(createTransformerDiagnostic(compilerPlugin, hook, e));
return node;
}
};
}
/**
* Wrap a user-defined `CustomTransformer` so that we can catch errors during transformation and measure execution time.
*/
function wrapCustomTransformer(customTransformer: CustomTransformer, context: TransformationContext, compilerPlugin: CompilerPlugin, hook: Hook): CustomTransformer {
return {
transformBundle(node) {
try {
return customTransformer.transformBundle(node);
}
catch (e) {
context.addCompilerDiagnostic(createTransformerDiagnostic(compilerPlugin, hook, e));
return node;
}
},
transformSourceFile(node) {
try {
return customTransformer.transformSourceFile(node);
}
catch (e) {
context.addCompilerDiagnostic(createTransformerDiagnostic(compilerPlugin, hook, e));
return node;
}
}
};
}
}
+21 -15
View File
@@ -323,9 +323,13 @@ namespace ts {
const diagnostics = [
...program.getConfigFileParsingDiagnostics(),
...program.getOptionsDiagnostics(cancellationToken),
...getPluginPreParseDiagnostics(program, cancellationToken),
...getPluginPreprocessDiagnostics(program, sourceFile, cancellationToken),
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
...program.getGlobalDiagnostics(cancellationToken),
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
...getPluginPreEmitGlobalDiagnostics(program, cancellationToken),
...program.getSemanticDiagnostics(sourceFile, cancellationToken),
...getPluginPreEmitDiagnostics(program, sourceFile, cancellationToken)
];
if (getEmitDeclarations(program.getCompilerOptions())) {
@@ -727,19 +731,19 @@ namespace ts {
return result;
}
function getPluginPreParseDiagnostics(program: BaseProgram, cancellationToken?: CancellationToken) {
function getPluginPreParseDiagnostics(program: BaseProgram | BuilderProgram, cancellationToken?: CancellationToken) {
return isAsyncProgram(program) ? program.getPluginPreParseDiagnostics(cancellationToken) : emptyArray;
}
function getPluginPreprocessDiagnostics(program: BaseProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken) {
function getPluginPreprocessDiagnostics(program: BaseProgram | BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken) {
return isAsyncProgram(program) ? program.getPluginPreprocessDiagnostics(sourceFile, cancellationToken) : emptyArray;
}
function getPluginPreEmitGlobalDiagnostics(program: BaseProgram, cancellationToken?: CancellationToken) {
function getPluginPreEmitGlobalDiagnostics(program: BaseProgram | BuilderProgram, cancellationToken?: CancellationToken) {
return isAsyncProgram(program) ? program.getPluginPreEmitGlobalDiagnostics(cancellationToken) : emptyArray;
}
function getPluginPreEmitDiagnostics(program: BaseProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken) {
function getPluginPreEmitDiagnostics(program: BaseProgram | BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken) {
return isAsyncProgram(program) ? program.getPluginPreEmitDiagnostics(sourceFile, cancellationToken) : emptyArray;
}
@@ -1620,11 +1624,6 @@ namespace ts {
// immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
// get any preEmit diagnostics, not just the ones
if (options.noEmitOnError) {
if (isAsyncProgram(program)) {
program.getPluginPreParseDiagnostics(cancellationToken);
program.getPluginPreprocessDiagnostics(sourceFile, cancellationToken);
program.getPluginPreEmitDiagnostics(sourceFile, cancellationToken);
}
const diagnostics = [
...program.getOptionsDiagnostics(cancellationToken),
...getPluginPreParseDiagnostics(program, cancellationToken),
@@ -3421,6 +3420,7 @@ namespace ts {
});
let preprocessDiagnostics: DiagnosticWithLocation[] | undefined;
let preprocessCompilerDiagnostics: Diagnostic[] | undefined;
let preprocessTransformer: NodeTransformer<SourceFile> | undefined;
let preprocessedNodes: Node[] | undefined;
if (preParseResult) {
@@ -3441,6 +3441,7 @@ namespace ts {
/*allowDtsFiles*/ true
);
preprocessDiagnostics = preprocessTransformer.diagnostics;
preprocessCompilerDiagnostics = preprocessTransformer.compilerDiagnostics;
preprocessedNodes = [];
changeCompilerHostToUsePreprocessor(host, node => {
disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node)));
@@ -3453,9 +3454,11 @@ namespace ts {
const { baseProgram, emitWorker, dropTypeCheckers } = createBaseProgram(createProgramOptions, host);
if (preprocessDiagnostics) {
for (const diagnostic of preprocessDiagnostics) {
pluginPreprocessDiagnostics!.add(diagnostic);
}
pluginPreprocessDiagnostics!.addRange(preprocessDiagnostics);
}
if (preprocessCompilerDiagnostics) {
pluginPreprocessDiagnostics!.addRange(preprocessCompilerDiagnostics);
}
const program = baseProgram as AsyncProgram;
@@ -3485,7 +3488,10 @@ namespace ts {
function getPluginPreprocessDiagnostics(sourceFile?: SourceFile) {
if (!pluginHost) return emptyArray;
return getDiagnosticsHelper(program, sourceFile, getPluginPreprocessDiagnosticsForFile);
return concatenate(
pluginPreprocessDiagnostics!.getGlobalDiagnostics(),
getDiagnosticsHelper(program, sourceFile, getPluginPreprocessDiagnosticsForFile)
);
}
function getPluginPreprocessDiagnosticsForFile(sourceFile: SourceFile) {
@@ -3546,7 +3552,7 @@ namespace ts {
}
}
export function isAsyncProgram(baseProgram: BaseProgram | Program | AsyncProgram): baseProgram is AsyncProgram {
export function isAsyncProgram(baseProgram: BaseProgram | Program | AsyncProgram | BuilderProgram): baseProgram is AsyncProgram {
return typeof (baseProgram as AsyncProgram).emitAsync === "function";
}
+10 -4
View File
@@ -132,6 +132,7 @@ namespace ts {
export interface NodeTransformer<T extends Node> {
diagnostics: DiagnosticWithLocation[];
/*@internal*/ compilerDiagnostics: Diagnostic[];
transformNodes(nodes: ReadonlyArray<T>): T[];
transformNode(node: T): T;
markComplete(): void;
@@ -182,6 +183,7 @@ namespace ts {
let onEmitNode: TransformationContext["onEmitNode"] = noEmitNotification;
let state = TransformationState.Uninitialized;
const diagnostics: DiagnosticWithLocation[] = [];
const compilerDiagnostics: Diagnostic[] = [];
// The transformation context is provided to each transformer as part of transformer
// initialization.
@@ -216,9 +218,10 @@ namespace ts {
onEmitNode = value;
},
addDiagnostic(diag) {
if (diagnostics) {
diagnostics.push(diag);
}
diagnostics.push(diag);
},
addCompilerDiagnostic(diag) {
compilerDiagnostics.push(diag);
}
};
@@ -236,6 +239,7 @@ namespace ts {
return {
diagnostics,
compilerDiagnostics,
transformNode,
transformNodes,
markComplete: () => { state = TransformationState.Completed; },
@@ -510,7 +514,8 @@ namespace ts {
substituteNode: tx.substituteNode,
emitNodeWithNotification: tx.emitNodeWithNotification,
dispose,
diagnostics: tx.diagnostics
diagnostics: tx.diagnostics,
compilerDiagnostics: tx.compilerDiagnostics,
};
function dispose() {
@@ -548,5 +553,6 @@ namespace ts {
startLexicalEnvironment: noop,
suspendLexicalEnvironment: noop,
addDiagnostic: noop,
addCompilerDiagnostic: noop
};
}
+5
View File
@@ -6645,6 +6645,7 @@ namespace ts {
onEmitNode: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
/* @internal */ addDiagnostic(diag: DiagnosticWithLocation): void;
/* @internal */ addCompilerDiagnostic(diag: Diagnostic): void;
}
export interface TransformationResult<T extends Node> {
@@ -6654,6 +6655,9 @@ namespace ts {
/** Gets diagnostics for the transformation. */
diagnostics?: DiagnosticWithLocation[];
/*@internal*/
compilerDiagnostics?: Diagnostic[];
/**
* Gets a substitute for a node, if one is available; otherwise, returns the original node.
*
@@ -7038,6 +7042,7 @@ namespace ts {
export interface DiagnosticCollection {
// Adds a diagnostic to this diagnostic collection.
add(diagnostic: Diagnostic): void;
addRange(diagnostics: Diagnostic[]): void;
// Returns the first existing diagnostic that is equivalent to the given one (sans related information)
lookup(diagnostic: Diagnostic): Diagnostic | undefined;
+5
View File
@@ -3100,6 +3100,7 @@ namespace ts {
return {
add,
addRange,
lookup,
getGlobalDiagnostics,
getDiagnostics,
@@ -3151,6 +3152,10 @@ namespace ts {
insertSorted(diagnostics, diagnostic, compareDiagnostics);
}
function addRange(diagnostics: Diagnostic[]) {
forEach(diagnostics, add);
}
function getGlobalDiagnostics(): Diagnostic[] {
hasReadNonFileDiagnostics = true;
return nonFileDiagnostics;
+30 -9
View File
@@ -269,14 +269,35 @@ namespace compiler {
if (compilerOptions.skipDefaultLibCheck === undefined) compilerOptions.skipDefaultLibCheck = true;
if (compilerOptions.noErrorTruncation === undefined) compilerOptions.noErrorTruncation = true;
const program = await ts.createAsyncProgram({
rootNames: project.fileNames || [],
options: compilerOptions,
host,
plugins
});
const emitResult = await program.emitAsync();
const errors = ts.getPreEmitDiagnostics(program);
return new CompilationResult(host, compilerOptions, program, emitResult, errors);
const defaultRewriteFrame = ts.Debug.filterStack.defaultRewriteFrame;
ts.Debug.filterStack.defaultRewriteFrame = frame => {
if (frame.fileName) {
frame.fileName = ts.normalizeSlashes(frame.fileName);
const file = frame.fileName
.replace(/^.*[/](src[/](?:compat|compiler|harness|server|services|shims|testRunner|tsc|tsserver(?:library)?|typescriptServices|typingsInstaller(?:Core)?|watchGuard)[/])/, "$1")
.replace(/^.*[/]((?:built[/]local|lib)[/])(?=(?:cancellationToken|tsc|tsserver(library)?|typescript(Services)?|typingsInstaller|watchGuard|run)\.js)/, "$1");
if (file !== frame.fileName) {
// set positions to 0 so that we don't have to accept diff changes due to unrelated additions/subtractions to related files.
frame.fileName = file;
frame.lineNumber = 0;
frame.columnNumber = 0;
}
}
return frame;
};
try {
const program = await ts.createAsyncProgram({
rootNames: project.fileNames || [],
options: compilerOptions,
host,
plugins
});
const emitResult = await program.emitAsync();
const errors = ts.sortAndDeduplicateDiagnostics(ts.concatenate(ts.getPreEmitDiagnostics(program), emitResult.diagnostics));
return new CompilationResult(host, compilerOptions, program, emitResult, errors);
}
finally {
ts.Debug.filterStack.defaultRewriteFrame = defaultRewriteFrame;
}
}
}
+12 -42
View File
@@ -386,51 +386,21 @@ namespace Utils {
const maxHarnessFrames = 1;
export function filterStack(error: Error, stackTraceLimit = Infinity) {
const stack = <string>(<any>error).stack;
if (stack) {
const lines = stack.split(/\r\n?|\n/g);
const filtered: string[] = [];
let frameCount = 0;
let harnessFrameCount = 0;
for (let line of lines) {
if (isStackFrame(line)) {
if (frameCount >= stackTraceLimit
|| isMocha(line)
|| isNode(line)) {
continue;
let harnessFrameCount = 0;
return ts.Debug.filterStack(error, {
stackTraceLimit,
excludeNode: true,
excludeMocha: true,
exclude: frame => {
if (frame.fileName && isHarness(frame.fileName)) {
if (harnessFrameCount >= maxHarnessFrames) {
return true;
}
if (isHarness(line)) {
if (harnessFrameCount >= maxHarnessFrames) {
continue;
}
harnessFrameCount++;
}
line = line.replace(/\bfile:\/\/\/(.*?)(?=(:\d+)*($|\)))/, (_, path) => ts.sys.resolvePath(path));
frameCount++;
harnessFrameCount++;
}
filtered.push(line);
return false;
}
(<any>error).stack = filtered.join(Harness.IO.newLine());
}
return error;
}
function isStackFrame(line: string) {
return /^\s+at\s/.test(line);
}
function isMocha(line: string) {
return /[\\/](node_modules|components)[\\/]mocha(js)?[\\/]|[\\/]mocha\.js/.test(line);
}
function isNode(line: string) {
return /\((timers|events|node|module)\.js:/.test(line);
});
}
function isHarness(line: string) {
@@ -0,0 +1,14 @@
error TS5077: Plugin 'does-not-exist' could not be found: Could not resolve JS module 'typescript-plugin-does-not-exist' starting at 'tests/cases/conformance/plugins'. Looked in: tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist/package.json, tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist.js, tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist.jsx, tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist/index.js, tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist/index.jsx, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist/package.json, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist.js, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist.jsx, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist/index.js, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist/index.jsx, tests/cases/node_modules/typescript-plugin-does-not-exist/package.json, tests/cases/node_modules/typescript-plugin-does-not-exist.js, tests/cases/node_modules/typescript-plugin-does-not-exist.jsx, tests/cases/node_modules/typescript-plugin-does-not-exist/index.js, tests/cases/node_modules/typescript-plugin-does-not-exist/index.jsx, tests/node_modules/typescript-plugin-does-not-exist/package.json, tests/node_modules/typescript-plugin-does-not-exist.js, tests/node_modules/typescript-plugin-does-not-exist.jsx, tests/node_modules/typescript-plugin-does-not-exist/index.js, tests/node_modules/typescript-plugin-does-not-exist/index.jsx, node_modules/typescript-plugin-does-not-exist/package.json, node_modules/typescript-plugin-does-not-exist.js, node_modules/typescript-plugin-does-not-exist.jsx, node_modules/typescript-plugin-does-not-exist/index.js, node_modules/typescript-plugin-does-not-exist/index.jsx.
!!! error TS5077: Plugin 'does-not-exist' could not be found: Could not resolve JS module 'typescript-plugin-does-not-exist' starting at 'tests/cases/conformance/plugins'. Looked in: tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist/package.json, tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist.js, tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist.jsx, tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist/index.js, tests/cases/conformance/plugins/node_modules/typescript-plugin-does-not-exist/index.jsx, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist/package.json, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist.js, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist.jsx, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist/index.js, tests/cases/conformance/node_modules/typescript-plugin-does-not-exist/index.jsx, tests/cases/node_modules/typescript-plugin-does-not-exist/package.json, tests/cases/node_modules/typescript-plugin-does-not-exist.js, tests/cases/node_modules/typescript-plugin-does-not-exist.jsx, tests/cases/node_modules/typescript-plugin-does-not-exist/index.js, tests/cases/node_modules/typescript-plugin-does-not-exist/index.jsx, tests/node_modules/typescript-plugin-does-not-exist/package.json, tests/node_modules/typescript-plugin-does-not-exist.js, tests/node_modules/typescript-plugin-does-not-exist.jsx, tests/node_modules/typescript-plugin-does-not-exist/index.js, tests/node_modules/typescript-plugin-does-not-exist/index.jsx, node_modules/typescript-plugin-does-not-exist/package.json, node_modules/typescript-plugin-does-not-exist.js, node_modules/typescript-plugin-does-not-exist.jsx, node_modules/typescript-plugin-does-not-exist/index.js, node_modules/typescript-plugin-does-not-exist/index.jsx.
==== tests/cases/conformance/plugins/tsconfig.json (0 errors) ====
{
"compilerOptions": {},
"plugins": [
"does-not-exist"
]
}
==== tests/cases/conformance/plugins/main.ts (0 errors) ====
const a = undefined;
@@ -0,0 +1,39 @@
error TS5080: Plugin 'typescript-plugin-transform' failed while executing the 'activate' hook: Error: Not yet implemented.
at Object.exports.activate (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:2:11)
at src/compiler/plugin.ts:1:1
... skipping 63 frames ...
at processImmediate (timers.js:658:5)
!!! error TS5080: Plugin 'typescript-plugin-transform' failed while executing the 'activate' hook: Error: Not yet implemented.
!!! error TS5080: at Object.exports.activate (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:2:11)
!!! error TS5080: at src/compiler/plugin.ts:1:1
!!! error TS5080: ... skipping 63 frames ...
!!! error TS5080: at processImmediate (timers.js:658:5)
==== tests/cases/conformance/plugins/tsconfig.json (0 errors) ====
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
==== tests/cases/conformance/plugins/main.ts (0 errors) ====
const a = undefined;
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/package.json (0 errors) ====
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preParse"]
}
}
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js (0 errors) ====
exports.activate = function () {
throw new Error("Not yet implemented.");
};
exports.preParse = function() {
};
@@ -0,0 +1,24 @@
//// [tests/cases/conformance/plugins/plugin.throwsOnActivate.ts] ////
//// [package.json]
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preParse"]
}
}
//// [index.js]
exports.activate = function () {
throw new Error("Not yet implemented.");
};
exports.preParse = function() {
};
//// [main.ts]
const a = undefined;
//// [main.js]
var a = undefined;
@@ -0,0 +1,35 @@
error TS5079: Plugin 'typescript-plugin-transform' could not be loaded: Error: Not yet implemented.
at tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:1:6
at ModuleLoader.require (src/harness/fakes.ts:1:1)
... skipping 37 frames ...
at fulfilled (built/local/run.js:1:1)
!!! error TS5079: Plugin 'typescript-plugin-transform' could not be loaded: Error: Not yet implemented.
!!! error TS5079: at tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:1:6
!!! error TS5079: at ModuleLoader.require (src/harness/fakes.ts:1:1)
!!! error TS5079: ... skipping 37 frames ...
!!! error TS5079: at fulfilled (built/local/run.js:1:1)
==== tests/cases/conformance/plugins/tsconfig.json (0 errors) ====
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
==== tests/cases/conformance/plugins/main.ts (0 errors) ====
const a = undefined;
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/package.json (0 errors) ====
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preEmit"]
}
}
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js (0 errors) ====
throw new Error("Not yet implemented.");
@@ -0,0 +1,20 @@
//// [tests/cases/conformance/plugins/plugin.throwsOnLoad.ts] ////
//// [package.json]
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preEmit"]
}
}
//// [index.js]
throw new Error("Not yet implemented.");
//// [main.ts]
const a = undefined;
//// [main.js]
var a = undefined;
@@ -0,0 +1,37 @@
error TS5080: Plugin 'typescript-plugin-transform' failed while executing the 'preEmit' hook: Error: Not yet implemented.
at Object.exports.preEmit (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:2:11)
at src/compiler/plugin.ts:1:1
... skipping 9 frames ...
at fulfilled (built/local/run.js:1:1)
!!! error TS5080: Plugin 'typescript-plugin-transform' failed while executing the 'preEmit' hook: Error: Not yet implemented.
!!! error TS5080: at Object.exports.preEmit (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:2:11)
!!! error TS5080: at src/compiler/plugin.ts:1:1
!!! error TS5080: ... skipping 9 frames ...
!!! error TS5080: at fulfilled (built/local/run.js:1:1)
==== tests/cases/conformance/plugins/tsconfig.json (0 errors) ====
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
==== tests/cases/conformance/plugins/main.ts (0 errors) ====
const a = undefined;
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/package.json (0 errors) ====
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preEmit"]
}
}
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js (0 errors) ====
exports.preEmit = function () {
throw new Error("Not yet implemented.");
};
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/plugins/plugin.throwsOnPreEmit.ts] ////
//// [package.json]
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preEmit"]
}
}
//// [index.js]
exports.preEmit = function () {
throw new Error("Not yet implemented.");
};
//// [main.ts]
const a = undefined;
//// [main.js]
var a = undefined;
@@ -0,0 +1,42 @@
error TS5081: Plugin 'typescript-plugin-transform' failed while executing a transformer provided by the 'preEmit' hook: Error: Not yet implemented.
at transform (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:6:15)
at src/compiler/plugin.ts:1:1
... skipping 13 frames ...
at fulfilled (built/local/run.js:1:1)
!!! error TS5081: Plugin 'typescript-plugin-transform' failed while executing a transformer provided by the 'preEmit' hook: Error: Not yet implemented.
!!! error TS5081: at transform (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:6:15)
!!! error TS5081: at src/compiler/plugin.ts:1:1
!!! error TS5081: ... skipping 13 frames ...
!!! error TS5081: at fulfilled (built/local/run.js:1:1)
==== tests/cases/conformance/plugins/tsconfig.json (0 errors) ====
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
==== tests/cases/conformance/plugins/main.ts (0 errors) ====
const a = undefined;
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/package.json (0 errors) ====
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preEmit"]
}
}
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js (0 errors) ====
exports.preEmit = function() {
return {
customTransformers: { after: [transform] }
};
function transform() {
throw new Error("Not yet implemented.");
}
};
@@ -0,0 +1,27 @@
//// [tests/cases/conformance/plugins/plugin.throwsOnPreEmitTransform.ts] ////
//// [package.json]
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preEmit"]
}
}
//// [index.js]
exports.preEmit = function() {
return {
customTransformers: { after: [transform] }
};
function transform() {
throw new Error("Not yet implemented.");
}
};
//// [main.ts]
const a = undefined;
//// [main.js]
var a = undefined;
@@ -0,0 +1,37 @@
error TS5080: Plugin 'typescript-plugin-transform' failed while executing the 'preParse' hook: Error: Not yet implemented.
at Object.exports.preParse (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:2:11)
at src/compiler/plugin.ts:1:1
... skipping 9 frames ...
at fulfilled (built/local/run.js:1:1)
!!! error TS5080: Plugin 'typescript-plugin-transform' failed while executing the 'preParse' hook: Error: Not yet implemented.
!!! error TS5080: at Object.exports.preParse (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:2:11)
!!! error TS5080: at src/compiler/plugin.ts:1:1
!!! error TS5080: ... skipping 9 frames ...
!!! error TS5080: at fulfilled (built/local/run.js:1:1)
==== tests/cases/conformance/plugins/tsconfig.json (0 errors) ====
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
==== tests/cases/conformance/plugins/main.ts (0 errors) ====
const a = undefined;
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/package.json (0 errors) ====
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preParse"]
}
}
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js (0 errors) ====
exports.preParse = function() {
throw new Error("Not yet implemented.");
};
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/plugins/plugin.throwsOnPreParse.ts] ////
//// [package.json]
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preParse"]
}
}
//// [index.js]
exports.preParse = function() {
throw new Error("Not yet implemented.");
};
//// [main.ts]
const a = undefined;
//// [main.js]
var a = undefined;
@@ -0,0 +1,42 @@
error TS5081: Plugin 'typescript-plugin-transform' failed while executing a transformer provided by the 'preParse' hook: Error: Not yet implemented.
at preprocess (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:6:15)
at src/compiler/plugin.ts:1:1
... skipping 6 frames ...
at fulfilled (built/local/run.js:1:1)
!!! error TS5081: Plugin 'typescript-plugin-transform' failed while executing a transformer provided by the 'preParse' hook: Error: Not yet implemented.
!!! error TS5081: at preprocess (tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js:6:15)
!!! error TS5081: at src/compiler/plugin.ts:1:1
!!! error TS5081: ... skipping 6 frames ...
!!! error TS5081: at fulfilled (built/local/run.js:1:1)
==== tests/cases/conformance/plugins/tsconfig.json (0 errors) ====
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
==== tests/cases/conformance/plugins/main.ts (0 errors) ====
const a = undefined;
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/package.json (0 errors) ====
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preParse"]
}
}
==== tests/cases/conformance/plugins/node_modules/typescript-plugin-transform/index.js (0 errors) ====
exports.preParse = function() {
return {
preprocessors: [preprocess]
};
function preprocess() {
throw new Error("Not yet implemented.");
}
};
@@ -0,0 +1,27 @@
//// [tests/cases/conformance/plugins/plugin.throwsOnPreParseTransform.ts] ////
//// [package.json]
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preParse"]
}
}
//// [index.js]
exports.preParse = function() {
return {
preprocessors: [preprocess]
};
function preprocess() {
throw new Error("Not yet implemented.");
}
};
//// [main.ts]
const a = undefined;
//// [main.js]
var a = undefined;
@@ -0,0 +1,12 @@
// @noImplicitReferences: true
// @noTypesAndSymbols: true
// @filename: tsconfig.json
{
"compilerOptions": {},
"plugins": [
"does-not-exist"
]
}
// @filename: main.ts
const a = undefined;
@@ -0,0 +1,29 @@
// @noImplicitReferences: true
// @noTypesAndSymbols: true
// @filename: node_modules/typescript-plugin-transform/package.json
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preParse"]
}
}
// @filename: node_modules/typescript-plugin-transform/index.js
exports.activate = function () {
throw new Error("Not yet implemented.");
};
exports.preParse = function() {
};
// @filename: tsconfig.json
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
// @filename: main.ts
const a = undefined;
@@ -0,0 +1,25 @@
// @noImplicitReferences: true
// @noTypesAndSymbols: true
// @filename: node_modules/typescript-plugin-transform/package.json
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preEmit"]
}
}
// @filename: node_modules/typescript-plugin-transform/index.js
throw new Error("Not yet implemented.");
// @filename: tsconfig.json
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
// @filename: main.ts
const a = undefined;
@@ -0,0 +1,27 @@
// @noImplicitReferences: true
// @noTypesAndSymbols: true
// @filename: node_modules/typescript-plugin-transform/package.json
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preEmit"]
}
}
// @filename: node_modules/typescript-plugin-transform/index.js
exports.preEmit = function () {
throw new Error("Not yet implemented.");
};
// @filename: tsconfig.json
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
// @filename: main.ts
const a = undefined;
@@ -0,0 +1,32 @@
// @noImplicitReferences: true
// @noTypesAndSymbols: true
// @filename: node_modules/typescript-plugin-transform/package.json
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preEmit"]
}
}
// @filename: node_modules/typescript-plugin-transform/index.js
exports.preEmit = function() {
return {
customTransformers: { after: [transform] }
};
function transform() {
throw new Error("Not yet implemented.");
}
};
// @filename: tsconfig.json
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
// @filename: main.ts
const a = undefined;
@@ -0,0 +1,27 @@
// @noImplicitReferences: true
// @noTypesAndSymbols: true
// @filename: node_modules/typescript-plugin-transform/package.json
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preParse"]
}
}
// @filename: node_modules/typescript-plugin-transform/index.js
exports.preParse = function() {
throw new Error("Not yet implemented.");
};
// @filename: tsconfig.json
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
// @filename: main.ts
const a = undefined;
@@ -0,0 +1,32 @@
// @noImplicitReferences: true
// @noTypesAndSymbols: true
// @filename: node_modules/typescript-plugin-transform/package.json
{
"name": "typescript-plugin-transform",
"version": "1.0.0",
"main": "index.js",
"typescriptPlugin": {
"activationEvents": ["preParse"]
}
}
// @filename: node_modules/typescript-plugin-transform/index.js
exports.preParse = function() {
return {
preprocessors: [preprocess]
};
function preprocess() {
throw new Error("Not yet implemented.");
}
};
// @filename: tsconfig.json
{
"compilerOptions": {},
"plugins": [
"transform"
]
}
// @filename: main.ts
const a = undefined;