Skip to content

Commit 994ebc7

Browse files
committed
AG-47932 Integrate AGLint v4
Squashed commit of the following: commit 82e3164 Author: scripthunter7 <d.tota@adguard.com> Date: Mon Dec 1 14:16:13 2025 +0100 Standardize log message prefixes to use [lsp] and [aglint] tags - Add [lsp] prefix to all language server log messages for consistent identification - Change AGLint debugger prefix from [AGLint debugger] to [aglint] for consistency - Apply prefixes across initialization, linting, configuration, and error messages - Update tracer.log calls to include [lsp] prefix for module resolution messages commit 2074339 Author: scripthunter7 <d.tota@adguard.com> Date: Mon Dec 1 14:09:52 2025 +0100 Improve AGLint package detection and loading reliability - Add node_modules and package.json to file watchers with node_modules exclusion patterns - Implement retry mechanism for AGLint loading when package.json or node_modules changes - Add aglintLoadingFailed and aglintLoading flags to prevent repeated failed attempts - Add debounced retryAglintLoading function (2s delay) to wait for npm install to complete - Implement tryResolveAglintPackage() using resolve package for better module resolution - Add resolve commit 9405280 Author: scripthunter7 <d.tota@adguard.com> Date: Mon Dec 1 12:33:05 2025 +0100 Remove enableAglintDebug setting and integrate with VSCode log level - Remove adblock.enableAglintDebug configuration option from package.json - Add automatic AGLint debug mode control based on VSCode's log level (Debug/Trace) - Implement shouldEnableAglintDebug() helper to map VSCode LogLevel to AGLint debug state - Add client/logLevelChanged notification to dynamically update debug mode - Pass initial debug state via initializationOptions during server initialization - Add onDidChangeLogLevel listeners commit 5fcf649 Author: scripthunter7 <d.tota@adguard.com> Date: Mon Dec 1 10:35:20 2025 +0100 bump client and server version commit cbdc821 Author: scripthunter7 <d.tota@adguard.com> Date: Mon Dec 1 10:34:21 2025 +0100 format json files commit f24587a Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 22:21:47 2025 +0100 Update version to 2.0.4 and improve logging system - Update version to 2.0.4 in package.json and CHANGELOG.md - Upgrade vscode-languageclient and vscode-languageserver to next.15 and next.13 - Add output channels for VSCode log level control integration - Convert file paths to file:// URLs for Windows compatibility in dynamic imports - Improve logging verbosity levels (info → debug for routine operations) - Add tip in README about controlling AGLint logging via VSCode's log level settings - Update commit 4170701 Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 19:58:32 2025 +0100 Update AGLint enabled message to be more specific commit cdcdf9a Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 18:52:29 2025 +0100 Update version to 2.0.3 in package.json and CHANGELOG.md commit 1c4bd5b Merge: edc8416 c590f99 Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 18:52:01 2025 +0100 Merge branch 'master' into fix/AG-47932 commit edc8416 Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 18:40:19 2025 +0100 Update version to 2.0.2 in package.json and CHANGELOG.md commit 05f1b9a Merge: 99dea52 2a4c889 Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 18:39:55 2025 +0100 Merge branch 'master' into fix/AG-47932 commit 99dea52 Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 18:34:36 2025 +0100 fix changelog commit a32d1cd Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 18:32:44 2025 +0100 Update version to 2.0.1 in package.json and CHANGELOG.md commit 6bb22ab Merge: a237cb4 13f0b1b Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 18:29:26 2025 +0100 Merge branch 'master' into fix/AG-47932 commit a237cb4 Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 18:10:01 2025 +0100 prepare v2.0.0 prerelease - Update version to 2.0.0 in package.json - Rename enableAglintCache setting to enableInMemoryAglintCache and mark as experimental - Change enableInMemoryAglintCache default value from true to false - Update CHANGELOG.md with release date and additional details about removed settings - Update README.md to reflect new setting name and experimental status - Update all references to enableAglintCache throughout codebase commit 7a4ebb6 Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 17:57:49 2025 +0100 fix type error commit 997b375 Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 28 17:55:34 2025 +0100 update AGLint to v4.0.0-beta.1 - Update AGLint dependency from v4.0.0-alpha.8 to v4.0.0-beta.1 - Update minimum supported AGLint version to v4.0.0-beta.1 commit 457af5f Author: scripthunter7 <d.tota@adguard.com> Date: Mon Nov 24 19:30:51 2025 +0100 Update to aglint 4.0.0-alpha.8 - Add adblock.enableAglintDebug configuration option (default: false) - Add adblock.enableAglintCache configuration option (default: true) - Implement LRU cache for linting results with cache key based on URI, AGLint version, document version, and config hash - Extract AGLint-related state into AglintContext class - Add ESLint rule to restrict direct imports from @adguard/aglint in server code - Update AGLint to v4.0.0-alpha.8 - Remove commit fb434cb Author: scripthunter7 <d.tota@adguard.com> Date: Fri Nov 21 15:25:24 2025 +0100 remove redundant check commit 3354eda Author: scripthunter7 <d.tota@adguard.com> Date: Wed Nov 19 21:18:07 2025 +0100 use destructuring assignment for fix and suggestions extraction - Replace explicit variable assignment with destructuring for diagnostic.data.fix - Replace explicit variable assignment with destructuring for diagnostic.data.suggestions - Remove unnecessary eslint-disable comments for prefer-destructuring rule ... and 24 more commits
1 parent c590f99 commit 994ebc7

