Skip to content

Commit

Permalink
feat: Support types compiler option in compiler APIs (denoland#4155)
Browse files Browse the repository at this point in the history
Handles `types` in the compiler APIs to make it easier to supply
external type libraries.
  • Loading branch information
kitsonk committed Feb 27, 2020
1 parent daf7617 commit 1d26da6
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 7 deletions.
27 changes: 24 additions & 3 deletions cli/js/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,14 +202,35 @@ async function tsCompilerOnMessage({
sources: sources ? Object.keys(sources) : undefined
});

// resolve the root name, if there are sources, the root name does not
// get resolved
const resolvedRootName = sources
? rootName
: resolveModules([rootName])[0];

// recursively process imports, loading each file into memory. If there
// are sources, these files are pulled out of the there, otherwise the
// files are retrieved from the privileged side
const rootNames = sources
? processLocalImports(sources, [[resolvedRootName, resolvedRootName]])
: await processImports([[resolvedRootName, resolvedRootName]]);

// if there are options, convert them into TypeScript compiler options,
// and resolve any external file references
let convertedOptions: ts.CompilerOptions | undefined;
if (options) {
const result = convertCompilerOptions(options);
convertedOptions = result.options;
if (result.files) {
// any files supplied in the configuration are resolved externally,
// even if sources are provided
const resolvedNames = resolveModules(result.files);
rootNames.push(
...(await processImports(resolvedNames.map(rn => [rn, rn])))
);
}
}

const state: WriteFileState = {
type: request.type,
bundle,
Expand All @@ -227,8 +248,8 @@ async function tsCompilerOnMessage({
writeFile
}));
const compilerOptions = [defaultRuntimeCompileOptions];
if (options) {
compilerOptions.push(convertCompilerOptions(options));
if (convertedOptions) {
compilerOptions.push(convertedOptions);
}
if (bundle) {
compilerOptions.push(defaultBundlerOptions);
Expand Down Expand Up @@ -278,7 +299,7 @@ async function tsCompilerOnMessage({
? Object.assign(
{},
defaultTranspileOptions,
convertCompilerOptions(options)
convertCompilerOptions(options).options
)
: defaultTranspileOptions;

Expand Down
16 changes: 15 additions & 1 deletion cli/js/compiler_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,21 @@ export interface CompilerOptions {
| "es2020"
| "esnext";

/** List of names of type definitions to include. Defaults to `undefined`. */
/** List of names of type definitions to include. Defaults to `undefined`.
*
* The type definitions are resolved according to the normal Deno resolution
* irrespective of if sources are provided on the call. Like other Deno
* modules, there is no "magical" resolution. For example:
*
* Deno.compile(
* "./foo.js",
* undefined,
* {
* types: [ "./foo.d.ts", "https://deno.land/x/example/types.d.ts" ]
* }
* );
*
*/
types?: string[];
}

Expand Down
15 changes: 15 additions & 0 deletions cli/js/compiler_api_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ test(async function compilerApiCompileLib() {
assertEquals(Object.keys(actual), ["/foo.js.map", "/foo.js"]);
});

test(async function compilerApiCompileTypes() {
const [diagnostics, actual] = await compile(
"/foo.ts",
{
"/foo.ts": `console.log(Foo.bar);`
},
{
types: ["./cli/tests/subdir/foo_types.d.ts"]
}
);
assert(diagnostics == null);
assert(actual);
assertEquals(Object.keys(actual), ["/foo.js.map", "/foo.js"]);
});

test(async function transpileOnlyApi() {
const actual = await transpileOnly({
"foo.ts": `export enum Foo { Foo, Bar, Baz };\n`
Expand Down
21 changes: 19 additions & 2 deletions cli/js/compiler_util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,20 @@ export function createWriteFile(state: WriteFileState): WriteFileCallback {
};
}

export interface ConvertCompilerOptionsResult {
files?: string[];
options: ts.CompilerOptions;
}

/** Take a runtime set of compiler options as stringified JSON and convert it
* to a set of TypeScript compiler options. */
export function convertCompilerOptions(str: string): ts.CompilerOptions {
export function convertCompilerOptions(
str: string
): ConvertCompilerOptionsResult {
const options: CompilerOptions = JSON.parse(str);
const out: Record<string, unknown> = {};
const keys = Object.keys(options) as Array<keyof CompilerOptions>;
const files: string[] = [];
for (const key of keys) {
switch (key) {
case "jsx":
Expand Down Expand Up @@ -261,11 +269,20 @@ export function convertCompilerOptions(str: string): ts.CompilerOptions {
default:
throw new TypeError("Unexpected emit target.");
}
break;
case "types":
const types = options[key];
assert(types);
files.push(...types);
break;
default:
out[key] = options[key];
}
}
return out as ts.CompilerOptions;
return {
options: out as ts.CompilerOptions,
files: files.length ? files : undefined
};
}

/** An array of TypeScript diagnostic types we ignore. */
Expand Down
16 changes: 15 additions & 1 deletion cli/js/lib.deno.ns.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2156,7 +2156,21 @@ declare namespace Deno {
| "es2020"
| "esnext";

/** List of names of type definitions to include. Defaults to `undefined`. */
/** List of names of type definitions to include. Defaults to `undefined`.
*
* The type definitions are resolved according to the normal Deno resolution
* irrespective of if sources are provided on the call. Like other Deno
* modules, there is no "magical" resolution. For example:
*
* Deno.compile(
* "./foo.js",
* undefined,
* {
* types: [ "./foo.d.ts", "https://deno.land/x/example/types.d.ts" ]
* }
* );
*
*/
types?: string[];
}

Expand Down
3 changes: 3 additions & 0 deletions cli/tests/subdir/foo_types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare namespace Foo {
const bar: string;
}

0 comments on commit 1d26da6

Please sign in to comment.