diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..ac1ff44 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,86 @@ +/** + * @file ESLint configuration based on Airbnb's with some modifications. + */ + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { join } = require('path'); + +const MAX_LINE_LENGTH = 120; + +module.exports = { + root: true, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'airbnb-base', + 'airbnb-typescript/base', + 'plugin:jsdoc/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + tsconfigRootDir: join(__dirname), + project: 'tsconfig.eslint.json', + }, + plugins: ['import', '@typescript-eslint', 'import-newlines'], + rules: { + 'max-len': [ + 'error', + { + code: MAX_LINE_LENGTH, + comments: MAX_LINE_LENGTH, + tabWidth: 4, + ignoreUrls: true, + ignoreTrailingComments: false, + ignoreComments: false, + }, + ], + '@typescript-eslint/indent': [ + 'error', + 4, + { + SwitchCase: 1, + }, + ], + 'jsdoc/multiline-blocks': ['error', { noSingleLineBlocks: true }], + 'import/prefer-default-export': 'off', + 'import-newlines/enforce': ['error', { items: 3, 'max-len': MAX_LINE_LENGTH }], + // Split external and internal imports with an empty line + 'import/order': [ + 'error', + { + groups: [ + ['builtin', 'external'], + ], + 'newlines-between': 'always', + }, + ], + // We can disable this, because we bundle everything + 'import/no-extraneous-dependencies': 'off', + 'no-restricted-syntax': ['error', 'LabeledStatement', 'WithStatement'], + 'no-continue': 'off', + 'jsdoc/require-param-type': 'off', + 'jsdoc/require-returns-type': 'off', + 'jsdoc/tag-lines': [ + 'warn', + 'any', + { + startLines: 1, + }, + ], + 'arrow-body-style': 'off', + 'no-await-in-loop': 'off', + // Force proper import and export of types + '@typescript-eslint/consistent-type-imports': [ + 'error', + { + fixStyle: 'inline-type-imports', + }, + ], + '@typescript-eslint/consistent-type-exports': [ + 'error', + { + fixMixedExportsWithInlineTypeSpecifier: true, + }, + ], + }, +}; diff --git a/.eslintrc.yaml b/.eslintrc.yaml deleted file mode 100644 index d7d949d..0000000 --- a/.eslintrc.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# ESLint configuration file for TypeScript based on Airbnb's style guide -# See https://github.com/AdguardTeam/CodeGuidelines/blob/master/JavaScript/Javascript.md -root: true -extends: - - eslint:recommended - - "plugin:@typescript-eslint/recommended" - - airbnb-base - - airbnb-typescript/base - - plugin:jsdoc/recommended -parser: "@typescript-eslint/parser" -parserOptions: - project: tsconfig.eslint.json -plugins: - - import - - "@typescript-eslint" -rules: - max-len: - - error - - code: 120 - comments: 120 - tabWidth: 4 - ignoreUrls: false - ignoreTrailingComments: false - ignoreComments: false - "@typescript-eslint/indent": - - error - - 4 - - SwitchCase: 1 - import/prefer-default-export: off - no-restricted-syntax: - - error - - LabeledStatement - - WithStatement - no-continue: off - jsdoc/require-param-type: off - jsdoc/require-returns-type: off - arrow-body-style: off - no-await-in-loop: off - import/no-extraneous-dependencies: off diff --git a/client/src/extension.ts b/client/src/extension.ts index cc2b55f..83e3161 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -1,9 +1,18 @@ import { join } from 'path'; import { - ThemeColor, commands, StatusBarAlignment, workspace, ExtensionContext, window, StatusBarItem, + ThemeColor, + commands, + StatusBarAlignment, + workspace, + type ExtensionContext, + window, + type StatusBarItem, } from 'vscode'; import { - LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, + LanguageClient, + type LanguageClientOptions, + type ServerOptions, + TransportKind, } from 'vscode-languageclient/node'; const SERVER_PATH = join('server', 'out', 'server.js'); diff --git a/package.json b/package.json index 13ab836..4a23310 100644 --- a/package.json +++ b/package.json @@ -117,6 +117,7 @@ "eslint": "^8.33.0", "eslint-config-airbnb-typescript": "^17.0.0", "eslint-plugin-import": "^2.27.5", + "eslint-plugin-import-newlines": "^1.3.4", "eslint-plugin-jsdoc": "^39.7.5", "fs-extra": "^11.1.1", "husky": "^8.0.3", diff --git a/server/src/server.ts b/server/src/server.ts index 89052fc..1b224f6 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -5,25 +5,26 @@ import { createConnection, TextDocuments, - Diagnostic, + type Diagnostic, DiagnosticSeverity, ProposedFeatures, - InitializeParams, + type InitializeParams, DidChangeConfigurationNotification, - InitializeResult, + type InitializeResult, } from 'vscode-languageserver/node'; import { TextDocument } from 'vscode-languageserver-textdocument'; -import { ParsedPath, join as joinPath } from 'path'; +import { type ParsedPath, join as joinPath } from 'path'; import { fileURLToPath, pathToFileURL } from 'url'; // TODO: Implement minimum version check // import { satisfies } from 'semver'; // Import type definitions from the AGLint package import type * as AGLint from '@adguard/aglint'; import cloneDeep from 'clone-deep'; + import { resolveAglintModulePath } from './utils/aglint-resolver'; import { AGLINT_PACKAGE_NAME, AGLINT_REPO_URL, LF } from './common/constants'; -import { defaultSettings, ExtensionSettings } from './settings'; -import { NPM, PackageManager, getInstallationCommand } from './utils/package-managers'; +import { defaultSettings, type ExtensionSettings } from './settings'; +import { NPM, type PackageManager, getInstallationCommand } from './utils/package-managers'; // Store AGLint module here let AGLintModule: typeof AGLint; diff --git a/server/src/settings.ts b/server/src/settings.ts index e70d84a..abb2a1f 100644 --- a/server/src/settings.ts +++ b/server/src/settings.ts @@ -10,7 +10,7 @@ * 2. Implement the logic in the server.ts file */ -import { NPM, PackageManager } from './utils/package-managers'; +import { NPM, type PackageManager } from './utils/package-managers'; /** * Represents the extension settings diff --git a/server/src/utils/aglint-resolver.ts b/server/src/utils/aglint-resolver.ts index 86f6509..3fc3924 100644 --- a/server/src/utils/aglint-resolver.ts +++ b/server/src/utils/aglint-resolver.ts @@ -3,11 +3,12 @@ */ import { Files } from 'vscode-languageserver/node'; + import { NPM, PNPM, - PackageManager, - TraceFunction, + type PackageManager, + type TraceFunction, YARN, findGlobalPathForPackageManager, } from './package-managers'; diff --git a/server/src/utils/package-managers.ts b/server/src/utils/package-managers.ts index 0bd7f67..b65d8c7 100644 --- a/server/src/utils/package-managers.ts +++ b/server/src/utils/package-managers.ts @@ -5,6 +5,7 @@ import { execSync } from 'child_process'; import { isAbsolute } from 'path'; import { Files } from 'vscode-languageserver/node'; + import { EMPTY } from '../common/constants'; /** diff --git a/test/grammar/comments/agent.test.ts b/test/grammar/comments/agent.test.ts index e9d9ac4..d6f00d3 100644 --- a/test/grammar/comments/agent.test.ts +++ b/test/grammar/comments/agent.test.ts @@ -2,7 +2,7 @@ * @file Tests for the adblock agents */ -import { AdblockTokenizer, getAdblockTokenizer } from '../common/get-adblock-tokenizer'; +import { type AdblockTokenizer, getAdblockTokenizer } from '../common/get-adblock-tokenizer'; import { expectTokens } from '../common/token-expectation'; let tokenize: AdblockTokenizer; diff --git a/test/grammar/common/adblock-grammar-loader.ts b/test/grammar/common/adblock-grammar-loader.ts index f8fb0ba..4644301 100644 --- a/test/grammar/common/adblock-grammar-loader.ts +++ b/test/grammar/common/adblock-grammar-loader.ts @@ -4,20 +4,29 @@ import { readFile } from 'fs/promises'; import { join } from 'path'; -import { IGrammar, Registry, parseRawGrammar } from 'vscode-textmate'; +import { type IGrammar, Registry, parseRawGrammar } from 'vscode-textmate'; import { loadWASM, OnigScanner, OnigString } from 'vscode-oniguruma'; + import { convertYamlToPlist } from '../../../tools/grammar-converter'; -/** Source file path for the grammar */ +/** + * Source file path for the grammar + */ const ADBLOCK_GRAMMAR_PATH = join(__dirname, '../../../', 'syntaxes/adblock.yaml-tmlanguage'); -/** Scope name for the adblock grammar */ +/** + * Scope name for the adblock grammar + */ const ADBLOCK_GRAMMAR_SCOPE = 'text.adblock'; -/** Scope name for the JavaScript grammar */ +/** + * Scope name for the JavaScript grammar + */ const JS_GRAMMAR_SCOPE = 'source.js'; -/** Dummy grammar for JavaScript (raw) */ +/** + * Dummy grammar for JavaScript (raw) + */ const DUMMY_JS_GRAMMAR = `{ "name": "JavaScript", "scopeName": "source.js", @@ -25,7 +34,9 @@ const DUMMY_JS_GRAMMAR = `{ "repository": {} }`; -/** Fake file name for the dummy JavaScript grammar */ +/** + * Fake file name for the dummy JavaScript grammar + */ const DUMMY_JS_GRAMMAR_FILE_NAME = 'dummy-js-grammar.json'; /** diff --git a/test/grammar/common/get-adblock-tokenizer.ts b/test/grammar/common/get-adblock-tokenizer.ts index d6f1201..7d50f8c 100644 --- a/test/grammar/common/get-adblock-tokenizer.ts +++ b/test/grammar/common/get-adblock-tokenizer.ts @@ -2,7 +2,8 @@ * @file Gets the adblock tokenizer function from the loaded grammar */ -import { IToken, INITIAL } from 'vscode-textmate'; +import { type IToken, INITIAL } from 'vscode-textmate'; + import { loadAdblockGrammar } from './adblock-grammar-loader'; /** diff --git a/test/grammar/common/token-expectation.ts b/test/grammar/common/token-expectation.ts index e9fa4df..b27cb57 100644 --- a/test/grammar/common/token-expectation.ts +++ b/test/grammar/common/token-expectation.ts @@ -1,4 +1,4 @@ -import { AdblockTokenizer } from './get-adblock-tokenizer'; +import { type AdblockTokenizer } from './get-adblock-tokenizer'; import { isArraysEqual } from './utils'; /** diff --git a/test/grammar/cosmetic/js-inject.test.ts b/test/grammar/cosmetic/js-inject.test.ts index 96277a4..a11e1cd 100644 --- a/test/grammar/cosmetic/js-inject.test.ts +++ b/test/grammar/cosmetic/js-inject.test.ts @@ -2,7 +2,7 @@ * @file Tests for JS injection rules */ -import { AdblockTokenizer, getAdblockTokenizer } from '../common/get-adblock-tokenizer'; +import { type AdblockTokenizer, getAdblockTokenizer } from '../common/get-adblock-tokenizer'; import { expectTokens } from '../common/token-expectation'; let tokenize: AdblockTokenizer; diff --git a/tools/grammar-builder.ts b/tools/grammar-builder.ts index a7d9bfd..611bc0f 100644 --- a/tools/grammar-builder.ts +++ b/tools/grammar-builder.ts @@ -3,18 +3,28 @@ */ import { - exists, mkdir, readFile, writeFile, + exists, + mkdir, + readFile, + writeFile, } from 'fs-extra'; import { join } from 'path'; + import { convertYamlToPlist } from './grammar-converter'; -/** Path to the source grammar file */ +/** + * Path to the source grammar file + */ const SOURCE_GRAMMAR_FILE = 'syntaxes/adblock.yaml-tmlanguage'; -/** Path to the out folder */ +/** + * Path to the out folder + */ const OUT_FOLDER = 'syntaxes/out'; -/** Path to the builded grammar file */ +/** + * Path to the builded grammar file + */ const DEST_GRAMMAR_FILE = join(OUT_FOLDER, 'adblock.plist'); /** diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index aad8167..e34c6e0 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -1,6 +1,7 @@ { "extends": "./tsconfig.json", "include": [ + ".eslintrc.cjs", "client/**/*.ts", "jest.config.ts", "server/**/*.ts", diff --git a/yarn.lock b/yarn.lock index f105051..fae3d43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1763,6 +1763,11 @@ eslint-module-utils@^2.7.4: dependencies: debug "^3.2.7" +eslint-plugin-import-newlines@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-import-newlines/-/eslint-plugin-import-newlines-1.3.4.tgz#c3917ae478b1dcce2a920637eaa8af001b8e1477" + integrity sha512-Lmf/BbK+EQKUfjKPcZpslE/KTGYlgaI8ZJ/sYzdbb3BVTg5+GmLBLHBjsUKNEVRM1SEhDTF/didtOSYKi4tSnQ== + eslint-plugin-import@^2.27.5: version "2.27.5" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65"