Repository: sweepline/eslint-plugin-unused-imports
Branch: master
Commit: 853a372a6713
Files: 23
Total size: 24.8 KB
Directory structure:
gitextract_523dtdv8/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ └── bug_report.md
│ └── workflows/
│ ├── release.yml
│ └── run_test.yml
├── .gitignore
├── .prettierrc.js
├── .vscode/
│ └── launch.json
├── LICENSE
├── README.md
├── docs/
│ └── rules/
│ ├── no-unused-imports.md
│ └── no-unused-vars.md
├── package.json
├── pnpm-workspace.yaml
├── src/
│ ├── __test__/
│ │ ├── cases-js.ts
│ │ ├── cases-ts.ts
│ │ └── no-unused-imports.test.ts
│ ├── index.ts
│ └── rules/
│ ├── load-rule.ts
│ ├── no-unused-imports.ts
│ ├── no-unused-vars.ts
│ └── predicates.ts
├── tsconfig.json
├── tsup.config.ts
└── vitest.config.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ""
labels: ""
assignees: ""
---
# Please follow the general troubleshooting steps first:
If the issue is with something being marked wrongly as a unused import and therefore being removed. It is an issue with the imported package (`@typescript-eslint/eslint-plugin` for TS or `eslint` for JS) and its `no-unused-vars` rule. I cannot do anything about this except updating if a fix is made upstream.
If new rules are added `no-unused-vars` upstream which should be autofixed, mark your issue _rule addition_.
Now if something is not marked an import and being removed by the autofixer, it is an issue I can do something about.
Please replace the above with a brief summary of your issue.
### Features:
**Please note by far the quickest way to get a new feature is to file a Pull Request.**
================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
uses: sxzz/workflows/.github/workflows/release.yml@v1
with:
publish: true
permissions:
contents: write
id-token: write
================================================
FILE: .github/workflows/run_test.yml
================================================
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name: Node.js CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: pnpm install
- run: pnpm run build
- run: pnpm test
================================================
FILE: .gitignore
================================================
node_modules
.idea
dist
================================================
FILE: .prettierrc.js
================================================
module.exports = {
tabWidth: 4,
semi: true, // Trailing semicolons
trailingComma: "all",
singleQuote: false,
quoteProps: "as-needed",
bracketSpacing: true,
printWidth: 100, // Line width (this fit my 1440p screen at a half-screen window)
arrowParens: "always",
};
================================================
FILE: .vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.1.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug current test file",
"runtimeExecutable": "npm",
"runtimeArgs": ["test", "--testPathPattern", "${file}", "--coverage", "false"],
"port": 9229,
"cwd": "${fileDirname}",
"timeout": 10000,
"console": "integratedTerminal"
}
]
}
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2022 Mikkel Holmer Pedersen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# eslint-plugin-unused-imports
Find and remove unused es6 module imports. It works by splitting up the `no-unused-vars` rule depending on it being an import statement in the AST and providing an autofix rule to remove the nodes if they are imports. This plugin composes the rule `no-unused-vars` of either the typescript or js plugin so be aware that the other plugins needs to be installed and reporting correctly for this to do so.
## _Versions_
- Version 4.1.x is for eslint 9 with @typescript-eslint/eslint-plugin 5 - 8
- Version 4.0.x is for eslint 9 with @typescript-eslint/eslint-plugin 8
- Version 3.x.x is for eslint 8 with @typescript-eslint/eslint-plugin 6 - 7
- Version 2.x.x is for eslint 8 with @typescript-eslint/eslint-plugin 5
- Version 1.x.x is for eslint 6 and 7.
## Typescript
If running typescript with [@typescript-eslint](https://github.com/typescript-eslint/typescript-eslint) make sure to use both `@typescript-eslint/eslint-plugin` and `@typescript-eslint/parser`.
## React
If writing react code you need to install `eslint-plugin-react` and enable the two rules `react/jsx-uses-react` and `react/jsx-uses-vars`. Otherwise all imports for components will be reported unused.
## Installation
You'll first need to install [ESLint](http://eslint.org) (and [@typescript-eslint](https://github.com/typescript-eslint/typescript-eslint) if using typescript):
```bash
npm i eslint --save-dev
```
Next, install `eslint-plugin-unused-imports`:
```bash
npm install eslint-plugin-unused-imports --save-dev
```
**Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `eslint-plugin-unused-imports` globally.
## Usage
Add `unused-imports` to the plugins section of your `eslint.config.js` configuration file.
```js
import unusedImports from "eslint-plugin-unused-imports";
export default [{
plugins: {
"unused-imports": unusedImports,
},
rules: {
"no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
"vars": "all",
"varsIgnorePattern": "^_",
"args": "after-used",
"argsIgnorePattern": "^_",
},
]
}
}];
```
## Supported Rules
- `no-unused-imports`
- `no-unused-vars`
================================================
FILE: docs/rules/no-unused-imports.md
================================================
# Do not allow unused imports (no-unused-imports)
A rule to find unused-imports only, as well as an autofixer.
================================================
FILE: docs/rules/no-unused-vars.md
================================================
# Do not allow unused vars (no-unused-vars)
This is just a helper rule to filter out the things caught by
the `no-unused-imports` rule without double warnings. As
well as being able to set them at different warning levels.
================================================
FILE: package.json
================================================
{
"name": "eslint-plugin-unused-imports",
"version": "4.4.1",
"type": "commonjs",
"packageManager": "pnpm@10.18.3",
"description": "Report and remove unused es6 modules",
"keywords": [
"eslint",
"eslintplugin",
"eslint-plugin",
"import",
"unused",
"modules",
"autofix"
],
"author": "Mikkel Holmer Pedersen",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsup",
"test": "vitest",
"format": "prettier --write '**/*.[jt]s'",
"prepack": "npm run build",
"release": "bumpp"
},
"peerDependencies": {
"@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0",
"eslint": "^10.0.0 || ^9.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"@typescript-eslint/eslint-plugin": {
"optional": true
}
},
"devDependencies": {
"@types/eslint": "^9.6.1",
"@typescript-eslint-v5/eslint-plugin": "npm:@typescript-eslint/eslint-plugin@^5.62.0",
"@typescript-eslint-v5/parser": "npm:@typescript-eslint/parser@^5.62.0",
"@typescript-eslint-v6/eslint-plugin": "npm:@typescript-eslint/eslint-plugin@^6.21.0",
"@typescript-eslint-v6/parser": "npm:@typescript-eslint/parser@^6.21.0",
"@typescript-eslint-v7/eslint-plugin": "npm:@typescript-eslint/eslint-plugin@^7.18.0",
"@typescript-eslint-v7/parser": "npm:@typescript-eslint/parser@^7.18.0",
"@typescript-eslint/eslint-plugin": "^8.46.1",
"@typescript-eslint/parser": "^8.46.1",
"@typescript-eslint/utils": "^8.46.1",
"bumpp": "^10.3.1",
"eslint": "^9.37.0",
"prettier": "^3.6.2",
"tsup": "^8.5.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.46.1",
"vitest": "^3.2.4"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/sweepline/eslint-plugin-unused-imports.git"
},
"homepage": "https://github.com/sweepline/eslint-plugin-unused-imports",
"bugs": "https://github.com/sweepline/eslint-plugin-unused-imports/issues"
}
================================================
FILE: pnpm-workspace.yaml
================================================
onlyBuiltDependencies:
- esbuild
================================================
FILE: src/__test__/cases-js.ts
================================================
export default {
valid: [
{
code: `
import x from "package";
import { a, b } from "./utils";
import y from "package";
const c = a() + b + x() + y();
`,
},
{
code: `
import { NoAuthenticationGuard } from "./no-authentication.guard";
import { JwtAuthenticationGuard } from "./jwt-authentication.guard";
/**
* You can reference {@link NoAuthenticationGuard} instead.
* It's recommended to use the {@link JwtAuthenticationGuard}.
*/
const LOCAL_ENVIRONMENT_AUTHENTICATION_GUARD = JwtAuthenticationGuard;
`,
},
{
code: `
import { SomeClass } from "./some-class";
/**
* @see SomeClass
*/
const example = "test";
`,
},
{
code: `
import { MyType } from "./types";
/**
* @type {MyType}
*/
let value;
`,
},
{
code: `
import { Config } from "./config";
/**
* @param {Config} config - The configuration object
*/
function setup(config) {}
`,
},
],
invalid: [
{
code: `
import x from "package";
import { a, b } from "./utils";
import y from "package";
const c = b(x, y);
`,
errors: ["'a' is defined but never used."],
output: `
import x from "package";
import { b } from "./utils";
import y from "package";
const c = b(x, y);
`,
},
{
code: `
import { a, b } from "./utils";
import y from "package";
/**
* this is a jsdoc!
*/
const c = a(y);
`,
errors: ["'b' is defined but never used."],
output: `
import { a } from "./utils";
import y from "package";
/**
* this is a jsdoc!
*/
const c = a(y);
`,
},
{
code: `
import { a } from "./utils";
import y from "package";
const c = 4;
console.log(y);
`,
errors: ["'a' is defined but never used."],
output: `
import y from "package";
const c = 4;
console.log(y);
`,
},
{
code: `
import y from "package";
import { a } from "./utils";
/**
* c is the number 4
*/
const c = 4;
console.log(y);
`,
errors: ["'a' is defined but never used."],
output: `
import y from "package";
/**
* c is the number 4
*/
const c = 4;
console.log(y);
`,
},
{
code: `
import { UnusedClass } from "./unused";
import { UsedInJSDoc } from "./used";
/**
* Reference to {@link UsedInJSDoc}
*/
const example = "test";
`,
errors: ["'UnusedClass' is defined but never used."],
output: `
import { UsedInJSDoc } from "./used";
/**
* Reference to {@link UsedInJSDoc}
*/
const example = "test";
`,
},
],
};
================================================
FILE: src/__test__/cases-ts.ts
================================================
export default {
valid: [
{
code: `
import x from "package";
import { a, b } from "./utils";
import y from "package";
import TType from "Package";
const c: TType = a() + b + x() + y();
`,
},
{
code: `
import { NoAuthenticationGuard } from "./no-authentication.guard";
import { JwtAuthenticationGuard } from "./jwt-authentication.guard";
/**
* You can reference {@link NoAuthenticationGuard} instead.
* It's recommended to use the {@link JwtAuthenticationGuard}.
*/
const LOCAL_ENVIRONMENT_AUTHENTICATION_GUARD = JwtAuthenticationGuard;
`,
},
{
code: `
import type { SomeType } from "./types";
/**
* @see SomeType for more details
*/
const example = "test";
`,
},
{
code: `
import type { Config } from "./config";
/**
* @param {Config} config - The configuration object
*/
function setup(config: any) {}
`,
},
],
invalid: [
{
code: `
import x from "package";
import { a, b } from "./utils";
import y from "package";
import TType from "Package";
const c = a() + b + x() + y();
`,
errors: ["'TType' is defined but never used."],
output: `
import x from "package";
import { a, b } from "./utils";
import y from "package";
const c = a() + b + x() + y();
`,
},
{
code: `
import type { UnusedType } from "./unused";
import type { UsedInJSDoc } from "./used";
/**
* Reference to {@link UsedInJSDoc}
*/
const example = "test";
`,
errors: ["'UnusedType' is defined but never used."],
output: `
import type { UsedInJSDoc } from "./used";
/**
* Reference to {@link UsedInJSDoc}
*/
const example = "test";
`,
},
],
};
================================================
FILE: src/__test__/no-unused-imports.test.ts
================================================
import { RuleTester } from "eslint";
import casesJS from "./cases-js";
import casesTS from "./cases-ts";
import { it, describe } from "vitest";
import { createRuleWithPredicate, unusedImportsPredicate } from "../rules/predicates";
import { getESLintBaseRule } from "../rules/load-rule";
const parsers = [
{
name: "eslint",
parser: undefined,
rule: getESLintBaseRule(),
},
{
name: "typescript-eslint v8",
parser: await import("@typescript-eslint/parser").then((r) => r.default),
rule: await import("@typescript-eslint/eslint-plugin").then(
(r) => r.rules["no-unused-vars"],
),
},
{
name: "typescript-eslint v7",
parser: await import("@typescript-eslint-v7/parser").then((r) => r.default),
rule: await import("@typescript-eslint-v7/eslint-plugin").then(
(r) => r.rules["no-unused-vars"],
),
},
{
name: "typescript-eslint v6",
parser: await import("@typescript-eslint-v6/parser").then((r) => r.default),
rule: await import("@typescript-eslint-v6/eslint-plugin").then(
(r) => r.rules["no-unused-vars"],
),
},
{
name: "typescript-eslint v5",
parser: await import("@typescript-eslint-v5/parser").then((r) => r.default),
rule: await import("@typescript-eslint-v5/eslint-plugin").then(
(r) => r.rules["no-unused-vars"],
),
},
];
describe("no-unused-imports", () => {
for (const { name, parser, rule: baseRule } of parsers) {
it(`with ${name}`, () => {
const ruleTester = new RuleTester({
languageOptions: {
parser,
ecmaVersion: 2015,
sourceType: "module",
},
});
const rule = createRuleWithPredicate(
"no-unused-imports",
baseRule,
unusedImportsPredicate,
);
ruleTester.run("no-unused-imports", rule, casesJS);
if (name !== "eslint") {
ruleTester.run("no-unused-imports", rule, casesTS);
}
});
}
});
================================================
FILE: src/index.ts
================================================
/**
* @fileoverview Find and remove unused es6 modules
* @author Mikkel Holmer Pedersen
*/
import noUnusedVars from "./rules/no-unused-vars";
import noUnusedImports from "./rules/no-unused-imports";
import { ESLint } from "eslint";
const plugin: ESLint.Plugin = {
meta: {
name: "unused-imports",
},
rules: {
"no-unused-vars": noUnusedVars,
"no-unused-imports": noUnusedImports,
},
};
export default plugin;
================================================
FILE: src/rules/load-rule.ts
================================================
import { Rule } from "eslint";
import { createRequire } from "module";
let rule: Rule.RuleModule | undefined;
const require = createRequire(import.meta.url);
export function getBaseRule(): Rule.RuleModule {
if (!rule) {
rule = getRuleFromTSLintPlugin() ?? getRuleFromTSLint() ?? getESLintBaseRule();
}
return rule!;
}
export function getRuleFromTSLintPlugin() {
try {
const tslintPlugin = require("@typescript-eslint/eslint-plugin");
return tslintPlugin.rules["no-unused-vars"];
} catch (_) {
return null;
}
}
export function getRuleFromTSLint() {
try {
const tslint = require("typescript-eslint");
return tslint.plugin.rules["no-unused-vars"];
} catch (_) {
return null;
}
}
export function getESLintBaseRule() {
try {
const eslint = require("eslint");
return new eslint.Linter({ configType: "eslintrc" }).getRules().get("no-unused-vars");
} catch {
// since ESLint 10.0.0, new Linter({ configType: "eslintrc" }) will now throw an TypeError explicitly:
// https://github.com/eslint/eslint/blob/b69cfb32a16c5d5e9986390d484fae1d21e406f9/lib/linter/linter.js#L757
//
// This means we can catch the error and load the rule from an unsafe API:
const eslint_USE_AT_YOUR_OWN_RISK = require("eslint/use-at-your-own-risk");
// builtinRules was added since ESLint 8.0.0 and was mentioned in ESLint's "Migrate to ESLint 8.0.0" guide:
// https://eslint.org/docs/latest/use/migrate-to-8.0.0#-the-cliengine-class-has-been-removed
//
// However, it's still considered an unstable API and may change without a major version bump. We need to guard the access.
if ('builtinRules' in eslint_USE_AT_YOUR_OWN_RISK && eslint_USE_AT_YOUR_OWN_RISK.builtinRules instanceof Map) {
return eslint_USE_AT_YOUR_OWN_RISK.builtinRules.get("no-unused-vars");
}
throw new TypeError("[eslint-plugin-unused-imports] Cannot load 'no-unused-vars' rule from ESLint. This is most likely due to a breaking change in ESLint's internal API. Please report this issue to 'eslint-plugin-unused-imports'.");
}
}
================================================
FILE: src/rules/no-unused-imports.ts
================================================
/**
* @fileoverview Add fixer to imports in no-unused-vars.
* @author Mikkel Holmer Pedersen <mikkel@holmerp.dk>
*/
import { unusedImportsPredicate, createRuleWithPredicate } from "./predicates";
import { getBaseRule } from "./load-rule";
export default createRuleWithPredicate("no-unused-imports", getBaseRule(), unusedImportsPredicate);
================================================
FILE: src/rules/no-unused-vars.ts
================================================
/**
* @fileoverview Filter imports from no-unused-vars.
* @author Mikkel Holmer Pedersen <mikkel@holmerp.dk>
*/
import { createRuleWithPredicate, unusedVarsPredicate } from "./predicates";
import { getBaseRule } from "./load-rule";
export default createRuleWithPredicate("no-unused-vars", getBaseRule(), unusedVarsPredicate);
================================================
FILE: src/rules/predicates.ts
================================================
import { SourceCode, AST, Rule } from "eslint";
export type Predicate = (
problem: Rule.ReportDescriptor,
context: Rule.RuleContext,
) => Rule.ReportDescriptor | false;
const commaFilter = { filter: (token: AST.Token) => token.value === "," };
const includeCommentsFilter = { includeComments: true };
/**
* Check if an identifier is referenced in JSDoc comments
* Looks for JSDoc tags like @link, @see, @type, etc.
*/
function isUsedInJSDoc(identifierName: string, sourceCode: SourceCode): boolean {
const comments = sourceCode.getAllComments();
// JSDoc tags that can reference identifiers
// Pattern matches: {@link Name}, {@see Name}, @type {Name}, etc.
const jsdocPattern = new RegExp(
// {@link Name} or @see Name
`(?:@(?:link|linkcode|linkplain|see)\\s+${identifierName}\\b)|` +
// {@link Name}
`(?:\\{@(?:link|linkcode|linkplain)\\s+${identifierName}\\b\\})|` +
// @type {Name}, @param {Name}, etc.
`(?:[@{](?:type|typedef|param|returns?|template|augments|extends|implements)\\s+[^}]*\\b${identifierName}\\b)`,
);
return comments.some((comment) => {
// Only check block comments (/* ... */) as JSDoc uses block comment syntax
if (comment.type !== "Block") {
return false;
}
return jsdocPattern.test(comment.value);
});
}
function makePredicate(
isImport: boolean,
addFixer?: (parent: any, sourceCode: SourceCode) => Partial<Rule.ReportDescriptor> | boolean,
): Predicate {
return (problem, context) => {
const sourceCode = context.sourceCode || context.getSourceCode();
const node =
(problem as any).node ??
// typescript-eslint >= 7.8 sets a range instead of a node
sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc((problem as any).loc.start));
const { parent } = node;
// Check if this is an import and if it's used in JSDoc comments
if (parent && /^Import(|Default|Namespace)Specifier$/.test(parent.type) && isImport) {
const identifierName = node.name;
if (identifierName && isUsedInJSDoc(identifierName, sourceCode)) {
// Don't report if used in JSDoc
return false;
}
}
return parent
? /^Import(|Default|Namespace)Specifier$/.test(parent.type) == isImport
? Object.assign(problem, addFixer?.(parent, sourceCode))
: false
: isImport
? false
: problem;
};
}
export const unusedVarsPredicate = makePredicate(false);
export const unusedImportsPredicate = makePredicate(true, (parent, sourceCode) => ({
fix(fixer) {
const grandParent = parent.parent;
if (!grandParent) {
return null;
}
// Only one import
if (grandParent.specifiers.length === 1) {
const nextToken = sourceCode.getTokenAfter(grandParent, includeCommentsFilter);
const newLinesBetween = nextToken
? nextToken.loc!.start.line - grandParent.loc.start.line
: 0;
const endOfReplaceRange = nextToken ? nextToken.range![0] : grandParent.range[1];
const count = Math.max(0, newLinesBetween - 1);
return [
fixer.remove(grandParent),
fixer.replaceTextRange(
[grandParent.range[1], endOfReplaceRange],
"\n".repeat(count),
),
];
}
// Not last specifier
if (parent !== grandParent.specifiers[grandParent.specifiers.length - 1]) {
const comma = sourceCode.getTokenAfter(parent, commaFilter)!;
const prevNode = sourceCode.getTokenBefore(parent)!;
return [
fixer.removeRange([prevNode.range[1], parent.range![0]]),
fixer.remove(parent),
fixer.remove(comma),
];
}
// Default export and a single normal left, ex. "import default, { package1 } from 'module';"
if (
grandParent.specifiers.filter((specifier) => specifier.type === "ImportSpecifier")
.length === 1
) {
const start = sourceCode.getTokenBefore(parent, commaFilter)!;
const end = sourceCode.getTokenAfter(parent, {
filter: (token) => token.value === "}",
})!;
return fixer.removeRange([start.range[0], end.range[1]]);
}
return fixer.removeRange([
sourceCode.getTokenBefore(parent, commaFilter)!.range[0],
parent.range[1],
]);
},
}));
export function createRuleWithPredicate(
name: string,
baseRule: Rule.RuleModule,
predicate: Predicate,
): Rule.RuleModule {
return {
...baseRule,
meta: {
...baseRule.meta,
fixable: "code",
docs: {
...baseRule.meta?.docs,
url: `https://github.com/sweepline/eslint-plugin-unused-imports/blob/master/docs/rules/${name}.md`,
},
},
create(context) {
return baseRule.create(
Object.create(context, {
report: {
enumerable: true,
value(problem: Rule.ReportDescriptor) {
const result = predicate(problem, context);
if (result) {
context.report(result);
}
},
},
}),
);
},
};
}
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"skipLibCheck": true,
"noEmit": true,
}
}
================================================
FILE: tsup.config.ts
================================================
import { defineConfig } from "tsup";
export default defineConfig({
entryPoints: ["src/index.ts"],
format: ["cjs", "esm"],
dts: true,
clean: true,
splitting: true,
shims: true,
cjsInterop: true,
external: ["eslint", "@typescript-eslint/eslint-plugin"],
});
================================================
FILE: vitest.config.ts
================================================
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true,
},
});
gitextract_523dtdv8/ ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ └── bug_report.md │ └── workflows/ │ ├── release.yml │ └── run_test.yml ├── .gitignore ├── .prettierrc.js ├── .vscode/ │ └── launch.json ├── LICENSE ├── README.md ├── docs/ │ └── rules/ │ ├── no-unused-imports.md │ └── no-unused-vars.md ├── package.json ├── pnpm-workspace.yaml ├── src/ │ ├── __test__/ │ │ ├── cases-js.ts │ │ ├── cases-ts.ts │ │ └── no-unused-imports.test.ts │ ├── index.ts │ └── rules/ │ ├── load-rule.ts │ ├── no-unused-imports.ts │ ├── no-unused-vars.ts │ └── predicates.ts ├── tsconfig.json ├── tsup.config.ts └── vitest.config.ts
SYMBOL INDEX (9 symbols across 2 files)
FILE: src/rules/load-rule.ts
function getBaseRule (line 8) | function getBaseRule(): Rule.RuleModule {
function getRuleFromTSLintPlugin (line 15) | function getRuleFromTSLintPlugin() {
function getRuleFromTSLint (line 24) | function getRuleFromTSLint() {
function getESLintBaseRule (line 33) | function getESLintBaseRule() {
FILE: src/rules/predicates.ts
type Predicate (line 3) | type Predicate = (
function isUsedInJSDoc (line 15) | function isUsedInJSDoc(identifierName: string, sourceCode: SourceCode): ...
function makePredicate (line 39) | function makePredicate(
method fix (line 75) | fix(fixer) {
function createRuleWithPredicate (line 132) | function createRuleWithPredicate(
Condensed preview — 23 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (28K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 866,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"\"\nlabels: \"\"\nassignees: \"\"\n---\n\n# Please follow t"
},
{
"path": ".github/workflows/release.yml",
"chars": 217,
"preview": "name: Release\n\non:\n push:\n tags:\n - 'v*'\n\njobs:\n release:\n uses: sxzz/workflows/.github/workflows/release.y"
},
{
"path": ".github/workflows/run_test.yml",
"chars": 869,
"preview": "# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tes"
},
{
"path": ".gitignore",
"chars": 24,
"preview": "node_modules\n.idea\ndist\n"
},
{
"path": ".prettierrc.js",
"chars": 296,
"preview": "module.exports = {\n tabWidth: 4,\n semi: true, // Trailing semicolons\n trailingComma: \"all\",\n singleQuote: fa"
},
{
"path": ".vscode/launch.json",
"chars": 656,
"preview": "{\n // Use IntelliSense to learn about possible attributes.\n // Hover to view descriptions of existing attributes.\n"
},
{
"path": "LICENSE",
"chars": 1079,
"preview": "MIT License\n\nCopyright (c) 2022 Mikkel Holmer Pedersen\n\nPermission is hereby granted, free of charge, to any person obta"
},
{
"path": "README.md",
"chars": 2415,
"preview": "# eslint-plugin-unused-imports\n\nFind and remove unused es6 module imports. It works by splitting up the `no-unused-vars`"
},
{
"path": "docs/rules/no-unused-imports.md",
"chars": 112,
"preview": "# Do not allow unused imports (no-unused-imports)\n\nA rule to find unused-imports only, as well as an autofixer.\n"
},
{
"path": "docs/rules/no-unused-vars.md",
"chars": 224,
"preview": "# Do not allow unused vars (no-unused-vars)\n\nThis is just a helper rule to filter out the things caught by\nthe `no-unuse"
},
{
"path": "package.json",
"chars": 2374,
"preview": "{\n \"name\": \"eslint-plugin-unused-imports\",\n \"version\": \"4.4.1\",\n \"type\": \"commonjs\",\n \"packageManager\": \"pnp"
},
{
"path": "pnpm-workspace.yaml",
"chars": 35,
"preview": "onlyBuiltDependencies:\n - esbuild\n"
},
{
"path": "src/__test__/cases-js.ts",
"chars": 2651,
"preview": "export default {\n valid: [\n {\n code: `\nimport x from \"package\";\nimport { a, b } from \"./utils\";\nimp"
},
{
"path": "src/__test__/cases-ts.ts",
"chars": 1757,
"preview": "export default {\n valid: [\n {\n code: `\nimport x from \"package\";\nimport { a, b } from \"./utils\";\nimp"
},
{
"path": "src/__test__/no-unused-imports.test.ts",
"chars": 2201,
"preview": "import { RuleTester } from \"eslint\";\nimport casesJS from \"./cases-js\";\nimport casesTS from \"./cases-ts\";\nimport { it, de"
},
{
"path": "src/index.ts",
"chars": 452,
"preview": "/**\n * @fileoverview Find and remove unused es6 modules\n * @author Mikkel Holmer Pedersen\n */\nimport noUnusedVars from \""
},
{
"path": "src/rules/load-rule.ts",
"chars": 2200,
"preview": "import { Rule } from \"eslint\";\nimport { createRequire } from \"module\";\n\nlet rule: Rule.RuleModule | undefined;\n\nconst re"
},
{
"path": "src/rules/no-unused-imports.ts",
"chars": 344,
"preview": "/**\n * @fileoverview Add fixer to imports in no-unused-vars.\n * @author Mikkel Holmer Pedersen <mikkel@holmerp.dk>\n */\ni"
},
{
"path": "src/rules/no-unused-vars.ts",
"chars": 331,
"preview": "/**\n * @fileoverview Filter imports from no-unused-vars.\n * @author Mikkel Holmer Pedersen <mikkel@holmerp.dk>\n */\nimpor"
},
{
"path": "src/rules/predicates.ts",
"chars": 5710,
"preview": "import { SourceCode, AST, Rule } from \"eslint\";\n\nexport type Predicate = (\n problem: Rule.ReportDescriptor,\n conte"
},
{
"path": "tsconfig.json",
"chars": 160,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"Bundler\",\n \"skipLib"
},
{
"path": "tsup.config.ts",
"chars": 289,
"preview": "import { defineConfig } from \"tsup\";\n\nexport default defineConfig({\n entryPoints: [\"src/index.ts\"],\n format: [\"cjs"
},
{
"path": "vitest.config.ts",
"chars": 123,
"preview": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n test: {\n globals: true,\n },\n}"
}
]
About this extraction
This page contains the full source code of the sweepline/eslint-plugin-unused-imports GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 23 files (24.8 KB), approximately 6.7k tokens, and a symbol index with 9 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.