knip 2.17.3 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,4 +9,5 @@ type GetDependenciesDeep = (configFilePath: string, dependencies: Set<string>, o
9
9
  manifest: Manifest;
10
10
  }) => Promise<Set<string>>;
11
11
  export declare const getDependenciesDeep: GetDependenciesDeep;
12
+ export declare const resolveExtendsSpecifier: (specifier: string) => string | undefined;
12
13
  export {};
@@ -56,14 +56,15 @@ const resolvePackageName = (namespace, pluginName) => {
56
56
  : `${namespace}-${pluginName}`;
57
57
  };
58
58
  const resolvePluginPackageName = (pluginName) => resolvePackageName('eslint-plugin', pluginName);
59
- const resolveExtendsSpecifier = (specifier) => {
59
+ export const resolveExtendsSpecifier = (specifier) => {
60
60
  if (isInternal(specifier))
61
61
  return;
62
62
  if (/\/eslint-(config|plugin)/.test(specifier))
63
63
  return specifier;
64
- const strippedSpecifier = specifier
65
- .replace(/(^plugin:|:.+$)/, '')
66
- .replace(/\/(eslint-)?(recommended.*|stylistic.*|strict.*|all)$/, '');
64
+ const noProtocolSpecifier = specifier.replace(/(^plugin:|:.+$)/, '');
65
+ if (noProtocolSpecifier.startsWith('@typescript-eslint/'))
66
+ return '@typescript-eslint/eslint-plugin';
67
+ const strippedSpecifier = noProtocolSpecifier.replace(/\/(eslint-)?(recommended|all)$/, '');
67
68
  if (/eslint-(config|plugin)-/.test(strippedSpecifier))
68
69
  return strippedSpecifier;
69
70
  const packageName = getPackageNameFromModuleSpecifier(strippedSpecifier);
@@ -17,16 +17,12 @@ const resolveExtensibleConfig = async (configFilePath) => {
17
17
  }
18
18
  return config;
19
19
  };
20
- const findJestDependencies = async (configFilePath, { cwd, manifest }) => {
21
- let config = configFilePath.endsWith('package.json')
22
- ? manifest.jest
23
- : await resolveExtensibleConfig(configFilePath);
24
- if (typeof config === 'function')
25
- config = await config();
26
- if (!config)
27
- return [];
28
- const replaceRootDir = (name) => name.includes('<rootDir>') ? join(cwd, name.replace(/^.*<rootDir>/, '')) : name;
20
+ const resolveDependencies = (config) => {
29
21
  const presets = (config.preset ? [config.preset] : []).map(preset => isInternal(preset) ? preset : join(preset, 'jest-preset'));
22
+ const projects = Array.isArray(config.projects)
23
+ ? config.projects.map(config => (typeof config === 'string' ? config : resolveDependencies(config))).flat()
24
+ : [];
25
+ const runner = config.runner ? [config.runner] : [];
30
26
  const environments = config.testEnvironment === 'jsdom' ? ['jest-environment-jsdom'] : [];
31
27
  const resolvers = config.resolver ? [config.resolver] : [];
32
28
  const reporters = config.reporters
@@ -45,6 +41,8 @@ const findJestDependencies = async (configFilePath, { cwd, manifest }) => {
45
41
  : []).filter(value => !/\$[0-9]/.test(value));
46
42
  return [
47
43
  ...presets,
44
+ ...projects,
45
+ ...runner,
48
46
  ...environments,
49
47
  ...resolvers,
50
48
  ...reporters,
@@ -53,6 +51,17 @@ const findJestDependencies = async (configFilePath, { cwd, manifest }) => {
53
51
  ...setupFilesAfterEnv,
54
52
  ...transform,
55
53
  ...moduleNameMapper,
56
- ].map(replaceRootDir);
54
+ ];
55
+ };
56
+ const findJestDependencies = async (configFilePath, { cwd, manifest }) => {
57
+ let config = configFilePath.endsWith('package.json')
58
+ ? manifest.jest
59
+ : await resolveExtensibleConfig(configFilePath);
60
+ if (typeof config === 'function')
61
+ config = await config();
62
+ if (!config)
63
+ return [];
64
+ const replaceRootDir = (name) => name.includes('<rootDir>') ? join(cwd, name.replace(/^.*<rootDir>/, '')) : name;
65
+ return resolveDependencies(config).map(replaceRootDir);
57
66
  };
58
67
  export const findDependencies = timerify(findJestDependencies);
@@ -1,18 +1,34 @@
1
1
  import { compact } from '../../util/array.js';
2
- import { isInternal } from '../../util/path.js';
2
+ import { dirname, isInternal, toAbsolute } from '../../util/path.js';
3
3
  import { timerify } from '../../util/Performance.js';
4
4
  import { hasDependency, load } from '../../util/plugin.js';
5
5
  export const NAME = 'TypeScript';
6
6
  export const ENABLERS = ['typescript'];
7
7
  export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
8
8
  export const CONFIG_FILE_PATTERNS = ['tsconfig.json'];
9
- const findTypeScriptDependencies = async (configFilePath) => {
9
+ const resolveExtensibleConfig = async (configFilePath) => {
10
10
  const config = await load(configFilePath);
11
+ if (config?.extends) {
12
+ if (isInternal(config.extends)) {
13
+ const presetConfigPath = toAbsolute(config.extends, dirname(configFilePath));
14
+ const presetConfig = await resolveExtensibleConfig(presetConfigPath);
15
+ Object.assign(config, presetConfig);
16
+ }
17
+ }
18
+ return config;
19
+ };
20
+ const findTypeScriptDependencies = async (configFilePath) => {
21
+ const config = await resolveExtensibleConfig(configFilePath);
11
22
  if (!config)
12
23
  return [];
13
24
  const extend = config.extends ? [config.extends].flat().filter(extend => !isInternal(extend)) : [];
14
25
  const plugins = compact(config.compilerOptions?.plugins?.map(plugin => plugin.name) ?? []);
15
26
  const importHelpers = config.compilerOptions?.importHelpers ? ['tslib'] : [];
16
- return [...extend, ...plugins, ...importHelpers];
27
+ const jsx = config.compilerOptions?.jsxImportSource
28
+ ? [config.compilerOptions.jsxImportSource]
29
+ : config.compilerOptions?.jsx
30
+ ? ['react']
31
+ : [];
32
+ return [...extend, ...plugins, ...importHelpers, ...jsx];
17
33
  };
18
34
  export const findDependencies = timerify(findTypeScriptDependencies);
@@ -3,10 +3,16 @@ type SymbolTable = Map<string, ts.Symbol>;
3
3
  type SymbolWithExports = ts.Symbol & {
4
4
  exports?: SymbolTable;
5
5
  };
6
+ type PragmaMap = {
7
+ arguments: {
8
+ factory: string;
9
+ };
10
+ };
6
11
  export interface BoundSourceFile extends ts.SourceFile {
7
12
  symbol?: SymbolWithExports;
8
13
  resolvedModules?: ts.ModeAwareCache<ts.ResolvedModuleWithFailedLookupLocations>;
9
14
  locals?: SymbolTable;
10
15
  scriptKind?: ts.ScriptKind;
16
+ pragmas?: Map<string, PragmaMap | PragmaMap[]>;
11
17
  }
12
18
  export {};
@@ -1,6 +1,6 @@
1
1
  import ts from 'typescript';
2
2
  import { debugLog } from '../util/debug.js';
3
- import { extname } from '../util/path.js';
3
+ import { extname, isInternal } from '../util/path.js';
4
4
  export class SourceFileManager {
5
5
  sourceFileCache = new Map();
6
6
  snapshotCache = new Map();
@@ -11,7 +11,8 @@ export class SourceFileManager {
11
11
  this.asyncCompilers = compilers[1];
12
12
  }
13
13
  createSourceFile(filePath, contents) {
14
- const sourceFile = ts.createSourceFile(filePath, contents, ts.ScriptTarget.Latest, true);
14
+ const setParentNodes = isInternal(filePath);
15
+ const sourceFile = ts.createSourceFile(filePath, contents, ts.ScriptTarget.Latest, setParentNodes);
15
16
  this.sourceFileCache.set(filePath, sourceFile);
16
17
  return sourceFile;
17
18
  }
@@ -5,6 +5,7 @@ import { isMaybePackageName } from '../util/modules.js';
5
5
  import { isInNodeModules } from '../util/path.js';
6
6
  import { isDeclarationFileExtension, isAccessExpression, getAccessExpressionName } from './ast-helpers.js';
7
7
  import getExportVisitors from './visitors/exports/index.js';
8
+ import { getJSXImplicitImportBase } from './visitors/helpers.js';
8
9
  import getImportVisitors from './visitors/imports/index.js';
9
10
  import getScriptVisitors from './visitors/scripts/index.js';
10
11
  const getVisitors = (sourceFile) => ({
@@ -20,6 +21,9 @@ export const getImportsAndExports = (sourceFile, options) => {
20
21
  const aliasedExports = {};
21
22
  const scripts = new Set();
22
23
  const importedInternalSymbols = new Map();
24
+ const jsxImport = getJSXImplicitImportBase(sourceFile);
25
+ if (jsxImport)
26
+ externalImports.add(jsxImport);
23
27
  const visitors = getVisitors(sourceFile);
24
28
  const addInternalImport = (options) => {
25
29
  const { identifier, specifier, symbol, filePath, isReExport } = options;
@@ -1,3 +1,4 @@
1
1
  import { BoundSourceFile } from '../SourceFile.js';
2
2
  export declare const isNotJS: (sourceFile: BoundSourceFile) => boolean;
3
3
  export declare const isJS: (sourceFile: BoundSourceFile) => boolean;
4
+ export declare function getJSXImplicitImportBase(sourceFile: BoundSourceFile): string | undefined;
@@ -1,3 +1,10 @@
1
1
  import ts from 'typescript';
2
2
  export const isNotJS = (sourceFile) => sourceFile.scriptKind !== ts.ScriptKind.JS && sourceFile.scriptKind !== ts.ScriptKind.JSX;
3
3
  export const isJS = (sourceFile) => sourceFile.scriptKind === ts.ScriptKind.JS || sourceFile.scriptKind === ts.ScriptKind.JSX;
4
+ export function getJSXImplicitImportBase(sourceFile) {
5
+ const jsxImportSourcePragmas = sourceFile.pragmas?.get('jsximportsource');
6
+ const jsxImportSourcePragma = Array.isArray(jsxImportSourcePragmas)
7
+ ? jsxImportSourcePragmas[jsxImportSourcePragmas.length - 1]
8
+ : jsxImportSourcePragmas;
9
+ return jsxImportSourcePragma?.arguments.factory;
10
+ }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.17.3";
1
+ export declare const version = "2.18.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.17.3';
1
+ export const version = '2.18.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "2.17.3",
3
+ "version": "2.18.0",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://github.com/webpro/knip",
6
6
  "repository": "github:webpro/knip",