Skip to content

Commit

Permalink
Add JSDoc to deno_typescript (denoland#2890)
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsonk authored and ry committed Sep 10, 2019
1 parent 46cbc6e commit 3779667
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 92 deletions.
30 changes: 22 additions & 8 deletions deno_typescript/amd_runtime.js
@@ -1,20 +1,34 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.

// A very very basic AMD preamble to support the output of TypeScript outFile
// bundles.
let require, define;

/**
* @type {(name: string) => any}
*/
let require;

/**
* @type {(name: string, deps: ReadonlyArray<string>, factory: (...deps: any[]) => void) => void}
*/
let define;

(function() {
/**
* @type {Map<string, { name: string, exports: any }>}
*/
const modules = new Map();

function println(first, ...s) {
Deno.core.print(first + " " + s.map(JSON.stringify).join(" ") + "\n");
}

/**
* @param {string} name
*/
function createOrLoadModule(name) {
if (!modules.has(name)) {
const m = { name, exports: {} };
let m = modules.get(name);
if (!m) {
m = { name, exports: {} };
modules.set(name, m);
}
return modules.get(name);
return m;
}

require = name => {
Expand Down
193 changes: 109 additions & 84 deletions deno_typescript/compiler_main.js
@@ -1,8 +1,16 @@
// Because we're bootstrapping the TS compiler without dependencies on Node,
// this is written in JS.
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.

// Because we're bootstrapping the TypeScript compiler without dependencies on
// Node, this is written in JavaScript, but leverages JSDoc that can be
// understood by the TypeScript language service, so it allows type safety
// checking in VSCode.

const ASSETS = "$asset$";

/**
* @param {string} configText
* @param {Array<string>} rootNames
*/
function main(configText, rootNames) {
println(`>>> ts version ${ts.version}`);
println(`>>> rootNames ${rootNames}`);
Expand Down Expand Up @@ -34,37 +42,57 @@ function main(configText, rootNames) {
dispatch("setEmitResult", emitResult);
}

/**
* @param {...string} s
*/
function println(...s) {
Deno.core.print(s.join(" ") + "\n");
}

/**
* @returns {never}
*/
function unreachable() {
throw Error("unreachable");
}

/**
* @param {unknown} cond
*/
function assert(cond) {
if (!cond) {
throw Error("assert");
}
}

// decode(Uint8Array): string
/**
* @param {Uint8Array | null} ui8
*/
function decodeAscii(ui8) {
let out = "";
if (!ui8) {
return out;
}
for (let i = 0; i < ui8.length; i++) {
out += String.fromCharCode(ui8[i]);
}
return out;
}

/**
* @param {string} str
*/
function encode(str) {
const charCodes = str.split("").map(c => c.charCodeAt(0));
const ui8 = new Uint8Array(charCodes);
return ui8;
}

// Warning! The op_id values below are shared between this code and
// the Rust side. Update with care!
//
/** **Warning!** The op_id values below are shared between this code and the
* Rust side. Update with care!
* @type {Record<string, number>}
*/
const ops = {
readFile: 49,
exit: 50,
Expand All @@ -73,53 +101,56 @@ const ops = {
setEmitResult: 53
};

// interface CompilerHost extends ModuleResolutionHost {
/**
* @implements {ts.CompilerHost}
*/
class Host {
// fileExists(fileName: string): boolean;
/**
* @param {string} fileName
*/
fileExists(fileName) {
return true;
}

// readFile(fileName: string): string | undefined;
readFile() {
/**
* @param {string} fileName
*/
readFile(fileName) {
unreachable();
return undefined;
}

// trace?(s: string): void;
// directoryExists?(directoryName: string): boolean;
// realpath?(path: string): string;
// getCurrentDirectory?(): string;
// getDirectories?(path: string): string[];

// useCaseSensitiveFileNames(): boolean;
useCaseSensitiveFileNames() {
return false;
}

// getDefaultLibFileName(options: CompilerOptions): string;
getDefaultLibFileName(options) {
/**
* @param {ts.CompilerOptions} _options
*/
getDefaultLibFileName(_options) {
return "lib.deno_core.d.ts";
}

// getDefaultLibLocation?(): string;
getDefaultLibLocation() {
return ASSETS;
}

// getCurrentDirectory(): string;
getCurrentDirectory() {
return ".";
}

// getCanonicalFileName(fileName: string): string
getCanonicalFileName(fileName) {
unreachable();
}

// getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?:
// (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile
// | undefined;
getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) {
/**
* @param {string} fileName
* @param {ts.ScriptTarget} languageVersion
* @param {(message: string) => void} _onError
* @param {boolean} shouldCreateNewSourceFile
*/
getSourceFile(
fileName,
languageVersion,
_onError,
shouldCreateNewSourceFile
) {
assert(!shouldCreateNewSourceFile); // We haven't yet encountered this.

// This hacks around the fact that TypeScript tries to magically guess the
Expand Down Expand Up @@ -148,27 +179,34 @@ class Host {
return sourceFile;
}

/*
writeFile(
fileName: string,
data: string,
writeByteOrderMark: boolean,
onError?: (message: string) => void,
sourceFiles?: ReadonlyArray<ts.SourceFile>
): void
*/
/**
* @param {string} fileName
* @param {string} data
* @param {boolean} _writeByteOrderMark
* @param {((message: string) => void)?} _onError
* @param {ReadonlyArray<ts.SourceFile>?} sourceFiles
*/
writeFile(
fileName,
data,
writeByteOrderMark,
onError = null,
_writeByteOrderMark,
_onError = null,
sourceFiles = null
) {
if (sourceFiles == null) {
return;
}
const moduleName = sourceFiles[sourceFiles.length - 1].moduleName;
return dispatch("writeFile", { fileName, moduleName, data });
}

// getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined;
/**
* @param {string} fileName
* @param {ts.Path} path
* @param {ts.ScriptTarget} languageVersion
* @param {*} onError
* @param {boolean} shouldCreateNewSourceFile
*/
getSourceFileByPath(
fileName,
path,
Expand All @@ -177,35 +215,27 @@ class Host {
shouldCreateNewSourceFile
) {
unreachable();
return undefined;
}

// getCancellationToken?(): CancellationToken;
getCancellationToken() {
unreachable();
}

// getCanonicalFileName(fileName: string): string;
/**
* @param {string} fileName
*/
getCanonicalFileName(fileName) {
return fileName;
}

// getNewLine(): string
getNewLine() {
return "\n";
}

// readDirectory?(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): string[];
readDirectory() {
unreachable();
}

// resolveModuleNames?(
// moduleNames: string[],
// containingFile: string,
// reusedNames?: string[],
// redirectedReference?: ResolvedProjectReference
// ): (ResolvedModule | undefined)[];
/**
* @param {string[]} moduleNames
* @param {string} containingFile
* @return {Array<ts.ResolvedModule | undefined>}
*/
resolveModuleNames(moduleNames, containingFile) {
/** @type {string[]} */
const resolvedNames = dispatch("resolveModuleNames", {
moduleNames,
containingFile
Expand All @@ -216,37 +246,18 @@ class Host {
});
return r;
}

// resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
/*
resolveTypeReferenceDirectives() {
unreachable();
}
*/

// getEnvironmentVariable?(name: string): string | undefined;
getEnvironmentVariable() {
unreachable();
}

// createHash?(data: string): string;
createHash() {
unreachable();
}

// getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined;
getParsedCommandLine() {
unreachable();
}
}

/**
* @param {string} configurationText
*/
function configure(configurationText) {
const { config, error } = ts.parseConfigFileTextToJson(
"tsconfig.json",
configurationText
);
if (error) {
return { diagnostics: [error] };
return { options: {}, diagnostics: [error] };
}
const { options, errors } = ts.convertCompilerOptionsFromJson(
config.compilerOptions,
Expand All @@ -258,6 +269,10 @@ function configure(configurationText) {
};
}

/**
* @param {string} opName
* @param {Record<string,any>} obj
*/
function dispatch(opName, obj) {
const s = JSON.stringify(obj);
const msg = encode(s);
Expand All @@ -270,14 +285,21 @@ function dispatch(opName, obj) {
return res["ok"];
}

/**
* @param {number} code
*/
function exit(code) {
dispatch("exit", { code });
unreachable();
return unreachable();
}

// Maximum number of diagnostics to display.
const MAX_ERRORS = 5;

/**
* @param {ts.CompilerHost} host
* @param {ReadonlyArray<ts.Diagnostic> | undefined} diagnostics
*/
function handleDiagnostics(host, diagnostics) {
if (diagnostics && diagnostics.length) {
let rest = 0;
Expand All @@ -294,7 +316,10 @@ function handleDiagnostics(host, diagnostics) {
}
}

/** Returns the TypeScript Extension enum for a given media type. */
/** Returns the TypeScript Extension enum for a given media type.
* @param {string} fileName
* @returns {ts.Extension}
*/
function getExtension(fileName) {
if (fileName.endsWith(".d.ts")) {
return ts.Extension.Dts;
Expand Down
13 changes: 13 additions & 0 deletions deno_typescript/globals.d.ts
@@ -0,0 +1,13 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.

// This scopes the `ts` namespace globally, which is where it exists at runtime
// when building Deno, but the `typescript/lib/typescript.d.ts` is defined as a
// module

import * as _ts from "typescript";

declare global {
namespace ts {
export = _ts;
}
}

0 comments on commit 3779667

Please sign in to comment.