0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

Improve robustness of lib builder.

This commit is contained in:
Kitson Kelly 2018-11-04 10:45:06 +11:00 committed by Ryan Dahl
parent 2cf3a89f63
commit 765f229357
7 changed files with 102 additions and 12 deletions

View file

@ -75,14 +75,24 @@ export function checkDiagnostics(project: Project, onlyFor?: string[]) {
})
.map(diagnostic => diagnostic.compilerObject);
logDiagnostics(diagnostics);
if (diagnostics.length) {
console.log(
ts.formatDiagnosticsWithColorAndContext(diagnostics, formatDiagnosticHost)
);
process.exit(1);
}
}
function createDeclarationError(
msg: string,
declaration: ImportDeclaration | ExportDeclaration
): Error {
return new Error(
`${msg}\n` +
` In: "${declaration.getSourceFile().getFilePath()}"\n` +
` Text: "${declaration.getText()}"`
);
}
export interface FlattenNamespaceOptions {
customSources?: { [sourceFilePath: string]: string };
debug?: boolean;
@ -151,7 +161,12 @@ export function flattenNamespace({
}
sourceFile.getExportDeclarations().forEach(exportDeclaration => {
processSourceFile(exportDeclaration.getModuleSpecifierSourceFileOrThrow());
const exportedSourceFile = exportDeclaration.getModuleSpecifierSourceFile();
if (exportedSourceFile) {
processSourceFile(exportedSourceFile);
} else {
throw createDeclarationError("Missing source file.", exportDeclaration);
}
exportDeclaration.remove();
});
@ -254,9 +269,19 @@ export function loadFiles(project: Project, filePaths: string[]) {
}
}
/** Log diagnostics to the console with colour. */
export function logDiagnostics(diagnostics: ts.Diagnostic[]): void {
if (diagnostics.length) {
console.log(
ts.formatDiagnosticsWithColorAndContext(diagnostics, formatDiagnosticHost)
);
}
}
export interface NamespaceSourceFileOptions {
debug?: boolean;
namespace?: string;
namespaces: Set<string>;
rootPath: string;
sourceFileMap: Map<SourceFile, string>;
}
@ -267,7 +292,13 @@ export interface NamespaceSourceFileOptions {
*/
export function namespaceSourceFile(
sourceFile: SourceFile,
{ debug, namespace, rootPath, sourceFileMap }: NamespaceSourceFileOptions
{
debug,
namespace,
namespaces,
rootPath,
sourceFileMap
}: NamespaceSourceFileOptions
): string {
if (sourceFileMap.has(sourceFile)) {
return "";
@ -300,22 +331,42 @@ export function namespaceSourceFile(
const output = sourceFile
.getImportDeclarations()
.filter(declaration => {
const dsf = declaration.getModuleSpecifierSourceFile();
if (dsf == null) {
try {
const namespaceName = declaration
.getNamespaceImportOrThrow()
.getText();
if (!namespaces.has(namespaceName)) {
throw createDeclarationError(
"Already defined source file under different namespace.",
declaration
);
}
} catch (e) {
throw createDeclarationError(
"Unsupported import clause.",
declaration
);
}
declaration.remove();
}
return dsf;
})
.map(declaration => {
if (
declaration.getNamedImports().length ||
!declaration.getNamespaceImport()
) {
throw new Error(
"Unsupported import clause.\n" +
` In: "${declaration.getSourceFile().getFilePath()}"\n` +
` Text: "${declaration.getText()}"`
);
throw createDeclarationError("Unsupported import clause.", declaration);
}
const text = namespaceSourceFile(
declaration.getModuleSpecifierSourceFileOrThrow(),
{
debug,
namespace: declaration.getNamespaceImportOrThrow().getText(),
namespaces,
rootPath,
sourceFileMap
}
@ -328,6 +379,8 @@ export function namespaceSourceFile(
.getExportDeclarations()
.forEach(declaration => declaration.remove());
namespaces.add(namespace);
return `${output}
${globalNamespaceText || ""}

View file

@ -18,6 +18,7 @@ import {
getSourceComment,
loadDtsFiles,
loadFiles,
logDiagnostics,
namespaceSourceFile,
normalizeSlashes
} from "./ast_util";
@ -222,6 +223,7 @@ export function mergeGlobal({
// declaration source file into a namespace that exists within the merged
// namespace
const importDeclarations = sourceFile.getImportDeclarations();
const namespaces = new Set<string>();
for (const declaration of importDeclarations) {
const declarationSourceFile = declaration.getModuleSpecifierSourceFile();
if (
@ -241,6 +243,7 @@ export function mergeGlobal({
namespaceSourceFile(dtsSourceFile, {
debug,
namespace: declaration.getNamespaceImportOrThrow().getText(),
namespaces,
rootPath: basePath,
sourceFileMap
})
@ -308,6 +311,14 @@ export function main({
// emit the project, which will be only the declaration files
const inputEmitResult = inputProject.emitToMemory();
const inputDiagnostics = inputEmitResult
.getDiagnostics()
.map(d => d.compilerObject);
logDiagnostics(inputDiagnostics);
if (inputDiagnostics.length) {
process.exit(1);
}
// the declaration project will be the target for the emitted files from
// the input project, these will be used to transfer information over to
// the final library file

View file

@ -128,7 +128,10 @@ test(function buildLibraryMerge() {
});
assert(targetSourceFile.getNamespace("moduleC") != null);
assertEqual(targetSourceFile.getNamespaces().length, 1);
assert(targetSourceFile.getNamespace("moduleD") != null);
assert(targetSourceFile.getNamespace("moduleE") != null);
assert(targetSourceFile.getNamespace("moduleF") != null);
assertEqual(targetSourceFile.getNamespaces().length, 4);
assert(targetSourceFile.getInterface("FooBar") != null);
assertEqual(targetSourceFile.getInterfaces().length, 1);
const variableDeclarations = targetSourceFile.getVariableDeclarations();
@ -138,7 +141,15 @@ test(function buildLibraryMerge() {
variableDeclarations[2].getType().getText(),
`typeof moduleC.qat`
);
assertEqual(variableDeclarations.length, 3);
assertEqual(
variableDeclarations[3].getType().getText(),
`typeof moduleE.process`
);
assertEqual(
variableDeclarations[4].getType().getText(),
`typeof moduleD.reprocess`
);
assertEqual(variableDeclarations.length, 5);
});
// TODO author unit tests for `ast_util.ts`

View file

@ -1,6 +1,10 @@
import * as moduleC from "./moduleC";
import * as moduleD from "./moduleD";
import * as moduleE from "./moduleE";
// tslint:disable-next-line:no-any
const foobarbaz: any = {};
foobarbaz.bar = new moduleC.Bar();
foobarbaz.qat = moduleC.qat;
foobarbaz.process = moduleE.process;
foobarbaz.reprocess = moduleD.reprocess;

View file

@ -0,0 +1,5 @@
import * as moduleF from "./moduleF";
export function reprocess(value: typeof moduleF.key) {
console.log(value);
}

View file

@ -0,0 +1,5 @@
import * as moduleF from "./moduleF";
export function process(value: typeof moduleF.key) {
console.log(value);
}

View file

@ -0,0 +1 @@
export const key = "value";