catlint 1.3.0 → 2.0.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.
- package/dist/cjs/cli/commands/init.d.ts +1 -0
- package/dist/cjs/cli/commands/lint.d.ts +1 -0
- package/dist/{cli/index.d.cts → cjs/cli/index.d.ts} +1 -0
- package/dist/cjs/config/api/defineConfig.d.ts +2 -0
- package/dist/cjs/config/api/loadConfig.d.ts +3 -0
- package/dist/cjs/config/index.d.ts +3 -0
- package/dist/cjs/config/types/config.d.ts +17 -0
- package/dist/cjs/config/types/configAdapter.d.ts +2 -0
- package/dist/cjs/core/api/index.d.ts +3 -0
- package/dist/cjs/core/api/lintProject.d.ts +2 -0
- package/dist/cjs/core/api/linter.d.ts +5 -0
- package/dist/cjs/core/index.d.ts +2 -0
- package/dist/cjs/core/models/index.d.ts +1 -0
- package/dist/cjs/core/models/lintResult/index.d.ts +1 -0
- package/dist/cjs/core/models/lintResult/model.d.ts +7 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/ir/index.d.ts +1 -0
- package/dist/cjs/ir/models/File.d.ts +6 -0
- package/dist/cjs/ir/models/IRParser.d.ts +2 -0
- package/dist/cjs/ir/models/Node.d.ts +13 -0
- package/dist/cjs/ir/models/index.d.ts +3 -0
- package/dist/cjs/rules/helpers/defaultAdapter.d.ts +9 -0
- package/dist/cjs/rules/index.d.ts +1 -0
- package/dist/cjs/rules/models/index.d.ts +2 -0
- package/dist/cjs/rules/models/message/index.d.ts +1 -0
- package/dist/cjs/rules/models/message/model.d.ts +10 -0
- package/dist/cjs/rules/models/rule/index.d.ts +2 -0
- package/dist/cjs/rules/models/rule/model.d.ts +12 -0
- package/dist/cjs/rules/models/rule/service.d.ts +2 -0
- package/dist/cjs/shared/pattern/loadFiles.d.ts +1 -0
- package/dist/esm/cli/commands/init.d.ts +1 -0
- package/dist/esm/cli/commands/init.js +18 -0
- package/dist/esm/cli/commands/lint.d.ts +1 -0
- package/dist/esm/cli/commands/lint.js +6 -0
- package/dist/esm/cli/index.d.ts +2 -0
- package/dist/esm/cli/index.js +15 -0
- package/dist/esm/config/api/defineConfig.d.ts +2 -0
- package/dist/esm/config/api/defineConfig.js +8 -0
- package/dist/esm/config/api/loadConfig.d.ts +3 -0
- package/dist/esm/config/api/loadConfig.js +22 -0
- package/dist/esm/config/index.d.ts +3 -0
- package/dist/esm/config/index.js +3 -0
- package/dist/esm/config/types/config.d.ts +17 -0
- package/dist/esm/config/types/config.js +8 -0
- package/dist/esm/config/types/configAdapter.d.ts +2 -0
- package/dist/esm/config/types/configAdapter.js +8 -0
- package/dist/esm/core/api/index.d.ts +3 -0
- package/dist/esm/core/api/index.js +3 -0
- package/dist/esm/core/api/lintProject.d.ts +2 -0
- package/dist/esm/core/api/lintProject.js +16 -0
- package/dist/esm/core/api/linter.d.ts +5 -0
- package/dist/esm/core/api/linter.js +15 -0
- package/dist/esm/core/index.d.ts +2 -0
- package/dist/esm/core/index.js +2 -0
- package/dist/esm/core/models/index.d.ts +1 -0
- package/dist/esm/core/models/index.js +1 -0
- package/dist/esm/core/models/lintResult/index.d.ts +1 -0
- package/dist/esm/core/models/lintResult/index.js +1 -0
- package/dist/esm/core/models/lintResult/model.d.ts +7 -0
- package/dist/esm/core/models/lintResult/model.js +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/ir/index.d.ts +1 -0
- package/dist/esm/ir/index.js +1 -0
- package/dist/esm/ir/models/File.d.ts +6 -0
- package/dist/esm/ir/models/File.js +1 -0
- package/dist/esm/ir/models/IRParser.d.ts +2 -0
- package/dist/esm/ir/models/IRParser.js +1 -0
- package/dist/esm/ir/models/Node.d.ts +13 -0
- package/dist/esm/ir/models/Node.js +8 -0
- package/dist/esm/ir/models/index.d.ts +3 -0
- package/dist/esm/ir/models/index.js +3 -0
- package/dist/esm/rules/helpers/defaultAdapter.d.ts +9 -0
- package/dist/esm/rules/helpers/defaultAdapter.js +16 -0
- package/dist/esm/rules/index.d.ts +1 -0
- package/dist/esm/rules/index.js +1 -0
- package/dist/esm/rules/models/index.d.ts +2 -0
- package/dist/esm/rules/models/index.js +2 -0
- package/dist/esm/rules/models/message/index.d.ts +1 -0
- package/dist/esm/rules/models/message/index.js +1 -0
- package/dist/esm/rules/models/message/model.d.ts +10 -0
- package/dist/esm/rules/models/message/model.js +6 -0
- package/dist/esm/rules/models/rule/index.d.ts +2 -0
- package/dist/esm/rules/models/rule/index.js +2 -0
- package/dist/esm/rules/models/rule/model.d.ts +12 -0
- package/dist/esm/rules/models/rule/model.js +1 -0
- package/dist/esm/rules/models/rule/service.d.ts +2 -0
- package/dist/esm/rules/models/rule/service.js +9 -0
- package/dist/esm/shared/pattern/loadFiles.d.ts +1 -0
- package/dist/esm/shared/pattern/loadFiles.js +6 -0
- package/dist/types/cli/commands/init.d.ts +1 -0
- package/dist/types/cli/commands/lint.d.ts +1 -0
- package/dist/types/cli/index.d.ts +2 -0
- package/dist/types/config/api/defineConfig.d.ts +2 -0
- package/dist/types/config/api/loadConfig.d.ts +3 -0
- package/dist/types/config/index.d.ts +3 -0
- package/dist/types/config/types/config.d.ts +17 -0
- package/dist/types/config/types/configAdapter.d.ts +2 -0
- package/dist/types/core/api/index.d.ts +3 -0
- package/dist/types/core/api/lintProject.d.ts +2 -0
- package/dist/types/core/api/linter.d.ts +5 -0
- package/dist/types/core/index.d.ts +2 -0
- package/dist/types/core/models/index.d.ts +1 -0
- package/dist/types/core/models/lintResult/index.d.ts +1 -0
- package/dist/types/core/models/lintResult/model.d.ts +7 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/ir/index.d.ts +1 -0
- package/dist/types/ir/models/File.d.ts +6 -0
- package/dist/types/ir/models/IRParser.d.ts +2 -0
- package/dist/types/ir/models/Node.d.ts +13 -0
- package/dist/types/ir/models/index.d.ts +3 -0
- package/dist/types/rules/helpers/defaultAdapter.d.ts +9 -0
- package/dist/types/rules/index.d.ts +1 -0
- package/dist/types/rules/models/index.d.ts +2 -0
- package/dist/types/rules/models/message/index.d.ts +1 -0
- package/dist/types/rules/models/message/model.d.ts +10 -0
- package/dist/types/rules/models/rule/index.d.ts +2 -0
- package/dist/types/rules/models/rule/model.d.ts +12 -0
- package/dist/types/rules/models/rule/service.d.ts +2 -0
- package/dist/types/shared/pattern/loadFiles.d.ts +1 -0
- package/package.json +40 -15
- package/src/cli/commands/init.ts +1 -1
- package/src/cli/index.ts +1 -1
- package/src/config/api/loadConfig.ts +1 -1
- package/src/core/api/lintProject.ts +1 -1
- package/tsconfig.build.json +9 -0
- package/tsconfig.cjs.json +11 -0
- package/tsconfig.esm.json +11 -0
- package/tsconfig.json +3 -2
- package/dist/cli/index.cjs +0 -27896
- package/dist/index.cjs +0 -4976
- package/dist/index.d.cts +0 -80
- package/legacy/group/model.ts +0 -6
- package/legacy/group/service.ts +0 -13
- package/legacy/shared/yagni/index.ts +0 -4
- package/legacy/shared/yagni/noUnusedFeatures/index.ts +0 -4
- package/legacy/shared/yagni/noUnusedFeatures/main.ts +0 -10
- package/legacy/shared/yagni/noUnusedFeatures/noUnusedClasses.ts +0 -26
- package/legacy/shared/yagni/noUnusedFeatures/noUnusedFunctions.ts +0 -26
- package/legacy/shared/yagni/noUnusedFeatures/noUnusedVariables.ts +0 -26
- package/legacy/shared/yagni/utils.ts +0 -5
- package/tsup.config.ts +0 -13
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const init: () => Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const lint: () => Promise<void>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IRParser } from '../../ir/models/IRParser';
|
|
2
|
+
import type { AdaptedRule, Rule } from '../../rules/models/rule/model';
|
|
3
|
+
export interface Config {
|
|
4
|
+
lint: {
|
|
5
|
+
includes: string[];
|
|
6
|
+
excludes: string[];
|
|
7
|
+
};
|
|
8
|
+
parsers: {
|
|
9
|
+
pattern: string;
|
|
10
|
+
parser: IRParser;
|
|
11
|
+
}[];
|
|
12
|
+
rules: Rule[];
|
|
13
|
+
}
|
|
14
|
+
export interface NormalizedConfig extends Config {
|
|
15
|
+
rules: AdaptedRule[];
|
|
16
|
+
}
|
|
17
|
+
export declare const defaultConfig: NormalizedConfig;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LintResult } from '../models/lintResult/model';
|
|
2
|
+
import type { IRFile } from '../../ir/models/File';
|
|
3
|
+
import type { AdaptedRule } from '../../rules/models/rule/model';
|
|
4
|
+
export declare function travelFile(file: IRFile): (rule: AdaptedRule) => LintResult;
|
|
5
|
+
export declare function lintFile(file: IRFile, rules: AdaptedRule[]): LintResult[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lintResult';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './model';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './models';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AdaptedRule, Rule } from '../models/rule/model';
|
|
2
|
+
/**
|
|
3
|
+
* @function defaultAdapter recursively adapts a Rule to an AdaptedRule by providing default values for undefined/null fields.
|
|
4
|
+
*
|
|
5
|
+
* @param rule the rule to adapt
|
|
6
|
+
* @returns a AdaptedRule without undefined/null fields
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
export declare const defaultAdapter: (rule: Rule) => AdaptedRule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './models';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './model';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IRFile } from '../../../ir/models/File';
|
|
2
|
+
import type { Message } from '../../models/message/model';
|
|
3
|
+
export type RuleFn = (file: IRFile) => Message[];
|
|
4
|
+
export interface Rule {
|
|
5
|
+
name: string;
|
|
6
|
+
fn?: RuleFn;
|
|
7
|
+
subrules?: Rule[];
|
|
8
|
+
}
|
|
9
|
+
export interface AdaptedRule extends Rule {
|
|
10
|
+
fn: RuleFn;
|
|
11
|
+
subrules: AdaptedRule[];
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const loadFiles: (baseDir: string, includes: string[], excludes?: string[]) => Promise<string[]>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const init: () => Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { defaultConfig } from '../../config/index';
|
|
4
|
+
import { inspect } from 'util';
|
|
5
|
+
export const init = async () => {
|
|
6
|
+
const { useTypescript } = await inquirer.prompt([
|
|
7
|
+
{
|
|
8
|
+
type: 'confirm',
|
|
9
|
+
name: 'useTypescript',
|
|
10
|
+
message: 'Do you want to use typescript?',
|
|
11
|
+
default: true,
|
|
12
|
+
},
|
|
13
|
+
]);
|
|
14
|
+
fs.writeFileSync(`catlint.config.${useTypescript ? 'ts' : 'js'}`, `import { defineConfig } from 'catlint/config';
|
|
15
|
+
|
|
16
|
+
export default defineConfig(${inspect(defaultConfig)});
|
|
17
|
+
`);
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const lint: () => Promise<void>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { init } from './commands/init';
|
|
4
|
+
import { lint } from './commands/lint';
|
|
5
|
+
const program = new Command();
|
|
6
|
+
program.name('catlint').description('A linter for detecting code bad practices').version('0.0.1');
|
|
7
|
+
program
|
|
8
|
+
.command('init')
|
|
9
|
+
.description('Inits CatLint in your current project folder')
|
|
10
|
+
.action(async () => await init());
|
|
11
|
+
program
|
|
12
|
+
.command('lint')
|
|
13
|
+
.description('Lints the current project')
|
|
14
|
+
.action(async () => await lint());
|
|
15
|
+
program.parse();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { adaptConfig } from '../types/configAdapter';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { pathToFileURL } from 'url';
|
|
4
|
+
export const loadConfigFromFile = async (filePath) => {
|
|
5
|
+
try {
|
|
6
|
+
const config = await import(pathToFileURL(filePath).href);
|
|
7
|
+
return adaptConfig(config.default);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
console.log(`No config file found at ${filePath}`);
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export const loadConfig = async (projectPath) => {
|
|
15
|
+
const configPath = path.join(process.cwd(), projectPath) + '/catlint.config';
|
|
16
|
+
const config = (await loadConfigFromFile(configPath + '.js')) ??
|
|
17
|
+
(await loadConfigFromFile(configPath + '.ts'));
|
|
18
|
+
if (!config) {
|
|
19
|
+
throw new Error('No config file found');
|
|
20
|
+
}
|
|
21
|
+
return config;
|
|
22
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IRParser } from '../../ir/models/IRParser';
|
|
2
|
+
import type { AdaptedRule, Rule } from '../../rules/models/rule/model';
|
|
3
|
+
export interface Config {
|
|
4
|
+
lint: {
|
|
5
|
+
includes: string[];
|
|
6
|
+
excludes: string[];
|
|
7
|
+
};
|
|
8
|
+
parsers: {
|
|
9
|
+
pattern: string;
|
|
10
|
+
parser: IRParser;
|
|
11
|
+
}[];
|
|
12
|
+
rules: Rule[];
|
|
13
|
+
}
|
|
14
|
+
export interface NormalizedConfig extends Config {
|
|
15
|
+
rules: AdaptedRule[];
|
|
16
|
+
}
|
|
17
|
+
export declare const defaultConfig: NormalizedConfig;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { loadFiles } from '../../shared/pattern/loadFiles';
|
|
2
|
+
import { lintFile } from './linter';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import { Minimatch } from 'minimatch';
|
|
5
|
+
export const lintProject = async (config, projectDir) => {
|
|
6
|
+
const files = await loadFiles(projectDir, config.lint.includes, config.lint.excludes);
|
|
7
|
+
return files
|
|
8
|
+
.map((filePath) => {
|
|
9
|
+
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
10
|
+
const parser = config.parsers.find((parser) => new Minimatch(parser.pattern).match(filePath));
|
|
11
|
+
if (!parser)
|
|
12
|
+
console.error(`No parser found for file ${filePath}`);
|
|
13
|
+
return parser?.parser(fileContent, filePath) ?? {};
|
|
14
|
+
})
|
|
15
|
+
.map((file) => lintFile(file, config.rules));
|
|
16
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LintResult } from '../models/lintResult/model';
|
|
2
|
+
import type { IRFile } from '../../ir/models/File';
|
|
3
|
+
import type { AdaptedRule } from '../../rules/models/rule/model';
|
|
4
|
+
export declare function travelFile(file: IRFile): (rule: AdaptedRule) => LintResult;
|
|
5
|
+
export declare function lintFile(file: IRFile, rules: AdaptedRule[]): LintResult[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function travelFile(file) {
|
|
2
|
+
const travelRule = (rule) => {
|
|
3
|
+
return {
|
|
4
|
+
name: rule.name,
|
|
5
|
+
messages: rule.fn(file),
|
|
6
|
+
subrules: rule.subrules.map(travelRule),
|
|
7
|
+
isCorrect: rule.fn(file).length === 0 && rule.subrules.every((r) => travelRule(r).isCorrect),
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
return travelRule;
|
|
11
|
+
}
|
|
12
|
+
export function lintFile(file, rules) {
|
|
13
|
+
const results = rules.map((rule) => travelFile(file)(rule));
|
|
14
|
+
return results;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lintResult';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lintResult';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './model';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './model';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './models';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './models';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export var IRKind;
|
|
2
|
+
(function (IRKind) {
|
|
3
|
+
IRKind[IRKind["Codeline"] = 0] = "Codeline";
|
|
4
|
+
IRKind[IRKind["Literal"] = 1] = "Literal";
|
|
5
|
+
IRKind[IRKind["Function"] = 2] = "Function";
|
|
6
|
+
IRKind[IRKind["Class"] = 3] = "Class";
|
|
7
|
+
IRKind[IRKind["Variable"] = 4] = "Variable";
|
|
8
|
+
})(IRKind || (IRKind = {}));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AdaptedRule, Rule } from '../models/rule/model';
|
|
2
|
+
/**
|
|
3
|
+
* @function defaultAdapter recursively adapts a Rule to an AdaptedRule by providing default values for undefined/null fields.
|
|
4
|
+
*
|
|
5
|
+
* @param rule the rule to adapt
|
|
6
|
+
* @returns a AdaptedRule without undefined/null fields
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
export declare const defaultAdapter: (rule: Rule) => AdaptedRule;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const EMPTY_FN = () => [];
|
|
2
|
+
/**
|
|
3
|
+
* @function defaultAdapter recursively adapts a Rule to an AdaptedRule by providing default values for undefined/null fields.
|
|
4
|
+
*
|
|
5
|
+
* @param rule the rule to adapt
|
|
6
|
+
* @returns a AdaptedRule without undefined/null fields
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
export const defaultAdapter = (rule) => {
|
|
10
|
+
const { name, fn = EMPTY_FN, subrules = [] } = rule;
|
|
11
|
+
return {
|
|
12
|
+
name,
|
|
13
|
+
fn,
|
|
14
|
+
subrules: subrules.map(defaultAdapter),
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './models';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './models';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './model';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './model';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IRFile } from '../../../ir/models/File';
|
|
2
|
+
import type { Message } from '../../models/message/model';
|
|
3
|
+
export type RuleFn = (file: IRFile) => Message[];
|
|
4
|
+
export interface Rule {
|
|
5
|
+
name: string;
|
|
6
|
+
fn?: RuleFn;
|
|
7
|
+
subrules?: Rule[];
|
|
8
|
+
}
|
|
9
|
+
export interface AdaptedRule extends Rule {
|
|
10
|
+
fn: RuleFn;
|
|
11
|
+
subrules: AdaptedRule[];
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const loadFiles: (baseDir: string, includes: string[], excludes?: string[]) => Promise<string[]>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { glob } from 'glob';
|
|
2
|
+
export const loadFiles = async (baseDir, includes, excludes = []) => {
|
|
3
|
+
const included = (await Promise.all(includes.map((pattern) => glob(pattern, { cwd: baseDir, absolute: true })))).flat();
|
|
4
|
+
const excluded = (await Promise.all(excludes.map((pattern) => glob(pattern, { cwd: baseDir, absolute: true })))).flat();
|
|
5
|
+
return included.filter((file) => !excluded.includes(file));
|
|
6
|
+
};
|