Skip to content

Implementing more efficient cache invalidation in CLI #52

@johnsoncodehk

Description

@johnsoncodehk

Below is a custom rule that checks if the imported module is correctly added to package.json.

'missing-dependency'({ typescript: ts, sourceFile, reportError, languageServiceHost }) {
	const { noEmit } = languageServiceHost.getCompilationSettings();
	if (noEmit) {
		return;
	}
	const packageJsonPath = ts.findConfigFile(sourceFile.fileName, ts.sys.fileExists, 'package.json');
	if (!packageJsonPath) {
		return;
	}
	const packageJson = JSON.parse(ts.sys.readFile(packageJsonPath) ?? '');
	if (packageJson.private) {
		return;
	}
	const parentPackageJsonPath = ts.findConfigFile(path.dirname(path.dirname(packageJsonPath)), ts.sys.fileExists, 'package.json');
	const parentPackageJson = !!parentPackageJsonPath && parentPackageJsonPath !== packageJsonPath
		? JSON.parse(ts.sys.readFile(parentPackageJsonPath) ?? '')
		: {};
	ts.forEachChild(sourceFile, function visit(node) {
		if (
			ts.isImportDeclaration(node)
			&& !node.importClause?.isTypeOnly
			&& ts.isStringLiteral(node.moduleSpecifier)
			&& !node.moduleSpecifier.text.startsWith('./')
			&& !node.moduleSpecifier.text.startsWith('../')
		) {
			let moduleName = node.moduleSpecifier.text.split('/')[0];
			if (moduleName.startsWith('@')) {
				moduleName += '/' + node.moduleSpecifier.text.split('/')[1];
			}
			if (
				(
					packageJson.devDependencies?.[moduleName]
					|| parentPackageJson.dependencies?.[moduleName]
					|| parentPackageJson.devDependencies?.[moduleName]
					|| parentPackageJson.peerDependencies?.[moduleName]
				)
				&& !packageJson.dependencies?.[moduleName]
				&& !packageJson.peerDependencies?.[moduleName]
			) {
				reportError(
					`Module '${moduleName}' should be in the dependencies.`,
					node.getStart(sourceFile),
					node.getEnd()
				);
			}
		}
		ts.forEachChild(node, visit);
	});
},

This rule is not re-run when package.json changes, because cache invalidation only checks if the tsslint.config.ts and tsconfig include files have changed, but not package.json.

As a solution, we should probably proxy fs.readFileSync in the CLI to record the files that the rule depends on when it runs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions