Skip to content

Commit ee36442

Browse files
fix: code fixes (#21)
* fix: tsconfig * feat: added `.prettierrc` * chore: updated TODO * fix: minor bugs * chore: updated `eslint.config.mjs` * chore: updated `TODO.md` * chore: updated `isPositionInComment.ts` and `isPositionInString.ts` with `isPositionInScope.ts` * chore: updated `ClassNameCache` * chore: updated tests * chore: updated tests * chore: updated tests * chore: updated tests
1 parent b06c170 commit ee36442

39 files changed

Lines changed: 409 additions & 275 deletions

.prettierrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"semi": true,
3+
"singleQuote": false,
4+
"tabWidth": 2,
5+
"useTabs": false,
6+
"trailingComma": "es5",
7+
"printWidth": 80
8+
}

.vscode/settings.json

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
// Place your settings in this file to overwrite default and user settings.
22
{
3-
"files.exclude": {
4-
"out": false // set this to true to hide the "out" folder with the compiled JS files
5-
},
6-
"search.exclude": {
7-
"out": true // set this to false to include "out" folder in search results
8-
},
9-
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
10-
"typescript.tsc.autoDetect": "off",
11-
"cssModulesIntellisense.aliases": {
12-
"~": "./src"
13-
},
14-
"cSpell.words": ["onig", "ovsx", "pcss", "styl", "vsctm"]
3+
"files.exclude": {
4+
"out": false // set this to true to hide the "out" folder with the compiled JS files
5+
},
6+
"search.exclude": {
7+
"out": true // set this to false to include "out" folder in search results
8+
},
9+
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
10+
"typescript.tsc.autoDetect": "off",
11+
"cssModulesIntellisense.aliases": {
12+
"~": "./src"
13+
},
14+
"cSpell.words": [
15+
"garg",
16+
"lokesh",
17+
"onig",
18+
"ovsx",
19+
"pcss",
20+
"styl",
21+
"vscodeignore",
22+
"vsctm"
23+
]
1524
}

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
### Fixed
8+
9+
- Minor Bugs
10+
711
## [0.1.5] – 2026-01-27
812

913
### Added
@@ -135,5 +139,4 @@ All notable changes to this project will be documented in this file.
135139
[0.1.2]: https://github.com/Lokesh-Garg-22/CSS-Modules-IntelliSense/compare/v0.1.1...v0.1.2
136140
[0.1.3]: https://github.com/Lokesh-Garg-22/CSS-Modules-IntelliSense/compare/v0.1.2...v0.1.3
137141
[0.1.4]: https://github.com/Lokesh-Garg-22/CSS-Modules-IntelliSense/compare/v0.1.3...v0.1.4
138-
139142
[0.1.5]: https://github.com/Lokesh-Garg-22/CSS-Modules-IntelliSense/compare/v0.1.4...v0.1.5

docs/PROJECT_STRUCTURE.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ CSS/SCSS Modules IntelliSense VS Code extension.
55

66
## Directory Structure
77

8-
```
8+
```txt
99
css-modules-intellisense/
1010
├── .github/ # GitHub-specific files
1111
│ └── workflows/ # GitHub Actions workflows
@@ -33,7 +33,8 @@ css-modules-intellisense/
3333
│ │ ├── classNameCache.ts # Class name caching
3434
│ │ ├── cssModuleDependencyCache.ts
3535
│ │ ├── loadCaches.ts # Cache initialization
36-
│ │ └── processConfig.ts # Configuration processing
36+
│ │ ├── processConfig.ts # Configuration processing
37+
│ │ └── vsConfig.ts # VS Code configuration helpers
3738
│ ├── providers/ # Language feature providers
3839
│ │ ├── completionProvider.ts # Auto-completion
3940
│ │ ├── definitionProvider.ts # Go-to-definition
@@ -55,8 +56,7 @@ css-modules-intellisense/
5556
│ │ ├── getPath.ts
5657
│ │ ├── getRegistry.ts
5758
│ │ ├── isDocumentModule.ts
58-
│ │ ├── isPositionInComment.ts
59-
│ │ ├── isPositionInString.ts
59+
│ │ ├── isPositionInScope.ts
6060
│ │ └── sanitizeCssInput.ts
6161
│ ├── config.ts # Extension configuration
6262
│ └── extension.ts # Extension entry point
@@ -70,6 +70,7 @@ css-modules-intellisense/
7070
│ └── scss.tmLanguage.json
7171
├── .editorconfig # Editor configuration
7272
├── .gitignore # Git ignore rules
73+
├── .prettierrc # Prettier formatting rules
7374
├── .markdownlint.json # Markdown linting rules
7475
├── .vscode-test.mjs # VS Code test configuration
7576
├── .vscodeignore # Files to exclude from extension package
@@ -120,6 +121,7 @@ Static resources including test fixtures and extension icons
120121
## Configuration Files
121122

122123
- `.editorconfig` - Code style consistency
124+
- `.prettierrc` - Code formatting rules
123125
- `tsconfig.json` - TypeScript compiler settings
124126
- `eslint.config.mjs` - Linting rules
125127
- `package.json` - Extension metadata and dependencies

docs/TODO.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,25 @@
22

33
## Enhancements
44

5-
<!-- Add enhancements here -->
5+
- Add `cssModulesIntellisense.diagnostics.classNotDefined.enabled` (boolean) and
6+
`cssModulesIntellisense.diagnostics.classNotDefined.severity`
7+
(`"error" | "warning" | "info" | "hint"`)
8+
settings to control the "class not defined" diagnostic in `analyzeDocument`.
9+
10+
- Add `cssModulesIntellisense.diagnostics.classNotUsed.enabled` (boolean) and
11+
`cssModulesIntellisense.diagnostics.classNotUsed.severity`
12+
(`"error" | "warning" | "info" | "hint"`)
13+
settings to show a "Class 'x' is never used" diagnostic on CSS module files,
14+
by cross-referencing `ClassNameCache` against usage in all dependent JS/TS files
15+
via `CssModuleDependencyCache`.
616

717
## Known Issues
818

919
<!-- Add known issues here -->
1020

1121
## Future Improvements
1222

13-
<!-- Add future improvements here -->
23+
- Add an extension setting to configure the class name cache size (LRU max entries).
24+
Currently hardcoded to 3, which causes frequent cache evictions and re-parsing
25+
in projects with more than 3 CSS module files. Should be user-configurable via
26+
`cssModules.classNameCacheSize` in extension settings.

eslint.config.mjs

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,78 @@
11
import typescriptEslint from "@typescript-eslint/eslint-plugin";
22
import tsParser from "@typescript-eslint/parser";
33

4-
export default [{
5-
files: ["**/*.ts"],
6-
}, {
4+
export default [
5+
{
6+
ignores: ["dist/**", "node_modules/**", "assets/**", ".vscode-test/**"],
7+
},
8+
{
9+
files: ["src/**/*.ts"],
710
plugins: {
8-
"@typescript-eslint": typescriptEslint,
11+
"@typescript-eslint": typescriptEslint,
912
},
10-
1113
languageOptions: {
12-
parser: tsParser,
13-
ecmaVersion: 2022,
14-
sourceType: "module",
14+
parser: tsParser,
15+
ecmaVersion: 2022,
16+
sourceType: "module",
17+
parserOptions: {
18+
project: true,
19+
tsconfigRootDir: import.meta.dirname,
20+
},
1521
},
16-
1722
rules: {
18-
"@typescript-eslint/naming-convention": ["warn", {
19-
selector: "import",
20-
format: ["camelCase", "PascalCase"],
21-
}],
23+
// Naming
24+
"@typescript-eslint/naming-convention": [
25+
"warn",
26+
{ selector: "import", format: ["camelCase", "PascalCase"] },
27+
],
28+
29+
// Correctness
30+
curly: "warn",
31+
eqeqeq: ["warn", "always"],
32+
"@typescript-eslint/only-throw-error": "warn",
33+
"@typescript-eslint/no-floating-promises": "error",
34+
"@typescript-eslint/no-misused-promises": "error",
35+
"@typescript-eslint/await-thenable": "error",
2236

23-
curly: "warn",
24-
eqeqeq: "warn",
25-
"no-throw-literal": "warn",
26-
semi: "warn",
37+
// Type safety
38+
"@typescript-eslint/no-explicit-any": "warn",
39+
"@typescript-eslint/no-unsafe-assignment": "warn",
40+
"@typescript-eslint/no-unsafe-member-access": "warn",
41+
"@typescript-eslint/no-unsafe-call": "warn",
42+
"@typescript-eslint/no-unsafe-return": "warn",
43+
44+
// Dead code
45+
"@typescript-eslint/no-unused-vars": [
46+
"warn",
47+
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
48+
],
49+
"no-unused-vars": "off", // disabled in favour of @typescript-eslint/no-unused-vars
50+
51+
// Code style
52+
semi: "warn",
53+
"@typescript-eslint/consistent-type-imports": [
54+
"warn",
55+
{ prefer: "type-imports", fixStyle: "inline-type-imports" },
56+
],
57+
"@typescript-eslint/prefer-nullish-coalescing": "warn",
58+
"@typescript-eslint/prefer-optional-chain": "warn",
59+
},
60+
},
61+
{
62+
// Looser rules for config/test files — no type-aware linting needed
63+
files: ["*.mjs", "src/test/**/*.ts"],
64+
plugins: {
65+
"@typescript-eslint": typescriptEslint,
66+
},
67+
languageOptions: {
68+
parser: tsParser,
69+
ecmaVersion: 2022,
70+
sourceType: "module",
71+
},
72+
rules: {
73+
curly: "warn",
74+
eqeqeq: "warn",
75+
semi: "warn",
2776
},
28-
}];
77+
},
78+
];