35 files changed

+2308
-906
lines changed

.vscode/tasks.json

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -17,54 +17,6 @@
1717
},
1818
"problemMatcher": "$esbuild-watch",
1919
},
20-
{
21-
"label": "Integrated AGTree dev build (watch)",
22-
"type": "npm",
23-
"script": "watch:agtree",
24-
"isBackground": true,
25-
"group": {
26-
"kind": "build",
27-
"isDefault": true
28-
},
29-
"presentation": {
30-
"panel": "dedicated",
31-
"reveal": "never",
32-
"close": true
33-
},
34-
"problemMatcher": "$esbuild-watch",
35-
},
36-
{
37-
"label": "Integrated ECSSTree dev build (watch)",
38-
"type": "npm",
39-
"script": "watch:ecss-tree",
40-
"isBackground": true,
41-
"group": {
42-
"kind": "build",
43-
"isDefault": true
44-
},
45-
"presentation": {
46-
"panel": "dedicated",
47-
"reveal": "never",
48-
"close": true
49-
},
50-
"problemMatcher": "$esbuild-watch",
51-
},
52-
{
53-
"label": "Integrated AGLint dev build (watch)",
54-
"type": "npm",
55-
"script": "watch:aglint",
56-
"isBackground": true,
57-
"group": {
58-
"kind": "build",
59-
"isDefault": true
60-
},
61-
"presentation": {
62-
"panel": "dedicated",
63-
"reveal": "never",
64-
"close": true
65-
},
66-
"problemMatcher": "$esbuild-watch",
67-
},
6820
{
6921
"label": "Client dev build (watch)",
7022
"type": "npm",
@@ -126,9 +78,6 @@
12678
"dependsOn": [
12779
"Grammar dev build (watch)",
12880
"Server dev build (watch)",
129-
"Integrated AGTree dev build (watch)",
130-
"Integrated ECSSTree dev build (watch)",
131-
"Integrated AGLint dev build (watch)",
13281
"Client dev build (watch)"
13382
],
13483
},

