Skip to content

Commit

Permalink
fix: declaration generation error (umijs#733)
Browse files Browse the repository at this point in the history
  • Loading branch information
ninesunsabiu committed Feb 24, 2024
1 parent 1d6debf commit ef4e8d0
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 31 deletions.
35 changes: 19 additions & 16 deletions src/builder/bundless/dts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,13 @@ export default async function getDeclarations(
sourceFile,
};

// only collect dts for input files, to avoid output error in watch mode
// ref: https://github.com/umijs/father-next/issues/43
if (inputFiles.includes(sourceFile)) {
const index = output.findIndex(
(out) => out.file === ret.file && out.sourceFile === ret.sourceFile,
);
if (index > -1) {
output.splice(index, 1, ret);
} else {
output.push(ret);
}
const index = output.findIndex(
(out) => out.file === ret.file && out.sourceFile === ret.sourceFile,
);
if (index > -1) {
output.splice(index, 1, ret);
} else {
output.push(ret);
}

// group cache by file (d.ts & d.ts.map)
Expand Down Expand Up @@ -221,11 +217,14 @@ export default async function getDeclarations(

// check compile error
// ref: https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API#a-minimal-compiler
const diagnostics = ts
const allDiagnostics = ts
.getPreEmitDiagnostics(incrProgram.getProgram())
.concat(result.diagnostics)
// omit error for files which not included by build
.filter((d) => !d.file || inputFiles.includes(d.file.fileName));
.concat(result.diagnostics);

// omit error for files which not included by build
const diagnostics = allDiagnostics.filter(
(d) => !d.file || inputFiles.includes(d.file.fileName),
);

/* istanbul ignore if -- @preserve */
if (diagnostics.length) {
Expand Down Expand Up @@ -256,7 +255,11 @@ export default async function getDeclarations(
});
throw new Error('Declaration generation failed.');
}

return output.filter(
(it) => !allDiagnostics.some((d) => d.file?.fileName === it.sourceFile),
);
}

return output;
return [];
}
68 changes: 53 additions & 15 deletions src/builder/bundless/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ function replacePathExt(filePath: string, ext: string) {
return path.join(parsed.dir, `${parsed.name}${ext}`);
}

/**
* checks if a file path is located within a specific directory.
*/
const isFileInDir = (filePath: string, dirPath: string) => {
return filePath.startsWith(winPath(dirPath).replace(/\/+$/, ''));
};

/**
* transform specific files
*/
Expand All @@ -41,22 +48,36 @@ async function transformFiles(
watch?: true;
},
) {
// get config and dist path info for specific item
const itemPathInfo = (item: string) => {
const config = opts.configProvider.getConfigForFile(item);

if (config) {
const itemDistPath = path.join(
config.output!,
path.relative(config.input, item),
);
const itemDistAbsPath = path.join(opts.cwd, itemDistPath);
const itemDistDir = path.dirname(itemDistAbsPath);

return { config, itemDistPath, itemDistAbsPath, itemDistDir };
} else {
return null;
}
};

try {
let count = 0;
const declarationFileMap = new Map<string, string>();

// process all matched items
for (let item of files) {
const config = opts.configProvider.getConfigForFile(item);
const pathInfo = itemPathInfo(item);
const itemAbsPath = path.join(opts.cwd, item);

if (config) {
let itemDistPath = path.join(
config.output!,
path.relative(config.input, item),
);
let itemDistAbsPath = path.join(opts.cwd, itemDistPath);
const parentPath = path.dirname(itemDistAbsPath);
if (pathInfo) {
const { config, itemDistDir: parentPath, ...itemDisInfo } = pathInfo;
let { itemDistPath, itemDistAbsPath } = itemDisInfo;

// create parent directory if not exists
if (!fs.existsSync(parentPath)) {
Expand Down Expand Up @@ -124,13 +145,30 @@ async function transformFiles(
},
);

declarations.forEach((item) => {
fs.writeFileSync(
path.join(declarationFileMap.get(item.sourceFile)!, item.file),
item.content,
'utf-8',
);
});
declarations
// filterMap: filter out declarations with unrecognized distDir and mapping it
.flatMap(({ sourceFile, ...declaration }) => {
// Prioritize using declarationFileMap
// If not available, try to recalculate itemDistDir
const distDir =
declarationFileMap.get(sourceFile) ??
(() => {
const watchRoot = path.join(opts.cwd, opts.configProvider.input);
const isInWatchDir = isFileInDir(sourceFile, watchRoot);
return isInWatchDir
? itemPathInfo(path.relative(opts.cwd, sourceFile))?.itemDistDir
: undefined;
})();

return distDir ? [{ distDir, declaration }] : [];
})
.forEach(({ distDir, declaration }) => {
fs.writeFileSync(
path.join(distDir, declaration.file),
declaration.content,
'utf-8',
);
});
}

return count;
Expand Down

0 comments on commit ef4e8d0

Please sign in to comment.