From 1bcde1e948d8692d1c09bb9ccc37b9678434b0ef Mon Sep 17 00:00:00 2001 From: lvjiaxuan <11309921+lvjiaxuan@users.noreply.github.com> Date: Mon, 20 Mar 2023 18:30:43 +0800 Subject: [PATCH] feat!: refactor under diagnostic. --- package-lock.json | 44 ++--- package.json | 6 +- src/configuration.ts | 11 -- src/eslint.ts | 90 ---------- src/extension.ts | 389 ++++++++++++++----------------------------- src/global.ts | 3 - src/statusBarItem.ts | 32 ---- src/utils.ts | 16 +- 8 files changed, 155 insertions(+), 436 deletions(-) delete mode 100644 src/configuration.ts delete mode 100644 src/eslint.ts delete mode 100644 src/global.ts delete mode 100644 src/statusBarItem.ts diff --git a/package-lock.json b/package-lock.json index 4996cf0..283dc35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,11 +14,11 @@ }, "devDependencies": { "@lvjiaxuan/eslint-plugin": "^0.10.1", - "@types/eslint": "^8.21.1", - "@types/node": "^18.15.0", + "@types/eslint": "^8.21.3", + "@types/node": "^18.15.3", "@types/vscode": "1.60.0", "eslint": "^8.36.0", - "tsup": "^6.6.3", + "tsup": "^6.7.0", "typescript": "^4.9.5" }, "engines": { @@ -578,9 +578,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.21.1", - "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.21.1.tgz", - "integrity": "sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.3.tgz", + "integrity": "sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -609,9 +609,9 @@ } }, "node_modules/@types/node": { - "version": "18.15.0", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.15.0.tgz", - "integrity": "sha512-z6nr0TTEOBGkzLGmbypWOGnpSpSIBorEhC4L+4HeQ2iezKCi4f77kyslRwvHeNitymGQ+oFyIWGP96l/DPSV9w==", + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", "dev": true }, "node_modules/@types/semver": { @@ -2698,9 +2698,9 @@ "dev": true }, "node_modules/tsup": { - "version": "6.6.3", - "resolved": "https://registry.npmmirror.com/tsup/-/tsup-6.6.3.tgz", - "integrity": "sha512-OLx/jFllYlVeZQ7sCHBuRVEQBBa1tFbouoc/gbYakyipjVQdWy/iQOvmExUA/ewap9iQ7tbJf9pW0PgcEFfJcQ==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.7.0.tgz", + "integrity": "sha512-L3o8hGkaHnu5TdJns+mCqFsDBo83bJ44rlK7e6VdanIvpea4ArPcU3swWGsLVbXak1PqQx/V+SSmFPujBK+zEQ==", "dev": true, "dependencies": { "bundle-require": "^4.0.0", @@ -2728,7 +2728,7 @@ "peerDependencies": { "@swc/core": "^1", "postcss": "^8.4.12", - "typescript": "^4.1.0" + "typescript": ">=4.1.0" }, "peerDependenciesMeta": { "@swc/core": { @@ -3339,9 +3339,9 @@ } }, "@types/eslint": { - "version": "8.21.1", - "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.21.1.tgz", - "integrity": "sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.3.tgz", + "integrity": "sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==", "dev": true, "requires": { "@types/estree": "*", @@ -3370,9 +3370,9 @@ } }, "@types/node": { - "version": "18.15.0", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.15.0.tgz", - "integrity": "sha512-z6nr0TTEOBGkzLGmbypWOGnpSpSIBorEhC4L+4HeQ2iezKCi4f77kyslRwvHeNitymGQ+oFyIWGP96l/DPSV9w==", + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", "dev": true }, "@types/semver": { @@ -4969,9 +4969,9 @@ "dev": true }, "tsup": { - "version": "6.6.3", - "resolved": "https://registry.npmmirror.com/tsup/-/tsup-6.6.3.tgz", - "integrity": "sha512-OLx/jFllYlVeZQ7sCHBuRVEQBBa1tFbouoc/gbYakyipjVQdWy/iQOvmExUA/ewap9iQ7tbJf9pW0PgcEFfJcQ==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.7.0.tgz", + "integrity": "sha512-L3o8hGkaHnu5TdJns+mCqFsDBo83bJ44rlK7e6VdanIvpea4ArPcU3swWGsLVbXak1PqQx/V+SSmFPujBK+zEQ==", "dev": true, "requires": { "bundle-require": "^4.0.0", diff --git a/package.json b/package.json index c9e6a10..69977ca 100644 --- a/package.json +++ b/package.json @@ -101,11 +101,11 @@ }, "devDependencies": { "@lvjiaxuan/eslint-plugin": "^0.10.1", - "@types/eslint": "^8.21.1", - "@types/node": "^18.15.0", + "@types/eslint": "^8.21.3", + "@types/node": "^18.15.3", "@types/vscode": "1.60.0", "eslint": "^8.36.0", - "tsup": "^6.6.3", + "tsup": "^6.7.0", "typescript": "^4.9.5" } } diff --git a/src/configuration.ts b/src/configuration.ts deleted file mode 100644 index 2b0e916..0000000 --- a/src/configuration.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { workspace } from 'vscode' - -const config = workspace.getConfiguration('eslint-disable') - -const orgConfig = workspace.getConfiguration('eslint') - -export default { - disable: config.get('disable', false), - preLinting: config.get('preLinting', true), - useFlatConfig: orgConfig.get('experimental.useFlatConfig', false), -} diff --git a/src/eslint.ts b/src/eslint.ts deleted file mode 100644 index d2456d9..0000000 --- a/src/eslint.ts +++ /dev/null @@ -1,90 +0,0 @@ -import log from './log' -import { Files } from 'vscode-languageserver/node' -import { LanguageClient } from 'vscode-languageclient/node' -import { workspacePath } from './global' -import { exec } from 'node:child_process' -import { ESLint, Linter } from 'eslint' -import path from 'node:path' -import { type ExtensionContext } from 'vscode' -import { existFile } from './utils' -import config from './configuration' - -const useFlatConfig = config.useFlatConfig - -type PKG_MANAGERS = { agent: 'pnpm' | 'npm' | 'yarn', path: string } -const resolveESLintPath = () => Files.resolve(`eslint${ useFlatConfig ? '/use-at-your-own-risk' : '' }`, workspacePath, workspacePath, message => { /**/ }) - .catch(() => { - log('Fail to resolve local ESLint. Trying globally...') - return Promise.allSettled( - [ 'pnpm root -g', 'npm root -g', 'yarn global dir' ].map(item => - new Promise((resolve, reject) => - exec(item, (error, stdout) => { - if (error) { - reject(error) - return - } - resolve({ - agent: item.split(' ')[0] as PKG_MANAGERS['agent'], - path: stdout.toString().trim(), - }) - }))), - ) - }).then(result => { - - if (typeof result === 'string') { - return result - } - - const agent = result.filter(({ status }) => status === 'fulfilled')[0] as PromiseFulfilledResult - return Files.resolve('eslint', agent.value.path, workspacePath, message => { /**/ }) - }).catch(() => { - log('Fail to resolve global ESLint. Please install ESLint first.') - // eslint-disable-next-line promise/no-return-wrap - return Promise.reject('Fail to resolve global ESLint. Please install ESLint first.') - }) - -export const getESLintInstance = async (context: ExtensionContext) => { - const stateKey = useFlatConfig ? 'flatESLintPath' : 'eslintPath' - let eslintPath = context.workspaceState.get(stateKey) - if (eslintPath && await existFile(eslintPath)) { - log(`${ useFlatConfig ? 'Flat ' : '' }ESLint path found from storage`) - } else { - eslintPath = await resolveESLintPath() - void context.workspaceState.update(stateKey, eslintPath) - } - - const eslintModule = await import(path.join(eslintPath)) as { - ESLint: typeof ESLint - FlatESLint: typeof ESLint - } - - log(`${ useFlatConfig ? 'Flat ' : '' }ESLint library loaded from: ${ eslintPath }`) - return useFlatConfig - ? new eslintModule.FlatESLint({ - cwd: workspacePath, - overrideConfig: { - // @ts-ignore - files: [ '**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts' ], - languageOptions: { parserOptions: { tsconfigRootDir: workspacePath } }, - }, - }) - : new eslintModule.ESLint({ - cwd: workspacePath, - overrideConfig: { - overrides: [ - { - files: [ '*.ts', '*.d.ts', '*.tsx', '*.vue' ], - parserOptions: { tsconfigRootDir: workspacePath }, - }, - ], - }, - }) -} - -export const getESLintLinterInstance = async () => { - const eslintPath = await resolveESLintPath() - const eslintModule = await import(path.join(eslintPath)) as { Linter: typeof Linter } - - log(`ESLint library loaded from: ${ eslintPath }`) - return new eslintModule.Linter() -} diff --git a/src/extension.ts b/src/extension.ts index 1f25c90..1d45fd3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,307 +1,166 @@ -import { type ExtensionContext, Position, Range, type Selection, SnippetString, type TextEditor, commands, window, workspace } from 'vscode' -import type { ESLint } from 'eslint' -import { existFile, getTextBylines } from './utils' -import { workspacePath } from './global' -import { getESLintInstance } from './eslint' -import statusBarItem, { showStatusBarItem } from './statusBarItem' +import { ExtensionContext, Position, Range, Selection, SnippetString, commands, languages, window } from 'vscode' +import { existFileSync, getTextBylines } from './utils' import log from './log' -import config from './configuration' import path from 'node:path' -let eslint: ESLint +export function activate(context: ExtensionContext) { -type FileName = string -type LineNumber = number -type LineRules = Set -const lintingCache = new Map>() + context.subscriptions.push(disableForLines) + context.subscriptions.push(disableForEntire) +} + +export function deactivate() { + disableForLines.dispose() + disableForEntire.dispose() +} -let reLintingTimer: ReturnType +const disableForLines = commands.registerCommand('eslint-disable.disable', () => { + const result = getESLintDiagnostics() + if (!result) { + return + } -let extensionContext: ExtensionContext + const { text, selection, activeTextEditor, eslintDiagnostics } = result -export async function activate(context: ExtensionContext) { - const _startTime = Date.now() - log('eslint-disable is activating!') + let insertIndex = 0 + while (text.charAt(insertIndex) == ' ') { + insertIndex++ + } - extensionContext = context + const insertRules = eslintDiagnostics.reduce((insertRules, item) => { + const isRuleInLine = selection.isSingleLine + ? item.range.start.line === selection.start.line + : selection.start.line + 1 <= item.range.start.line && item.range.start.line <= selection.end.line + 1 - if (config.disable) { - log('eslint-disable is disable.') - return + if (isRuleInLine) { + // @ts-ignore + insertRules.add(item.code.value as string) + } + return insertRules + }, new Set()) + + if (selection.isSingleLine) { + // Insert at previous line. + void activeTextEditor.insertSnippet( + new SnippetString(`// eslint-disable-next-line \${1:${ [ ...insertRules ].join(', ') }}\n`), + new Position(selection.start.line, insertIndex), + ) + } else { + // Wrap lines and Press `ctrl+d` to edit rules between lines. + + void (async () => { + await activeTextEditor.insertSnippet( + new SnippetString(`${ ' '.repeat(insertIndex) }/* eslint-enable ${ [ ...insertRules ].join(', ') } */\n`), + new Position(selection.end.line + 1, 0), + ) + await activeTextEditor.insertSnippet( + new SnippetString(`/* eslint-disable \${1:${ [ ...insertRules ].join(', ') }} */\n`), + new Position(selection.start.line, insertIndex), + ) + })() } +}) - if (!workspacePath) { - log('No `workspacePath` found.') +const disableForEntire = commands.registerCommand('eslint-disable.entire', async () => { + const result = getESLintDiagnostics() + if (!result) { return } - eslint = await getESLintInstance(context) + const { text, selection, activeTextEditor, eslintDiagnostics } = result - context.subscriptions.push(...disposes, statusBarItem.value) + // @ts-ignore + let insertRules: Set = eslintDiagnostics.reduce((insertRules, item) => { - log(`eslint-disable is activated!(${ Date.now() - _startTime }ms)!`) - showStatusBarItem(`$(check) eslint-disable is activated!(${ Date.now() - _startTime }ms)!`) - - enablePreLinting(config.preLinting) -} - -// this method is called when your extension is deactivated -export function deactivate() { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - disposes.forEach(fn => fn.dispose()) - statusBarItem.value.dispose() -} + const isRuleInLine = selection.isSingleLine + ? item.range.start.line === selection.start.line + : selection.start.line + 1 <= item.range.start.line && item.range.start.line <= selection.end.line + 1 -const disposes = [ + if (isRuleInLine) { + // @ts-ignore + insertRules.add(item.code.value as string) + } + return insertRules + }, new Set()) - // Disable for lines - commands.registerCommand('eslint-disable.disable', (silent = false) => { - // keep - void disable(silent as boolean, ({ text, activeTextEditor, selection, lineRulesMap }) => { - let insertIndex = 0 - while (text.charAt(insertIndex) == ' ') { - insertIndex++ - } + // TODO Maybe not 0 line. + const startLineText = getTextBylines(0) + const startLineTextMatch = startLineText?.match(/\/\* eslint-disable (?.+) \*\//i) - if (selection.isSingleLine) { - // Insert at previous line. - void activeTextEditor.insertSnippet( - new SnippetString(`// eslint-disable-next-line ${ [ ...lineRulesMap.get(selection.start.line + 1)!.values() ].join('\\, ') }\n`), - new Position(selection.start.line, insertIndex), - ) - lineRulesMap.delete(selection.start.line + 1) - } else { - // Wrap lines and Press `ctrl+d` to edit rules between lines. + if (startLineTextMatch) { + const currentRules = startLineTextMatch?.groups!.rules.replaceAll(' ', '').split(',') ?? [] + currentRules.forEach(item => insertRules.add(item)) - const rules = new Set() - lineRulesMap.forEach((value, key) => { - if (selection.start.line + 1 <= +key && +key <= selection.end.line + 1) { - value.forEach(item => rules.add(item)) - lineRulesMap.delete(+key) - } - }) + // Delete exist comments. + await activeTextEditor.edit(editor => { - void (async () => { - await activeTextEditor.insertSnippet( - new SnippetString(`${ ' '.repeat(insertIndex) }/* eslint-enable ${ [ ...rules.values() ].join('\\, ') } */\n`), - new Position(selection.end.line + 1, 0), - ) - await activeTextEditor.insertSnippet( - new SnippetString(`/* eslint-disable ${ [ ...rules.values() ].join('\\, ') } */\n`), - new Position(selection.start.line, insertIndex), - ) - })() - } - }) - }), + editor.delete(new Range( + new Position(0, 0), + new Position(0, Number.MAX_SAFE_INTEGER), + )) - // Disable for entire - commands.registerCommand('eslint-disable.entire', () => { - // keep - void disable(false, async ({ selection, activeTextEditor, lineRulesMap }) => { - const startLineText = getTextBylines(0) const endLineText = getTextBylines(activeTextEditor.document.lineCount - 2) - const match = startLineText?.match(/\/\* eslint-disable (?.+) \*\//i) - - let foundRules: LineRules - if (selection.isSingleLine) { - foundRules = lineRulesMap.get(selection.start.line + 1)! - lineRulesMap.delete(selection.start.line + 1) - } else { - foundRules = new Set() - lineRulesMap.forEach((value, key) => { - if (selection.start.line + 1 <= +key && +key <= selection.end.line + 1) { - value.forEach(item => foundRules.add(item)) - lineRulesMap.delete(+key) - } - }) - } - - if (match) { - const entireRules = match?.groups!.rules.replaceAll(' ', '').split(',') ?? [] - const rules = [ ...new Set([ ...foundRules, ...entireRules ]) ] - - // Delete exist comments. - await activeTextEditor.edit(editor => { - editor.delete(new Range( - new Position(0, 0), - new Position(0, Number.MAX_SAFE_INTEGER), - )) - - if (endLineText?.startsWith('/* eslint-enable')) { - editor.delete(new Range( - new Position(activeTextEditor.document.lineCount - 2, 0), - new Position(activeTextEditor.document.lineCount - 2, Number.MAX_SAFE_INTEGER), - )) - } - }) - - await activeTextEditor.insertSnippet( - new SnippetString(`/* eslint-enable ${ rules.join(', ') } */`), + if (endLineText?.startsWith('/* eslint-enable')) { + editor.delete(new Range( new Position(activeTextEditor.document.lineCount - 2, 0), - ) - await activeTextEditor.insertSnippet( - new SnippetString(`/* eslint-disable ${ rules.join(', ') } */`), - new Position(0, 0), - ) - - } else { - await activeTextEditor.insertSnippet( - new SnippetString(`/* eslint-enable ${ [ ...foundRules.values() ].toString() } */\n`), - new Position(activeTextEditor.document.lineCount + 1, 0), - ) - await activeTextEditor.insertSnippet( - new SnippetString(`/* eslint-disable ${ [ ...foundRules.values() ].toString() } */\n`), - new Position(0, 0), - ) + new Position(activeTextEditor.document.lineCount - 2, Number.MAX_SAFE_INTEGER), + )) } }) - }), - - // Reload - commands.registerCommand('eslint-disable.reload', async () => { - log('Reloading eslint-disable.') - showStatusBarItem('$(loading~spin) Reloading eslint-disable.', 0) - // 1. Clear storage - const storage = extensionContext.workspaceState - storage.keys().forEach(key => storage.update(key, null)) - // 2. Re-get ESLint - eslint = await getESLintInstance(extensionContext) - // 3. - lintingCache.clear() - log('Reloading finished.') - showStatusBarItem('$(check) Reloading finished.') - }), -] - -const filesBusy = new Map() -async function disable(silent: boolean, insert: (opts: { - text: string, - activeTextEditor: TextEditor, - selection: Selection, - lineRulesMap: NonNullable> -}) => void) { - clearTimeout(reLintingTimer) - - const activeTextEditor = window.activeTextEditor! - - const fileName = activeTextEditor.document.fileName - const basename = path.basename(fileName) - if (!await existFile(fileName)) { - return false + await activeTextEditor.insertSnippet( + new SnippetString(`/* eslint-enable ${ [ ...insertRules ].join(', ') } */`), + new Position(activeTextEditor.document.lineCount - 2, 0), + ) + await activeTextEditor.insertSnippet( + new SnippetString(`/* eslint-disable ${ [ ...insertRules ].join(', ') } */`), + new Position(0, 0), + ) + } else { + await activeTextEditor.insertSnippet( + new SnippetString(`/* eslint-enable ${ [ ...insertRules ].join(', ') } */\n`), + new Position(activeTextEditor.document.lineCount + 1, 0), + ) + await activeTextEditor.insertSnippet( + new SnippetString(`/* eslint-disable ${ [ ...insertRules ].join(', ') } */\n`), + new Position(0, 0), + ) } +}) - if (await eslint.isPathIgnored(fileName)) { - return false - } +function getESLintDiagnostics() { + const { activeTextEditor } = window - if (activeTextEditor.selections.length > 1) { - log('Sorry, we can not disable multi-selections for now. It will be supported in later version.', true, 'OK') - return false + if (!activeTextEditor) { + log('No activeTextEditor found, please try again.', true, 'OK') + return } - if (filesBusy.get(fileName)) { - // Command would not await last command task, which executes in parallel. - return false + const { fileName } = activeTextEditor.document + if (!existFileSync(fileName)) { + log(`Not a exist file: ${ fileName }`) + return } - filesBusy.set(fileName, true) - - log('') - log('πŸ‘‡πŸ‘‡πŸ‘‡πŸ‘‡πŸ‘‡πŸ‘‡') - log(`eslint-disable services ${ fileName }`) - - await activeTextEditor.document.save() - - let lineRulesMap = lintingCache.get(fileName) - if (!lineRulesMap) { - - log(`${ basename } - Linting ${ basename }...`) - showStatusBarItem(`$(loading~spin) Linting ${ basename }...`, 0) - // FIXME: A workaround. - await new Promise(resolve => setTimeout(() => setTimeout(resolve))) - const _startTime = Date.now() - const results = await eslint.lintFiles(activeTextEditor.document.uri.fsPath) // By debugging, it is a sync task,which makes `statusBarItem.show` cloud not render immediately. + const uri = activeTextEditor.document.uri.toString() - log(`${ basename } - Linting finish(${ Date.now() - _startTime }ms).`) - showStatusBarItem(`$(check) Linting finish(${ Date.now() - _startTime }ms).`) + // activeTextEditor.selections would supported in later version. + const { selection } = activeTextEditor + const basename = path.basename(uri) - // eslint-disable-next-line require-atomic-updates - lineRulesMap = results?.[0].messages.reduce((preValue, item) => { - if (!item.ruleId) return preValue - - if (!preValue.has(item.line)) { - preValue.set(item.line, new Set([ item.ruleId ])) - } else { - preValue.set(item.line, preValue.get(item.line)!.add(item.ruleId)) - } - return preValue - }, new Map()) - - lintingCache.set(fileName, lineRulesMap) - log(`${ basename } - Set linting cache.`) - } else { - log(`${ basename } - Linting cache found.`) - showStatusBarItem(`Linting cache found for ${ path.parse(fileName).base }.`) + const text = getTextBylines(selection.start.line, selection.end.line) + if (!text?.replace(/\n|\r/g, '')) { + log(`${ basename } - No content to disable.`, true, 'OK') + return } - filesBusy.set(fileName, false) - if (lineRulesMap && [ ...lineRulesMap.values() ].every(item => !item.size)) { - log(`${ basename } - Everything is good.`, !silent, 'OK') + const diagnostics = languages.getDiagnostics() + const diagnosticOfUri = diagnostics.find(item => item[0].toString() === uri) + const eslintDiagnostics = diagnosticOfUri?.[1].filter(item => item.source === 'eslint') ?? [] + if (!eslintDiagnostics.length) { + log(`${ basename } - No problem found on your selection.`, true, 'OK') return - } else { - const allRules: string[] = [] - lineRulesMap.forEach((value, key) => allRules.push(`${ key }-${ [ ...value.values() ].toString() }`)) - log(`${ basename } - Problems found: ${ allRules.toString() } `) } - !silent && activeTextEditor.selections.forEach(selection => { - - const text = getTextBylines(selection.start.line, selection.end.line) - if (!text?.replace(/\n|\r/g, '')) { - log(`${ basename } - No content to disable.`, true, 'OK') - return - } - - - if (![ ...lineRulesMap!.keys() ].some(problemLine => - selection.start.line + 1 <= +problemLine && +problemLine <= selection.end.line + 1)) { - log(`${ basename } - No problem found on your selection.`, true, 'OK') - return - } - - insert({ text, activeTextEditor, selection, lineRulesMap: lineRulesMap! }) - }) - - return { activeTextEditor, basename, lineRulesMap } -} - -function enablePreLinting(preLinting: boolean) { - log(`Pre-Linting is ${ preLinting ? 'enable' : 'disable' }.`) - if (preLinting) { - window.activeTextEditor && void commands.executeCommand('eslint-disable.disable', true) - window.onDidChangeActiveTextEditor(() => window.activeTextEditor && commands.executeCommand('eslint-disable.disable', true)) - workspace.onDidChangeTextDocument(async event => { - const fileName = event.document.fileName - - if (!await existFile(event.document.fileName) || !event.contentChanges.length) { - return - } - - /** - * It seems that inserting `// eslint-disable` is no need to clear cache. - * But in actually, the line numbers in cache would be changed. - * Maybe I should re-compute these line numbers in later. - */ - if (lintingCache.has(fileName)) { - lintingCache.delete(fileName) - log(`${ path.basename(fileName) } - Clear linting cache. Re-Linting after 5s.`) - clearTimeout(reLintingTimer) - reLintingTimer = setTimeout(() => void commands.executeCommand('eslint-disable.disable', true), 5 * 1000) - } - }) - // @ts-ignore - // enablePreLinting.enabled = true - } + return { text, selection, activeTextEditor, eslintDiagnostics } } diff --git a/src/global.ts b/src/global.ts deleted file mode 100644 index 07e98d1..0000000 --- a/src/global.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { workspace } from 'vscode' - -export const workspacePath = workspace.workspaceFolders?.[0].uri.fsPath diff --git a/src/statusBarItem.ts b/src/statusBarItem.ts deleted file mode 100644 index 4c48bd7..0000000 --- a/src/statusBarItem.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { StatusBarAlignment, type StatusBarItem, window } from 'vscode' - -let statusBarItem: StatusBarItem - -const aop = () => { - if (!statusBarItem) { - statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left) - } -} - -export default { - get value () { - aop() - return statusBarItem - }, -} - -export const showStatusBarItem = (text: string, time = 5000) => { - try { - statusBarItem.text = text - statusBarItem.show() - time > 0 && hideStatusBarItem(time) - } catch {} -} - -let hideTimer: ReturnType -export const hideStatusBarItem = (delay = 5000) => { - try { - clearTimeout(hideTimer) - hideTimer = setTimeout(() => statusBarItem.hide(), delay) - } catch {} -} diff --git a/src/utils.ts b/src/utils.ts index c026775..84f06d2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -9,14 +9,10 @@ export const getTextBylines = (startLine: number, endLine?: number) => ), ) -export function existFile(file: string): Promise { - return new Promise((resolve, _reject) => { - // console.log(file) - fs.stat(file, (error, stats) => { - if (error !== null) { - resolve(false) - } - resolve(stats?.isFile() ?? false) - }) - }) +export function existFileSync(path: string) { + try { + fs.statSync(path) + return true + } catch {} + return false }