src/extension.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ export async function activate(context: vscode.ExtensionContext) {
2121
CheckDocument.diagnosticCollection = diagnosticCollection;
2222

2323
Cache.context = context;
24-
const loaded = Cache.loadCache();
24+
const loaded = await Cache.loadCache();
2525
if (!loaded) {
26-
CssModuleDependencyCache.populateCacheFromWorkspace();
26+
await CssModuleDependencyCache.populateCacheFromWorkspace();
2727
}
2828
loadCaches();
2929

src/libs/cache.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as fs from "fs";
22
import * as path from "path";
3-
import * as vscode from "vscode";
3+
import type * as vscode from "vscode";
44
import { CSS_MODULES_CACHE_FILENAME, DEBOUNCE_TIMER } from "../config";
55
import {
6-
CacheJsonObject,
6+
type CacheJsonObject,
77
ClassNameCache,
88
ClassNameRangeMap,
99
ModulePathCache,
@@ -79,7 +79,7 @@ export default class Cache {
7979
static async saveCache() {
8080
clearTimeout(this.saveCacheDebounceId);
8181
this.saveCacheDebounceId = setTimeout(() => {
82-
this._saveCache();
82+
this._saveCache().catch(console.error);
8383
}, DEBOUNCE_TIMER.CACHE);
8484
}
8585

@@ -142,10 +142,10 @@ export default class Cache {
142142
const parsed: { [K in keyof CacheJsonObject]?: CacheJsonObject[K] } =
143143
JSON.parse(raw);
144144

145-
this.pathMapCache.setArray(parsed.pathMapCache || []);
145+
this.pathMapCache.setArray(parsed.pathMapCache ?? []);
146146

147147
this.modulePathCache.setMap(
148-
Object.entries(parsed.modulePathCache || {}).map(
148+
Object.entries(parsed.modulePathCache ?? {}).map(
149149
([key, valueArray]) => [
150150
key,
151151
new ModulePathCacheSet(this.pathMapCache, valueArray),
@@ -154,7 +154,7 @@ export default class Cache {
154154
);
155155

156156
this.classNameCache.setMap(
157-
Object.entries(parsed.classNameCache || {}).map(([key, value]) => [
157+
Object.entries(parsed.classNameCache ?? {}).map(([key, value]) => [
158158
key,
159159
new ClassNameRangeMap(Object.entries(value)),
160160
])

src/libs/checkDocument.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export default class CheckDocument {
6060
static push(document: vscode.TextDocument): number {
6161
if (this.isQueueEmpty()) {
6262
const length = this.documentQueue.push(document);
63-
this.checkNextDocument();
63+
this.checkNextDocument().catch(console.error);
6464
return length;
6565
}
6666
while (this.documentQueue.length >= MAX_CHECK_DOCUMENT_QUEUE_LENGTH) {
@@ -109,7 +109,7 @@ export default class CheckDocument {
109109
static setDebounceTimer(): void {
110110
clearTimeout(this.debounceTimerId);
111111
this.debounceTimerId = setTimeout(() => {
112-
this.checkNextDocument();
112+
this.checkNextDocument().catch(console.error);
113113
}, DEBOUNCE_TIMER.CHECK_DOCUMENT);
114114
}
115115

@@ -137,7 +137,6 @@ export default class CheckDocument {
137137
return;
138138
}
139139

140-
const text = document.getText();
141140
const diagnostics: vscode.Diagnostic[] = [];
142141
const importMatches = await getAllImportModulePaths(document);
143142

src/libs/classNameCache.ts

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import {
99
resolveWorkspaceRelativePath,
1010
} from "../utils/getPath";
1111
import { sanitizeCssInput } from "../utils/sanitizeCssInput";
12-
import isPositionInComment from "../utils/isPositionInComment";
12+
import { isPositionInComment } from "../utils/isPositionInScope";
1313
import CssModuleDependencyCache from "./cssModuleDependencyCache";
1414
import CheckDocument from "./checkDocument";
15-
import { ClassNameRange, ClassNameRangeMap } from "../types/cache";
15+
import { type ClassNameRange, ClassNameRangeMap } from "../types/cache";
1616

1717
/**
1818
* A utility class to extract and cache class names from CSS Module files.
@@ -34,23 +34,29 @@ export default class ClassNameCache {
3434
static async updateClassNameCache(e: vscode.TextDocument) {
3535
const importPath = getWorkspaceRelativeUriPath(e.uri);
3636
clearTimeout(this.ClassNameCacheDebounceIdMap[importPath]);
37-
this.ClassNameCacheDebounceIdMap[importPath] = setTimeout(async () => {
38-
await ClassNameCache.extractFromUri(e.uri);
37+
this.ClassNameCacheDebounceIdMap[importPath] = setTimeout(() => {
38+
(async () => {
39+
await ClassNameCache.extractFromUri(e.uri);
3940

40-
if (SUPPORTED_MODULES.includes(e.languageId)) {
41-
const dependents = CssModuleDependencyCache.getDependentsForDocument(e);
41+
if (SUPPORTED_MODULES.includes(e.languageId)) {
42+
const dependents =
43+
CssModuleDependencyCache.getDependentsForDocument(e);
4244

43-
for (const workspacePath of dependents) {
44-
const resolvedPath = resolveWorkspaceRelativePath(workspacePath);
45-
if (!resolvedPath) {
46-
return;
45+
for (const workspacePath of dependents) {
46+
const resolvedPath = resolveWorkspaceRelativePath(workspacePath);
47+
if (!resolvedPath) {
48+
continue;
49+
}
50+
const document =
51+
await vscode.workspace.openTextDocument(resolvedPath);
52+
CheckDocument.push(document);
4753
}
48-
const document = await vscode.workspace.openTextDocument(
49-
resolvedPath
50-
);
51-
CheckDocument.push(document);
5254
}
53-
}
55+
})()
56+
.catch(console.error)
57+
.finally(() => {
58+
delete ClassNameCache.ClassNameCacheDebounceIdMap[importPath];
59+
});
5460
}, DEBOUNCE_TIMER.UPDATE_CLASS_NAME);
5561
}
5662

@@ -182,11 +188,11 @@ export default class ClassNameCache {
182188
): Promise<string[] | undefined> {
183189
if (Cache.classNameCache.hasByKey(importPath)) {
184190
return Array.from(
185-
Cache.classNameCache.getByKey(importPath)?.keys() || []
191+
Cache.classNameCache.getByKey(importPath)?.keys() ?? []
186192
);
187193
} else {
188194
return Array.from(
189-
(await this.extractAndCacheClassNames(importPath))?.keys() || []
195+
(await this.extractAndCacheClassNames(importPath))?.keys() ?? []
190196
);
191197
}
192198
}
@@ -279,7 +285,7 @@ export default class ClassNameCache {
279285
}
280286

281287
Cache.classNameCache.setByKey(importPath, classNames);
282-
Cache.saveCache();
288+
Cache.saveCache().catch(console.error);
283289
return classNames;
284290
}
285291
}

0 commit comments

Comments
 (0)