Skip to content

Commit

Permalink
feat: standardize debug namespaces to file paths (#10599)
Browse files Browse the repository at this point in the history
* feat: standardize debug namespaces to file paths

* test: just a bit more

* Replace unseemly regex with simpler packages split
  • Loading branch information
JoshuaKGoldberg authored Jan 13, 2025
1 parent a175189 commit 49a94b3
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 10 deletions.
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export default tseslint.config(
// Internal repo rules
//

'@typescript-eslint/internal/debug-namespace': 'error',
'@typescript-eslint/internal/eqeq-nullish': 'error',
'@typescript-eslint/internal/no-poorly-typed-ts-props': 'error',
'@typescript-eslint/internal/no-relative-paths-to-internal-packages':
Expand Down
65 changes: 65 additions & 0 deletions packages/eslint-plugin-internal/src/rules/debug-namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { TSESTree } from '@typescript-eslint/utils';

import { getStaticValue } from '@typescript-eslint/utils/ast-utils';

import { createRule } from '../util';

function filePathToNamespace(filePath: string) {
const relativePath = filePath
.split(/packages[\\/]+/)
.slice(1)
.join('');

const relativeNamespace = relativePath
.replace(/^[\\/]/, '')
.replace(/(?:dist|lib|src)\//, '')
.replace(/\.\w+$/, '')
.replaceAll(/[^a-z0-9-]+/gi, ':');

return `typescript-eslint:${relativeNamespace}`;
}

export default createRule({
name: __filename,
meta: {
type: 'problem',
docs: {
description:
'Enforce consistent debug() namespaces based on package name and file path',
},
fixable: 'code',
messages: {
mismatched:
'debug() namespace should match package and file. Use the fixer to update it.',
},
schema: [],
},
defaultOptions: [],
create(context) {
const expected = filePathToNamespace(context.filename);
if (!expected) {
return {};
}

return {
'VariableDeclarator[id.name="log"] > CallExpression[arguments.length=1][callee.name="debug"]'(
node: TSESTree.CallExpression,
) {
const [argument] = node.arguments;
const staticValue = getStaticValue(argument);
if (
typeof staticValue?.value !== 'string' ||
staticValue.value === expected
) {
return;
}

context.report({
node: argument,
messageId: 'mismatched',
fix: fixer => fixer.replaceText(argument, `'${expected}'`),
});
},
};
},
});
2 changes: 2 additions & 0 deletions packages/eslint-plugin-internal/src/rules/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Linter } from '@typescript-eslint/utils/ts-eslint';

import debugNamespace from './debug-namespace';
import eqeqNullish from './eqeq-nullish';
import noPoorlyTypedTsProps from './no-poorly-typed-ts-props';
import noRelativePathsToInternalPackages from './no-relative-paths-to-internal-packages';
Expand All @@ -9,6 +10,7 @@ import pluginTestFormatting from './plugin-test-formatting';
import preferASTTypesEnum from './prefer-ast-types-enum';

export default {
'debug-namespace': debugNamespace,
'eqeq-nullish': eqeqNullish,
'no-poorly-typed-ts-props': noPoorlyTypedTsProps,
'no-relative-paths-to-internal-packages': noRelativePathsToInternalPackages,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { RuleTester } from '@typescript-eslint/rule-tester';

import rule from '../../src/rules/debug-namespace';

const ruleTester = new RuleTester();

ruleTester.run('debug-namespace', rule, {
invalid: [
{
code: "const log = debug('not:correct');",
errors: [
{
column: 19,
endColumn: 32,
line: 1,
messageId: 'mismatched',
},
],
filename: 'typescript-eslint/packages/example/file.ts',
output: "const log = debug('typescript-eslint:example:file');",
},
{
code: "const log = debug('not:correct');",
errors: [
{
column: 19,
endColumn: 32,
line: 1,
messageId: 'mismatched',
},
],
filename: '/Users/example/typescript-eslint/packages/example/file.ts',
output: "const log = debug('typescript-eslint:example:file');",
},
{
code: "const log = debug('not:correct');",
errors: [
{
column: 19,
endColumn: 32,
line: 1,
messageId: 'mismatched',
},
],
filename: 'C:\\Code\\typescript-eslint\\packages\\example\\file.ts',
output: "const log = debug('typescript-eslint:example:file');",
},
],
valid: [
{
code: "const log = debug('typescript-eslint:example:file');",
filename: 'typescript-eslint/packages/example/file.ts',
},
{
code: "const logCustom = debug('typescript-eslint:example:file');",
filename: 'typescript-eslint/packages/example/file.ts',
},
{
code: "const logCustom = debug('...');",
filename: 'typescript-eslint/packages/example/file.ts',
},
{
code: "debug('...');",
filename: 'typescript-eslint/packages/example/file.ts',
},
{
code: 'const log = debug(null);',
filename: 'typescript-eslint/packages/example/file.ts',
},
{
code: 'const log = debug(123);',
filename: 'typescript-eslint/packages/example/file.ts',
},
],
});
2 changes: 1 addition & 1 deletion packages/type-utils/src/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as ts from 'typescript';

import { isTypeFlagSet } from './typeFlagUtils';

const log = debug('typescript-eslint:eslint-plugin:utils:types');
const log = debug('typescript-eslint:type-utils:predicates');

/**
* Checks if the given type is (or accepts) nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import type { ASTAndDefiniteProgram } from './shared';
import { getScriptKind } from './getScriptKind';
import { createDefaultCompilerOptionsFromExtra } from './shared';

const log = debug('typescript-eslint:typescript-estree:createIsolatedProgram');
const log = debug(
'typescript-eslint:typescript-estree:create-program:createIsolatedProgram',
);

/**
* @returns Returns a new source file and program corresponding to the linted code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import { firstDefined } from '../node-utils';
import { createProjectProgramError } from './createProjectProgramError';
import { getAstFromProgram } from './shared';

const log = debug('typescript-eslint:typescript-estree:createProjectProgram');
const log = debug(
'typescript-eslint:typescript-estree:create-program:createProjectProgram',
);

/**
* @param parseSettings Internal settings for parsing the file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { validateDefaultProjectForFilesGlob } from './validateDefaultProjectForF

const DEFAULT_PROJECT_MATCHED_FILES_THRESHOLD = 8;

const log = debug('typescript-eslint:typescript-estree:createProjectService');
const log = debug(
'typescript-eslint:typescript-estree:create-program:createProjectService',
);
const logTsserverErr = debug(
'typescript-eslint:typescript-estree:tsserver:err',
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import type { ASTAndNoProgram } from './shared';
import { isSourceFile } from '../source-files';
import { getScriptKind } from './getScriptKind';

const log = debug('typescript-eslint:typescript-estree:createSourceFile');
const log = debug(
'typescript-eslint:typescript-estree:create-program:createSourceFile',
);

function createSourceFile(parseSettings: ParseSettings): ts.SourceFile {
log(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import {
getCanonicalFileName,
} from './shared';

const log = debug('typescript-eslint:typescript-estree:createWatchProgram');
const log = debug(
'typescript-eslint:typescript-estree:create-program:getWatchProgramsForProjects',
);

/**
* Maps tsconfig paths to their corresponding file contents and resulting watches
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import type { ASTAndDefiniteProgram } from './shared';
import { getParsedConfigFile } from './getParsedConfigFile';
import { getAstFromProgram } from './shared';

const log = debug('typescript-eslint:typescript-estree:useProvidedProgram');
const log = debug(
'typescript-eslint:typescript-estree:create-program:useProvidedPrograms',
);

function useProvidedPrograms(
programInstances: Iterable<ts.Program>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { resolveProjectList } from './resolveProjectList';
import { warnAboutTSVersion } from './warnAboutTSVersion';

const log = debug(
'typescript-eslint:typescript-estree:parser:parseSettings:createParseSettings',
'typescript-eslint:typescript-estree:parseSettings:createParseSettings',
);

let TSCONFIG_MATCH_CACHE: ExpiringCache<string, string> | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import * as path from 'node:path';
import type { TSESTreeOptions } from '../parser-options';
import type { ParseSettings } from './index';

const log = debug('typescript-eslint:typescript-estree:getProjectConfigFiles');
const log = debug(
'typescript-eslint:typescript-estree:parseSettings:getProjectConfigFiles',
);

/**
* Checks for a matching TSConfig to a file including its parent directories,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from './ExpiringCache';

const log = debug(
'typescript-eslint:typescript-estree:parser:parseSettings:resolveProjectList',
'typescript-eslint:typescript-estree:parseSettings:resolveProjectList',
);

let RESOLUTION_CACHE: ExpiringCache<
Expand Down

0 comments on commit 49a94b3

Please sign in to comment.