Skip to content

Commit

Permalink
dev: drop node-watch (#2963)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason3S authored Dec 7, 2023
1 parent 07c0b2d commit fb06f93
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 84 deletions.
3 changes: 2 additions & 1 deletion Spell Checker.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
"editor.formatOnSave": true,
"files.eol": "\n",
"cSpell.flagWords": [],
"cSpell.enableFiletypes": ["github-actions-workflow"]
"cSpell.enableFiletypes": ["github-actions-workflow"],
"svg.preview.background": "dark-transparent"
},
"launch": {
"configurations": [
Expand Down
12 changes: 2 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"icon": "images/SpellCheck.png",
"author": "Jason Dent",
"license": "GPL-3.0-or-later",
"version": "3.0.1",
"version": "4.0.0",
"publisher": "streetsidesoftware",
"private": true,
"repository": {
Expand Down
1 change: 0 additions & 1 deletion packages/_server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
"cspell-lib": "^8.1.3",
"gensequence": "^6.0.0",
"json-rpc-api": "file:../json-rpc-api",
"node-watch": "^0.7.4",
"rxjs": "^7.8.1",
"utils-disposables": "file:../utils-disposables",
"utils-logger": "file:../utils-logger",
Expand Down
2 changes: 1 addition & 1 deletion packages/_server/src/config/configTargetsHelper.mts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function calculateConfigTargets(
configFilesFound?: string[],
): Promise<ConfigTarget[]> {
const found = new Set(configFilesFound);
async function isFound(filename: string) {
function isFound(filename: string) {
if (found.has(filename)) return true;
const href = toFileUri(filename).toString();
return found.has(href);
Expand Down
14 changes: 7 additions & 7 deletions packages/_server/src/config/dictionaryWatcher.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import type { CSpellSettings } from 'cspell-lib';
import { join } from 'path';
import { afterEach, describe, expect, test, vi } from 'vitest';

import { addNodeWatchMockImplementation, asNodeWatchMock } from '../test/mock-node-watch.js';
import { watch } from '../utils/nodeWatch.cjs';
import { addNodeWatchMockImplementation } from '../test/mock-node-watch.js';
import { watchFile } from '../utils/watchFile.mjs';
import { DictionaryWatcher } from './dictionaryWatcher.mjs';

vi.mock('node-watch');
vi.mock('../utils/watchFile.mjs');

const dictA = join(__dirname, 'dictA.txt');
const dictB = join(__dirname, 'dictB.txt');
Expand All @@ -23,11 +23,11 @@ const sampleConfig: CSpellSettings = {

describe('Validate Dictionary Watcher', () => {
afterEach(() => {
asNodeWatchMock(watch).__reset();
vi.resetAllMocks();
});

test('watching dictionaries', () => {
const mockWatch = addNodeWatchMockImplementation(vi.mocked(watch));
const mockWatch = addNodeWatchMockImplementation(vi.mocked(watchFile));
const dw = new DictionaryWatcher();

const listener = vi.fn();
Expand All @@ -49,8 +49,8 @@ describe('Validate Dictionary Watcher', () => {

expect(dw.watchedFiles).toEqual([]);

expect(mockWatch).toHaveBeenNthCalledWith(1, dictA, expect.any(Object), expect.any(Function));
expect(mockWatch).toHaveBeenNthCalledWith(2, dictB, expect.any(Object), expect.any(Function));
expect(mockWatch).toHaveBeenNthCalledWith(1, dictA, expect.any(Function));
expect(mockWatch).toHaveBeenNthCalledWith(2, dictB, expect.any(Function));
expect(mockWatch).toHaveBeenCalledTimes(2);

expect(listener).toHaveBeenCalledWith('update', dictB);
Expand Down
4 changes: 1 addition & 3 deletions packages/_server/src/config/documentSettings.mts
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ export class DocumentSettings {
const rawImports = cSpellConfigSettings.import || [];
const imports = Array.isArray(rawImports) ? rawImports : [rawImports];
imports.push('@cspell/cspell-bundled-dicts');
console.error('fetchSettingsFromVSCode %o', { imports });
// console.error('fetchSettingsFromVSCode %o', { imports });
cSpellConfigSettings.import = imports;
}

Expand Down Expand Up @@ -734,10 +734,8 @@ async function filterUrl(uri: Uri): Promise<Uri | undefined> {
try {
const stats = await stat(url);
const found = stats.isFile() ? uri : undefined;
console.error('filterUrl %o', { uri: uri.toString(), found: !!found });
return found;
} catch (e) {
console.error('filterUrl Not found', uri.toString());
return undefined;
}
}
Expand Down
2 changes: 0 additions & 2 deletions packages/_server/src/server.mts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ const overRideDefaults: CSpellUserSettings = {
ignoreRegExpList: [],
};

// Turn off the spell checker by default. The setting files should have it set.
// This prevents the spell checker from running too soon.
const defaultSettings = calcDefaultSettings();
const defaultDebounceMs = 50;
// Refresh the dictionary cache every 1000ms.
Expand Down
39 changes: 20 additions & 19 deletions packages/_server/src/test/mock-node-watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ import type { FSWatcher } from 'fs';
import type { MockedFunction } from 'vitest';
import { vi } from 'vitest';

declare function watch(pathName: PathName): Watcher;
declare function watch(pathName: PathName, options: Options): Watcher;
// declare function watch(pathName: PathName): Watcher;
// declare function watch(pathName: PathName, options: Options): Watcher;
declare function watch(pathName: PathName, callback: Callback): Watcher;
declare function watch(pathName: PathName, options: Options, callback: Callback): Watcher;
// declare function watch(pathName: PathName, options: Options, callback: Callback): Watcher;

type EventType = 'update' | 'remove';
type Callback = (eventType: EventType, filePath: string) => any;
type PathName = string | Array<string>;
type Callback = (eventType?: string, filePath?: string | null) => any;
type PathName = string;
type FilterReturn = boolean | symbol;

declare interface Watcher extends FSWatcher {
interface WatcherInternal extends FSWatcher {
/**
* Returns `true` if the watcher has been closed.
*/
Expand All @@ -25,19 +24,21 @@ declare interface Watcher extends FSWatcher {
getWatchedPaths(): Array<string>;
}

type Watcher = Pick<FSWatcher, 'close'>;

type NodeWatch = typeof watch;

type MockedNodeWatch = MockedFunction<NodeWatch>;

export interface NodeWatchMock extends MockedNodeWatch {
__trigger(eventType: 'update' | 'remove' | undefined, filename: string): void;
__getWatchers(filename?: string): Watcher[];
__getWatchers(filename?: string): WatcherInternal[];
__reset(): void;
}

type WatcherCallback = (eventType?: 'update' | 'remove', filename?: string) => void;

interface Watcher extends FSWatcher {
interface WatcherInternal extends FSWatcher {
/**
* Returns `true` if the watcher has been closed.
*/
Expand Down Expand Up @@ -86,23 +87,23 @@ type Options = {
};

export function addNodeWatchMockImplementation(mock: MockedNodeWatch): NodeWatchMock {
const callbacks = new Map<string, Set<Watcher>>();
const callbacks = new Map<string, Set<WatcherInternal>>();

function getWatchedPaths() {
return [...callbacks.keys()];
}

function addCallback(pathName: PathName): Watcher;
function addCallback(pathName: PathName, options: Options): Watcher;
function addCallback(pathName: PathName, callback: WatcherCallback): Watcher;
function addCallback(pathName: PathName, options: Options, callback: WatcherCallback): Watcher;
function addCallback(pathName: PathName, options?: Options | WatcherCallback, callback?: WatcherCallback): Watcher {
function addCallback(pathName: PathName): WatcherInternal;
function addCallback(pathName: PathName, options: Options): WatcherInternal;
function addCallback(pathName: PathName, callback: WatcherCallback): WatcherInternal;
function addCallback(pathName: PathName, options: Options, callback: WatcherCallback): WatcherInternal;
function addCallback(pathName: PathName, options?: Options | WatcherCallback, callback?: WatcherCallback): WatcherInternal {
if (typeof options === 'function') {
callback = options;
}

let isClosed = false;
const watcher: Watcher = {
const watcher: WatcherInternal = {
close: vi.fn(() => {
isClosed = true;
}),
Expand All @@ -126,14 +127,14 @@ export function addNodeWatchMockImplementation(mock: MockedNodeWatch): NodeWatch
eventNames: vi.fn(),
};

function defaultImpl(): Watcher {
function defaultImpl(): WatcherInternal {
return watcher;
}

const pathNames = Array.isArray(pathName) ? pathName : [pathName];

for (const pathName of pathNames) {
const cb = callbacks.get(pathName) || new Set<Watcher>();
const cb = callbacks.get(pathName) || new Set<WatcherInternal>();
cb.add(watcher);
callbacks.set(pathName, cb);
}
Expand All @@ -153,7 +154,7 @@ export function addNodeWatchMockImplementation(mock: MockedNodeWatch): NodeWatch
}
}

function getWatchers(filename: string | undefined): Watcher[] {
function getWatchers(filename: string | undefined): WatcherInternal[] {
if (!filename) {
return [...callbacks.keys()].map(getWatchers).reduce((acc, cur) => acc.concat(cur), []);
}
Expand Down
36 changes: 10 additions & 26 deletions packages/_server/src/utils/fileWatcher.mts
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import { logError } from '@internal/common-utils/log';
import { toFileUri } from '@internal/common-utils/uriHelper';
import type { FSWatcher } from 'fs';
import { format } from 'util';
import type { Disposable } from 'vscode-languageserver/node.js';

import { nodeWatch } from './nodeWatch.cjs';

export type KnownEvents = 'change' | 'error' | 'close';
export type EventType = KnownEvents | string;

export type Listener = (eventType?: EventType, filename?: string) => void;

type Watcher = Pick<FSWatcher, 'close'>;
import type { EventType, Listener, Watcher } from './watchFile.mjs';
import { watchFile } from './watchFile.mjs';

export class FileWatcher implements Disposable {
private watchedFile = new Map<string, Watcher>();
Expand All @@ -29,7 +21,8 @@ export class FileWatcher implements Disposable {
* @param eventType - event to trigger
* @param filename - filename to trigger
*/
readonly trigger: Listener = (eventType?: EventType, filename?: string): void => {
readonly trigger = (eventType?: EventType, filename?: string | null): void => {
filename ??= undefined;
this.notifyListeners(eventType, filename);
};

Expand All @@ -55,7 +48,7 @@ export class FileWatcher implements Disposable {
addFile(filename: string): boolean {
if (!this.watchedFile.has(filename)) {
try {
this.watchedFile.set(filename, watch(filename, this.trigger));
this.watchedFile.set(filename, watchFile(filename, this.trigger));
} catch (e) {
logError(format(e));
return false;
Expand All @@ -78,7 +71,11 @@ export class FileWatcher implements Disposable {
*/
clear(): void {
for (const w of this.watchedFile.values()) {
w.close();
try {
w.close();
} catch (_e) {
// ignore
}
}
this.watchedFile.clear();
}
Expand All @@ -96,16 +93,3 @@ export class FileWatcher implements Disposable {
}
}
}

function watch(filename: string, callback: (eventType?: EventType, filename?: string) => void): Watcher {
const uri = toFileUri(filename);
if (uri.scheme === 'file') {
return nodeWatch(filename, { persistent: false }, callback);
}

return {
close() {
callback('close', filename);
},
};
}
16 changes: 8 additions & 8 deletions packages/_server/src/utils/fileWatcher.test.mts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { afterEach, describe, expect, test, vi } from 'vitest';

import { addNodeWatchMockImplementation, asNodeWatchMock } from '../test/mock-node-watch.js';
import { addNodeWatchMockImplementation } from '../test/mock-node-watch.js';
import { FileWatcher } from './fileWatcher.mjs';
import { nodeWatch as watch } from './nodeWatch.cjs';
import { watchFile } from './watchFile.mjs';

vi.mock('node-watch');
vi.mock('./watchFile.mjs');

describe('Validate FileWatcher', () => {
afterEach(() => {
asNodeWatchMock(watch).__reset();
vi.resetAllMocks();
});

test('watching files', () => {
const mockWatch = addNodeWatchMockImplementation(vi.mocked(watch));
const mockWatch = addNodeWatchMockImplementation(vi.mocked(watchFile));
const watcher = new FileWatcher();
const listener = vi.fn();
const listener2 = vi.fn();
Expand Down Expand Up @@ -47,9 +47,9 @@ describe('Validate FileWatcher', () => {

expect(watcher.watchedFiles).toEqual([]);

expect(mockWatch).toHaveBeenNthCalledWith(1, 'file1', expect.objectContaining({ persistent: false }), expect.any(Function));
expect(mockWatch).toHaveBeenNthCalledWith(2, 'file2', expect.objectContaining({ persistent: false }), expect.any(Function));
expect(mockWatch).toHaveBeenNthCalledWith(3, 'file3', expect.objectContaining({ persistent: false }), expect.any(Function));
expect(mockWatch).toHaveBeenNthCalledWith(1, 'file1', expect.any(Function));
expect(mockWatch).toHaveBeenNthCalledWith(2, 'file2', expect.any(Function));
expect(mockWatch).toHaveBeenNthCalledWith(3, 'file3', expect.any(Function));
expect(mockWatch).toHaveBeenCalledTimes(3);

expect(listener).toHaveBeenNthCalledWith(1, 'update', 'file1');
Expand Down
5 changes: 0 additions & 5 deletions packages/_server/src/utils/nodeWatch.cts

This file was deleted.

27 changes: 27 additions & 0 deletions packages/_server/src/utils/watchFile.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { FSWatcher } from 'node:fs';
import { watch as fsWatch } from 'node:fs';

import { toFileUri } from '@internal/common-utils/uriHelper';

export type KnownEvents = 'change' | 'error' | 'close';
export type EventType = KnownEvents | string;

export type Listener = (eventType?: EventType, filename?: string) => void;
export type Watcher = Pick<FSWatcher, 'close'>;

export function watchFile(filename: string, callback: (eventType?: EventType, filename?: string | null) => void): Watcher {
const uri = toFileUri(filename);
if (uri.scheme === 'file') {
try {
return fsWatch(filename, { persistent: false }, callback);
} catch (e) {
// Watch is not supported
}
}

return {
close() {
callback('close', filename);
},
};
}
Loading

0 comments on commit fb06f93

Please sign in to comment.