CHANGELOG.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,44 @@ The format is based on [Keep a Changelog], and this project adheres to [Semantic
77
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
88
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
99

10-
## Unreleased
10+
## [2.0.4] (prerelease) - 2025-11-28
11+
12+
### Changed
13+
14+
- Improved logging.
15+
16+
### Fixed
17+
18+
- Loading AGLint on Windows.
19+
20+
## [2.0.3] (prerelease) - 2025-11-28
1121

1222
### Added
1323

1424
- Support for multi-root workspaces [#112].
1525
- `Remove this rule` quick fix option [#126].
26+
- Support for applying various fixes offered by AGLint [#127].
27+
- Support for detecting package manager automatically [#117].
28+
- `enableAglintDebug` and `enableInMemoryAglintCache` (experimental, disabled by default) settings.
1629

1730
### Changed
1831

32+
- Updated extension for AGLint `v4.0.0`.
1933
- Updated `husky` dependency to version `9.0.1` [#129].
2034

35+
### Removed
36+
37+
- Integrated version of AGLint. From now on, AGLint only works if it is installed separately.
38+
This provides more consistent behavior.
39+
This removed `useExternalAglintPackages` setting.
40+
- `packageManager` setting. It is now detected automatically.
41+
42+
[2.0.3]: https://github.com/AdguardTeam/VscodeAdblockSyntax/compare/1.1.17...2.0.3
2143
[#112]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/112
22-
[#129]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/129
44+
[#117]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/117
2345
[#126]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/126
46+
[#127]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/127
47+
[#129]: https://github.com/AdguardTeam/VscodeAdblockSyntax/issues/129
2448

2549
## 1.1.17 - 2024-05-05
2650

CONTRIBUTING.md

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ Table of Contents:
1313
- [Project structure](#project-structure)
1414
- [Running the extension in development mode](#running-the-extension-in-development-mode)
1515
- [Creating a production build](#creating-a-production-build)
16-
- [Updating integrated AGLint](#updating-integrated-aglint)
1716
- [Updating syntax highlighting](#updating-syntax-highlighting)
1817
- [Available commands](#available-commands)
1918
- [Useful links](#useful-links)
@@ -86,22 +85,6 @@ To create a production build of the extension:
8685
1. To ensure the build is correct, install the generated `.vsix` file in VSCode. Open the command palette
8786
(`Ctrl + Shift + P`), select "Extensions: Install from VSIX...", and choose the `vscode-adblock.vsix` file.
8887

89-
## Updating integrated AGLint
90-
91-
> [!NOTE]
92-
> This extension includes an integrated AGLint. It's a bundled version, avoiding the need for a separate AGLint
93-
> installation. However, the extension can use an external AGLint version if installed by a package manager.
94-
95-
1. Update AGLint in the `server/package.json` file. Alternatively, link the local AGLint repository if it hasn't been
96-
released on NPM.
97-
1. If there are breaking changes in the AGLint API, update the server code accordingly, changing the minimum supported
98-
AGLint version in `server/index.ts` (`MIN_AGLINT_VERSION` constant).
99-
1. Test the extension with the new AGLint version by running it in debug mode (see
100-
[*Running the extension in development mode*](#running-the-extension-in-development-mode) section). In the
101-
*"Extension Development Host"* window, you should open the test project (see `test/static` folder) and check if the
102-
extension works as expected.
103-
1. If needed, update the test project (e.g., update the config file, add new example rules).
104-
10588
## Updating syntax highlighting
10689

10790
1. Update the TM grammar in the `syntaxes/adblock.yaml-tmLanguage` file.
@@ -128,11 +111,6 @@ During development, you can use the following commands (listed in `package.json`
128111
for Continuous Integration (CI) purposes.
129112
- `pnpm build:vsix` - Produces a `.vsix` file in the out directory, which is used to install the extension in VSCode.
130113
- `pnpm clean` - Removes all generated files in the output directories, cleaning up the build results.
131-
- `pnpm esbuild:aglint` - Base ESBuild command for building integrated AGLint with the common options.
132-
- `pnpm esbuild:agtree` - Base ESBuild command for building integrated AGTree with the common options.
133-
Integrated AGTree comes with the integrated AGLint, this command just helps to bundle it to a separate file.
134-
This is needed because AGTree is also used by the server, and by bundling it to a separate file, we can avoid
135-
double-bundling AGTree.
136114
- `pnpm esbuild:server` - Base ESBuild command for building the server with the common options.
137115
- `pnpm esbuild:client` - Base ESBuild command for building the client with the common options.
138116
- `pnpm extract-changelog` - Extract changes from the `CHANGELOG.md` for a specific version. Typically, this is used by
@@ -145,8 +123,6 @@ During development, you can use the following commands (listed in `package.json`
145123
- `pnpm lint` - Run all linters.
146124
- `pnpm test:compile` - Check if the code compiles with [TypeScript][typescript].
147125
- `pnpm test` - Run tests with [Jest][jest].
148-
- `pnpm watch:aglint` - Watch for changes in the AGLint code and create a development build automatically.
149-
- `pnpm watch:agtree` - Watch for changes in the AGTree code and create a development build automatically.
150126
- `pnpm watch:client` - Watch for changes in the client code and create a development build automatically.
151127
- `pnpm watch:grammar` - Watch for changes in the TM grammar and rebuild it automatically.
152128
- `pnpm watch:server` - Watch for changes in the server code and create a development build automatically.

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,16 @@ to read.
7979

8080
### AGLint integration (linter)
8181

82-
We integrated [AGLint][aglint] into this extension, that makes it able to check your rules for various issues, such as
83-
invalid syntax, invalid domains, invalid / incompatible CSS selectors, unknown / incompatible scriptlets, bad practices,
84-
etc. For more information about AGLint, please refer to its [repository][aglint].
82+
This extension integrates [AGLint][aglint] to check your rules for syntax errors, invalid domains,
83+
incompatible CSS selectors, unknown scriptlets, and other issues. For more details, see the [AGLint repository][aglint].
8584

86-
AGLint integration is done in the following way:
85+
The extension automatically searches for AGLint installations in this order:
8786

88-
1. Extension will search local AGLint installation (if it is installed) and use it for linting. First, it will search
89-
for local installation in the current workspace, and if it is not found, it will search for a global installation.
90-
This is an ideal behavior, because if you have a local installation, it guarantees that you will use the same version
91-
of AGLint, and the results will be the same.
92-
2. If the extension doesn't find any installation, it will use the bundled version of AGLint, which is included in the
93-
extension itself. Usually, it is the latest version of AGLint. The advantage of this approach is that you don't need
94-
to install AGLint manually, and you can start using the extension immediately after installation.
87+
1. Local workspace installation
88+
2. Global installation
89+
3. Prompts to install if not found
90+
91+
Using a local installation ensures consistent results with your project's AGLint version.
9592

9693
> [!WARNING]
9794
> Please note that the linter is under active development, so it may not work properly for some rules. If you
@@ -106,9 +103,12 @@ This extension provides the following configuration options:
106103
| Option | Description | Default value | Possible values |
107104
| ------ | ----------- | ------------- | --------------- |
108105
| `adblock.enableAglint` | Enable or disable AGLint integration. If disabled, only syntax highlighting and other language features will be available. | `true` | `true`, `false` |
109-
| `adblock.useExternalAglintPackages` | If enabled, extension will search for AGLint installations in the system. If disabled, extension will use its own AGLint installation, which is included in the extension (integrated AGLint bundle). If you have AGLint installed in your system / project, it is recommended to enable this option in order to provide consistent results. | `true` | `true`, `false` |
110-
| `adblock.packageManager` | Package manager to use for searching global AGLint installations. Set it to your preferred package manager. | `npm` | `npm`, `yarn`, `pnpm` |
111-
<!--markdownlint-enable MD013-->
106+
| `adblock.enableInMemoryAglintCache` | ⚠️ **Experimental**: Enable or disable in-memory caching of linting results for better performance. | `false` | `true`, `false` |
107+
108+
**Note:** AGLint debug logging is automatically enabled when VSCode's log level is set to "Debug" or "Trace" via "Developer: Set Log Level".
109+
110+
> **💡 Tip**: To control AGLint logging verbosity, use VSCode's built-in log level control:
111+
> Open Command Palette (**Cmd+Shift+P**) → **Developer: Set Log Level...** → Select **AGLint**
112112
113113
### GitHub Linguist support
114114

client/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"name": "aglint-client",
3-
"version": "1.0.0",
3+
"version": "2.0.0",
44
"license": "MIT",
55
"author": "AdGuard Software Ltd.",
66
"description": "Integrates AGLint into VSCode",
77
"private": true,
88
"dependencies": {
99
"valibot": "^1.1.0",
10-
"vscode-languageclient": "^8.0.2"
10+
"vscode-languageclient": "10.0.0-next.15"
1111
},
1212
"devDependencies": {
1313
"@types/vscode": "^1.74.0"

client/src/extension.ts

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as v from 'valibot';
44
import {
55
commands,
66
type ExtensionContext,
7+
LogLevel,
78
RelativePattern,
89
StatusBarAlignment,
910
type StatusBarItem,
@@ -97,6 +98,20 @@ let defaultClient: LanguageClient | undefined;
9798
*/
9899
const clients = new Map<string, LanguageClient>();
99100

101+
/**
102+
* Convert VSCode LogLevel to a simple boolean for AGLint debug mode.
103+
* Enable AGLint debugger only when VSCode log level is Debug or Trace.
104+
*
105+
* @param logLevel VSCode log level.
106+
*
107+
* @returns Whether AGLint debug mode should be enabled.
108+
*/
109+
function shouldEnableAglintDebug(logLevel: LogLevel): boolean {
110+
// LogLevel enum: Off = 0, Trace = 1, Debug = 2, Info = 3, Warning = 4, Error = 5
111+
// Enable AGLint debug when log level is Trace (1) or Debug (2)
112+
return logLevel <= LogLevel.Debug;
113+
}
114+
100115
/**
101116
* Status bar item to show the AGLint status.
102117
* This is shared across all workspace folders and updates based on the active editor's folder.
@@ -220,25 +235,44 @@ function createClientForFolder(folder: WorkspaceFolder, serverModule: string): L
220235

221236
const rootFs = folder.uri.fsPath;
222237

238+
// Create output channel - this makes the extension appear in "Developer: Set Log Level"
239+
const outputChannel = Window.createOutputChannel(`${CLIENT_NAME} (${folder.name})`, { log: true });
240+
223241
const clientOptions: LanguageClientOptions = {
224242
documentSelector: [{ scheme: DOCUMENT_SCHEME, language: LANGUAGE_ID }],
225243

226244
workspaceFolder: folder,
227245
initializationOptions: {
228246
workspaceFolder: { uri: folder.uri.toString(), name: folder.name },
247+
enableAglintDebug: shouldEnableAglintDebug(outputChannel.logLevel),
229248
},
230249

250+
outputChannel,
251+
231252
synchronize: {
232253
fileEvents: [
233254
Workspace.createFileSystemWatcher(
234-
new RelativePattern(folder, `**/*.{${Array.from(SUPPORTED_FILE_EXTENSIONS).join(',')}}`),
255+
new RelativePattern(
256+
folder,
257+
`{**/*.{${Array.from(SUPPORTED_FILE_EXTENSIONS).join(',')}},!**/node_modules/**}`,
258+
),
235259
false,
236260
true,
237261
false,
238262
),
239-
// eslint-disable-next-line max-len
240-
Workspace.createFileSystemWatcher(new RelativePattern(folder, `**/{${Array.from(CONFIG_FILE_NAMES).join(',')}}`)),
241-
Workspace.createFileSystemWatcher(new RelativePattern(folder, `**/${IGNORE_FILE_NAME}`)),
263+
Workspace.createFileSystemWatcher(
264+
new RelativePattern(
265+
folder,
266+
`{**/{${Array.from(CONFIG_FILE_NAMES).join(',')}},!**/node_modules/**}`,
267+
),
268+
),
269+
Workspace.createFileSystemWatcher(
270+
new RelativePattern(folder, `{**/${IGNORE_FILE_NAME},!**/node_modules/**}`),
271+
),
272+
// Watch package.json for AGLint installation changes (only root, not node_modules)
273+
Workspace.createFileSystemWatcher(new RelativePattern(folder, 'package.json')),
274+
// Watch node_modules directory itself for package installation/updates
275+
Workspace.createFileSystemWatcher(new RelativePattern(folder, 'node_modules')),
242276
],
243277
},
244278

@@ -298,6 +332,15 @@ function createClientForFolder(folder: WorkspaceFolder, serverModule: string): L
298332
updateStatusBarForFolder(folder, params);
299333
});
300334

335+
// Listen for log level changes and notify the server
336+
outputChannel.onDidChangeLogLevel((newLogLevel) => {
337+
const enableDebug = shouldEnableAglintDebug(newLogLevel);
338+
// Send notification to server about log level change
339+
client.sendNotification('client/logLevelChanged', { enableAglintDebug: enableDebug }).catch(() => {
340+
// Ignore errors - server might not be ready yet
341+
});
342+
});
343+
301344
return client;
302345
}
303346

@@ -316,9 +359,16 @@ function ensureDefaultClient(serverModule: string) {
316359
debug: { module: serverModule, transport: TransportKind.ipc },
317360
};
318361

362+
// Create output channel - this makes the extension appear in "Developer: Set Log Level"
363+
const outputChannel = Window.createOutputChannel(`${CLIENT_NAME} (untitled)`, { log: true });
364+
319365
const clientOptions: LanguageClientOptions = {
320366
documentSelector: [{ scheme: FileScheme.Untitled, language: LANGUAGE_ID }],
321367
progressOnInitialization: true,
368+
outputChannel,
369+
initializationOptions: {
370+
enableAglintDebug: shouldEnableAglintDebug(outputChannel.logLevel),
371+
},
322372
};
323373

324374
// Give the untitled client a unique ID too
@@ -328,6 +378,16 @@ function ensureDefaultClient(serverModule: string) {
328378
serverOptions,
329379
clientOptions,
330380
);
381+
382+
// Listen for log level changes and notify the server
383+
outputChannel.onDidChangeLogLevel((newLogLevel) => {
384+
const enableDebug = shouldEnableAglintDebug(newLogLevel);
385+
// Send notification to server about log level change
386+
defaultClient?.sendNotification('client/logLevelChanged', { enableAglintDebug: enableDebug }).catch(() => {
387+
// Ignore errors - server might not be ready yet
388+
});
389+
});
390+
331391
defaultClient.start();
332392
}
333393

client/tsconfig.json

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
{
2-
"compilerOptions": {
3-
"module": "CommonJS",
4-
"target": "es2020",
5-
"lib": ["es2020"],
6-
"outDir": "out",
7-
"rootDir": "src",
8-
"sourceMap": true,
9-
"skipLibCheck": true,
10-
},
11-
"include": ["src"],
12-
"exclude": ["node_modules", ".vscode-test"]
13-
}
1+
{
2+
"compilerOptions": {
3+
"module": "es2020",
4+
"target": "es2020",
5+
"lib": ["es2020"],
6+
"moduleResolution": "bundler",
7+
"outDir": "out",
8+
"rootDir": "src",
9+
"sourceMap": true,
10+
"skipLibCheck": true
11+
},
12+
"include": ["src"],
13+
"exclude": ["node_modules", ".vscode-test"]
14+
}

0 commit comments

Comments
 (0)