From b01bd93a8ca90e1c2d11a949c120b3beb128a5ff Mon Sep 17 00:00:00 2001 From: Svyat Sobol Date: Wed, 5 Aug 2020 17:50:58 +0300 Subject: [PATCH] refactor: Get rid of openTextDocument in extractDanglingRefs util --- src/features/fsWatcher.ts | 2 +- src/utils/utils.spec.ts | 35 ++++++++++++++++++++++----- src/utils/utils.ts | 51 +++++++++++++++++---------------------- 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/src/features/fsWatcher.ts b/src/features/fsWatcher.ts index 62d1a961..55f48786 100644 --- a/src/features/fsWatcher.ts +++ b/src/features/fsWatcher.ts @@ -36,7 +36,7 @@ const textDocumentChangeListener = async (event: TextDocumentChangeEvent) => { } }; -const textDocumentChangeListenerDebounced = debounce(textDocumentChangeListener, 100); +const textDocumentChangeListenerDebounced = debounce(textDocumentChangeListener, 500); export const activate = (context: ExtensionContext) => { const fileWatcher = workspace.createFileSystemWatcher(`**/*`); diff --git a/src/utils/utils.spec.ts b/src/utils/utils.spec.ts index 279e0819..8c66d72d 100644 --- a/src/utils/utils.spec.ts +++ b/src/utils/utils.spec.ts @@ -1,4 +1,4 @@ -import { window, Selection, workspace, Position, Uri } from 'vscode'; +import { window, Selection, workspace, Range, Position, Uri } from 'vscode'; import fs from 'fs'; import path from 'path'; @@ -1345,10 +1345,8 @@ describe('extractDanglingRefs()', () => { await createFile(`${name0}.md`); expect( - await extractDanglingRefs( - await workspace.openTextDocument({ - language: 'markdown', - content: ` + extractDanglingRefs( + ` [[dangling-ref]] [[dangling-ref]] [[dangling-ref2|Test Label]] @@ -1362,7 +1360,6 @@ describe('extractDanglingRefs()', () => { \`\`\` [[${name0}]] `, - }), ), ).toEqual(['dangling-ref', 'dangling-ref2', 'folder1/long-dangling-ref', 'dangling-ref3']); }); @@ -1406,4 +1403,30 @@ describe('findDanglingRefsByFsPath()', () => { 'dangling-ref3', ]); }); + + it('should find dangling refs from the just edited document', async () => { + const name0 = rndName(); + + await createFile(`${name0}.md`, '[[dangling-ref]]'); + + const doc = await openTextDocument(`${name0}.md`); + + const editor = await window.showTextDocument(doc); + + const refsByFsPath = await findDanglingRefsByFsPath(getWorkspaceCache().markdownUris); + + expect(Object.keys(refsByFsPath)).toHaveLength(1); + expect(Object.values(refsByFsPath)[0]).toEqual(['dangling-ref']); + + await editor.edit((edit) => edit.insert(new Position(1, 0), '[[dangling-ref2]]')); + + const refsByFsPath2 = await findDanglingRefsByFsPath(getWorkspaceCache().markdownUris); + + expect(Object.keys(refsByFsPath2)).toHaveLength(1); + expect(Object.values(refsByFsPath2)[0]).toEqual(['dangling-ref', 'dangling-ref2']); + + await editor.edit((edit) => edit.delete(new Range(new Position(0, 0), new Position(2, 0)))); + + expect(await findDanglingRefsByFsPath(getWorkspaceCache().markdownUris)).toEqual({}); + }); }); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 8cc2a9d9..0f2bdd78 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -92,37 +92,31 @@ export const fsPathToRef = ({ return trimLeadingSlash(ref.includes('.') ? ref.slice(0, ref.lastIndexOf('.')) : ref); }; -export const extractDanglingRefs = async (document: vscode.TextDocument) => { - const matches = matchAll(new RegExp(refPattern, 'gi'), document.getText()); - - if (matches.length) { - const refs = matches.reduce((refs, match) => { - const [, , $2] = match; - const offset = (match.index || 0) + 2; - - const refStart = document.positionAt(offset); - const lineStart = document.lineAt(refStart); - - if ( - isInFencedCodeBlock(document, lineStart.lineNumber) || - isInCodeSpan(document, lineStart.lineNumber, refStart.character) - ) { - return refs; - } +const refRegexp = new RegExp(refPattern, 'gi'); - const { ref } = parseRef($2); +export const extractDanglingRefs = (content: string) => { + const refs: string[] = []; - if (!findUriByRef(getWorkspaceCache().allUris, ref)) { - refs.push(ref); - } + content.split(/\r?\n/g).forEach((lineText, lineNum) => { + for (const match of matchAll(refRegexp, lineText)) { + const [, , reference] = match; + if (reference) { + const offset = (match.index || 0) + 2; - return refs; - }, []); + if (isInFencedCodeBlock(content, lineNum) || isInCodeSpan(content, lineNum, offset)) { + continue; + } - return Array.from(new Set(refs)); - } + const { ref } = parseRef(reference); - return []; + if (!findUriByRef(getWorkspaceCache().allUris, ref)) { + refs.push(ref); + } + } + } + }); + + return Array.from(new Set(refs)); }; export const findDanglingRefsByFsPath = async (uris: vscode.Uri[]) => { @@ -138,9 +132,8 @@ export const findDanglingRefsByFsPath = async (uris: vscode.Uri[]) => { continue; } - const refs = await extractDanglingRefs( - await vscode.workspace.openTextDocument(vscode.Uri.file(fsPath)), - ); + const doc = workspace.textDocuments.find((doc) => doc.uri.fsPath === fsPath); + const refs = extractDanglingRefs(doc ? doc.getText() : fs.readFileSync(fsPath).toString()); if (refs.length) { refsByFsPath[fsPath] = refs;