Skip to content

Commit

Permalink
[WIP] Initial createProgram
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsonk committed Sep 6, 2018
1 parent 59f3fca commit 77ddd59
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 164 deletions.
2 changes: 1 addition & 1 deletion BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ run_node("bundle") {
"js/compiler.ts",
"js/console.ts",
"js/fetch.ts",
"js/fetch_types.d.ts",
"js/fetch_types.ts",
"js/globals.ts",
"js/main.ts",
"js/os.ts",
Expand Down
4 changes: 2 additions & 2 deletions js/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ import libEsnextIntlDts from "/third_party/node_modules/typescript/lib/lib.esnex
import libEsnextSymbolDts from "/third_party/node_modules/typescript/lib/lib.esnext.symbol.d.ts!string";

// Static definitions
import fetchTypesDts from "/js/fetch_types.d.ts!string";
import flatbuffersDts from "/third_party/node_modules/@types/flatbuffers/index.d.ts!string";
import pluginsDts from "/js/plugins.d.ts!string";
import textEncodingDts from "/third_party/node_modules/@types/text-encoding/index.d.ts!string";
import typescriptDts from "/third_party/node_modules/typescript/lib/typescript.d.ts!string";
// tslint:enable:max-line-length
Expand Down Expand Up @@ -82,8 +82,8 @@ export const assetSourceCode: { [key: string]: string } = {
"lib.esnext.symbol.d.ts": libEsnextSymbolDts,

// Static definitions
"fetch-types.d.ts": fetchTypesDts,
"flatbuffers.d.ts": flatbuffersDts,
"plugins.d.ts": pluginsDts,
"text-encoding.d.ts": textEncodingDts,
"typescript.d.ts": typescriptDts
};
128 changes: 102 additions & 26 deletions js/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { assert, log, notImplemented } from "./util";
import * as sourceMaps from "./v8_source_maps";

const EOL = "\n";
const ASSETS = "$asset$";
const ASSETS = "/$asset$";

// tslint:disable:no-any
type AmdCallback = (...args: any[]) => void;
Expand Down Expand Up @@ -65,8 +65,10 @@ export interface Os {
*/
export interface Ts {
createLanguageService: typeof ts.createLanguageService;
createProgram: typeof ts.createProgram;
/* tslint:disable-next-line:max-line-length */
formatDiagnosticsWithColorAndContext: typeof ts.formatDiagnosticsWithColorAndContext;
getPreEmitDiagnostics: typeof ts.getPreEmitDiagnostics;
}

/**
Expand Down Expand Up @@ -107,16 +109,6 @@ export class ModuleMetaData implements ts.IScriptSnapshot {
}
}

/**
* The required minimal API to allow formatting of TypeScript compiler
* diagnostics.
*/
const formatDiagnosticsHost: ts.FormatDiagnosticsHost = {
getCurrentDirectory: () => ".",
getCanonicalFileName: (fileName: string) => fileName,
getNewLine: () => EOL
};

/**
* Throw a module resolution error, when a module is unsuccessfully resolved.
*/
Expand All @@ -131,19 +123,14 @@ function throwResolutionError(
);
}

// ts.ScriptKind is not available at runtime, so local enum definition
enum ScriptKind {
JS = 1,
TS = 3,
JSON = 6
}

/**
* A singleton class that combines the TypeScript Language Service host API
* with Deno specific APIs to provide an interface for compiling and running
* TypeScript and JavaScript modules.
*/
export class DenoCompiler implements ts.LanguageServiceHost {
// Needed to supply to the TypeScript compiler
private _cwd = "";
// Modules are usually referenced by their ModuleSpecifier and ContainingFile,
// and keeping a map of the resolved module file name allows more efficient
// future resolution
Expand Down Expand Up @@ -229,7 +216,10 @@ export class DenoCompiler implements ts.LanguageServiceHost {
}

this._window.define = this.makeDefine(moduleMetaData);
this._globalEval(this.compile(moduleMetaData));
if (!moduleMetaData.outputCode) {
throw new Error(`Missing source code for: "${moduleMetaData.fileName}"`);
}
this._globalEval(moduleMetaData.outputCode);
this._window.define = undefined;
}

Expand Down Expand Up @@ -274,7 +264,9 @@ export class DenoCompiler implements ts.LanguageServiceHost {
? this._moduleMetaDataMap.get(fileName)
: fileName.startsWith(ASSETS)
? this.resolveModule(fileName, "")
: undefined;
: fileName === "/js/plugins.d.ts"
? this.resolveModule(`${ASSETS}/plugins.d.ts`, "")
: undefined;
}

/**
Expand Down Expand Up @@ -348,6 +340,29 @@ export class DenoCompiler implements ts.LanguageServiceHost {

// Deno specific compiler API

compileProgram(rootModuleMetaData: ModuleMetaData) {
this._log("compiler.compileProgram", rootModuleMetaData.fileName);
const program = this._ts.createProgram({
rootNames: [rootModuleMetaData.fileName],
options: this._options,
host: this
});
const emitResult = program.emit();

const diagnostics = [
...this._ts.getPreEmitDiagnostics(program),
...emitResult.diagnostics
];
if (diagnostics.length > 0) {
const errMsg = this._ts.formatDiagnosticsWithColorAndContext(
diagnostics,
this
);
console.log(errMsg);
this._os.exit(1);
}
}

/**
* Retrieve the output of the TypeScript compiler for a given module and
* cache the result.
Expand All @@ -371,7 +386,7 @@ export class DenoCompiler implements ts.LanguageServiceHost {
if (diagnostics.length > 0) {
const errMsg = this._ts.formatDiagnosticsWithColorAndContext(
diagnostics,
formatDiagnosticsHost
this
);
console.log(errMsg);
// All TypeScript errors are terminal for deno
Expand Down Expand Up @@ -570,6 +585,23 @@ export class DenoCompiler implements ts.LanguageServiceHost {
return moduleMetaData;
}

runProgram(
moduleSpecifier: ModuleSpecifier,
containingFile: ContainingFile
): void {
this._log("compiler.runProgram", { moduleSpecifier, containingFile });
const moduleMetaData = this.resolveModule(moduleSpecifier, containingFile);
this.compileProgram(moduleMetaData);
if (!moduleMetaData.deps) {
this._gatherDependencies(moduleMetaData);
}
this._drainRunQueue();
}

setCwd(cwd: string): void {
this._cwd = cwd;
}

/**
* Caches the resolved `fileName` in relationship to the `moduleSpecifier`
* and `containingFile` in order to reduce calls to the privileged side
Expand Down Expand Up @@ -597,6 +629,15 @@ export class DenoCompiler implements ts.LanguageServiceHost {
return this._options;
}

getCanonicalFileName(fileName: string): string {
return fileName;
}

getDirectories(path: string) {
this._log("getDirectories()", path);
return notImplemented();
}

getNewLine(): string {
return EOL;
}
Expand All @@ -613,13 +654,13 @@ export class DenoCompiler implements ts.LanguageServiceHost {
const suffix = fileName.substr(fileName.lastIndexOf(".") + 1);
switch (suffix) {
case "ts":
return ScriptKind.TS;
return ts.ScriptKind.TS;
case "js":
return ScriptKind.JS;
return ts.ScriptKind.JS;
case "json":
return ScriptKind.JSON;
return ts.ScriptKind.JSON;
default:
return this._options.allowJs ? ScriptKind.JS : ScriptKind.TS;
return this._options.allowJs ? ts.ScriptKind.JS : ts.ScriptKind.TS;
}
}

Expand All @@ -634,9 +675,25 @@ export class DenoCompiler implements ts.LanguageServiceHost {
return this._getModuleMetaData(fileName);
}

getSourceFile(
fileName: string,
languageVersion: ts.ScriptTarget
): ts.SourceFile | undefined {
this._log("getSourceFile()", fileName);
const moduleMetaData = this._getModuleMetaData(fileName);
if (!moduleMetaData || !moduleMetaData.sourceCode) {
return undefined;
}
return ts.createSourceFile(
moduleMetaData.fileName,
moduleMetaData.sourceCode,
languageVersion
);
}

getCurrentDirectory(): string {
this._log("getCurrentDirectory()");
return "";
return this._cwd;
}

getDefaultLibFileName(): string {
Expand Down Expand Up @@ -694,6 +751,25 @@ export class DenoCompiler implements ts.LanguageServiceHost {
});
}

writeFile(
fileName: string,
data: string,
writeByteOrderMark: boolean,
onError?: ((message: string) => void),
sourceFiles?: ReadonlyArray<ts.SourceFile>
): void {
this._log("writeFile()", fileName);
if (!sourceFiles || sourceFiles.length !== 1) {
throw new Error(`Unexpected emit of file: "${fileName}"`);
}
const sourceFileName = sourceFiles[0].fileName;
const moduleMetaData = this._getModuleMetaData(sourceFileName);
if (!moduleMetaData) {
throw new Error(`Cannot find source module: ${sourceFileName}`);
}
moduleMetaData.outputCode = data;
}

// Deno specific static properties and methods

/**
Expand Down
Loading

0 comments on commit 77ddd59

Please sign in to comment.