mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 21:50:00 -05:00
Add JSDoc to deno_typescript (#2890)
This commit is contained in:
parent
46cbc6e0e9
commit
3779667646
4 changed files with 150 additions and 92 deletions
|
@ -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 => {
|
||||
|
|
|
@ -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}`);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
13
deno_typescript/globals.d.ts
vendored
Normal file
13
deno_typescript/globals.d.ts
vendored
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
6
deno_typescript/jsconfig.json
Normal file
6
deno_typescript/jsconfig.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"target": "esnext"
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue