From 132dfd000f35dc993eac5a004b2a7d204f1fe748 Mon Sep 17 00:00:00 2001 From: asispts <79239132+asispts@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:14:11 +0000 Subject: [PATCH 1/2] Prevent inline control flow usage --- .oxlintrc.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.oxlintrc.json b/.oxlintrc.json index 73faff3..9849a35 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -22,6 +22,8 @@ "style": "off" // Idiomatic and consistent style rules }, "rules": { + "unicorn/require-post-message-target-origin": "allow", // false-positive + "eslint/curly": "error", "import-js/order": [ "error", { @@ -56,8 +58,7 @@ "variables": "suggestion" } } - ], - "unicorn/require-post-message-target-origin": "allow" // false-positive + ] }, "overrides": [ { From 248d43e3979436c2013605d5ba8d358c6385ec83 Mon Sep 17 00:00:00 2001 From: asispts <79239132+asispts@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:17:17 +0000 Subject: [PATCH 2/2] Fix all violations --- src/avatarManager.ts | 38 +++++++--- src/backend/actions/commit.ts | 8 +- src/backend/queries/commitDetails.ts | 12 ++- src/backend/queries/loadCommits.ts | 24 ++++-- src/backend/utils/promise.ts | 11 ++- src/diffDocProvider.ts | 4 +- src/extension.ts | 8 +- src/extension/messageHandler.ts | 4 +- src/extension/repoManager.ts | 15 +++- src/extension/webviewBridge.ts | 4 +- src/extension/webviewPanel.ts | 8 +- src/extension/workspaceSearch.ts | 8 +- src/extension/workspaceWatcher.ts | 74 ++++++++++++++----- src/extensionState.ts | 8 +- src/l10n.ts | 12 ++- src/repoFileWatcher.ts | 11 ++- src/webview/dropdown.ts | 28 +++++-- src/webview/graph.ts | 42 ++++++++--- src/webview/main.ts | 98 ++++++++++++++++++------- src/webview/utils/date.ts | 4 +- src/webview/utils/dom.ts | 8 +- src/webview/utils/git.ts | 8 +- tests/extension/repoManager.test.ts | 4 +- tests/extension/workspaceSearch.test.ts | 8 +- 24 files changed, 333 insertions(+), 116 deletions(-) diff --git a/src/avatarManager.ts b/src/avatarManager.ts index 4789900..ece65a2 100644 --- a/src/avatarManager.ts +++ b/src/avatarManager.ts @@ -27,7 +27,9 @@ export class AvatarManager { this.avatarStorageFolder = this.extensionState.getAvatarStoragePath(); this.avatars = this.extensionState.getAvatarCache(); this.queue = new AvatarRequestQueue(() => { - if (this.interval !== null) return; + if (this.interval !== null) { + return; + } this.interval = setInterval(() => { // Fetch avatars every 10 seconds this.fetchAvatarsInterval(); @@ -82,7 +84,9 @@ export class AvatarManager { private async fetchAvatarsInterval() { if (this.queue.hasItems()) { let avatarRequest = this.queue.takeItem(); - if (avatarRequest === null) return; // No avatar can be checked at the current time + if (avatarRequest === null) { + return; + } // No avatar can be checked at the current time let remoteSource = await this.getRemoteSource(avatarRequest); // Fetch the remote source of the avatar switch (remoteSource.type) { @@ -173,7 +177,9 @@ export class AvatarManager { avatarRequest.email, commit.author.avatar_url + "&size=54" ); - if (img !== null) this.saveAvatar(avatarRequest.email, img, false); + if (img !== null) { + this.saveAvatar(avatarRequest.email, img, false); + } return; } } else if (res.statusCode === 403) { @@ -239,7 +245,9 @@ export class AvatarManager { if (users.length > 0 && users[0].avatar_url) { // Avatar url found let img = await this.downloadAvatarImage(avatarRequest.email, users[0].avatar_url); - if (img !== null) this.saveAvatar(avatarRequest.email, img, false); + if (img !== null) { + this.saveAvatar(avatarRequest.email, img, false); + } return; } } else if (res.statusCode === 429) { @@ -277,7 +285,9 @@ export class AvatarManager { ); identicon = true; } - if (img !== null) this.saveAvatar(avatarRequest.email, img, identicon); + if (img !== null) { + this.saveAvatar(avatarRequest.email, img, identicon); + } } private async downloadAvatarImage(email: string, imageUrl: string): Promise { @@ -394,7 +404,9 @@ class AvatarRequestQueue { // Add an existing avatar request item, setting the next time the request should be checked and registering if the current attempt failed public addItem(item: AvatarRequestItem, checkAfter: number, failedAttempt: boolean) { item.checkAfter = checkAfter; - if (failedAttempt) item.attempts++; + if (failedAttempt) { + item.attempts++; + } this.insertItem(item); } @@ -405,8 +417,9 @@ class AvatarRequestQueue { // Takes an item from the queue if possible, respecting the value set for checkAfter public takeItem() { - if (this.queue.length > 0 && this.queue[0].checkAfter < new Date().getTime()) + if (this.queue.length > 0 && this.queue[0].checkAfter < new Date().getTime()) { return this.queue.shift()!; + } return null; } @@ -418,11 +431,16 @@ class AvatarRequestQueue { prevLength = this.queue.length; while (l <= r) { c = (l + r) >> 1; - if (this.queue[c].checkAfter <= item.checkAfter) l = c + 1; - else r = c - 1; + if (this.queue[c].checkAfter <= item.checkAfter) { + l = c + 1; + } else { + r = c - 1; + } } this.queue.splice(l, 0, item); - if (prevLength === 0) this.itemsAvailableCallback(); + if (prevLength === 0) { + this.itemsAvailableCallback(); + } } } diff --git a/src/backend/actions/commit.ts b/src/backend/actions/commit.ts index 5504df1..c56f670 100644 --- a/src/backend/actions/commit.ts +++ b/src/backend/actions/commit.ts @@ -14,7 +14,9 @@ export async function cherrypickCommit( input: ActionPayload<"cherrypickCommit"> ): Promise { const args = ["cherry-pick"]; - if (input.parentIndex > 0) args.push("-m", String(input.parentIndex)); + if (input.parentIndex > 0) { + args.push("-m", String(input.parentIndex)); + } args.push(input.commitHash); await git.raw(args); } @@ -24,7 +26,9 @@ export async function revertCommit( input: ActionPayload<"revertCommit"> ): Promise { const args = ["revert", "--no-edit"]; - if (input.parentIndex > 0) args.push("-m", String(input.parentIndex)); + if (input.parentIndex > 0) { + args.push("-m", String(input.parentIndex)); + } args.push(input.commitHash); await git.raw(args); } diff --git a/src/backend/queries/commitDetails.ts b/src/backend/queries/commitDetails.ts index 68695d6..c44d37f 100644 --- a/src/backend/queries/commitDetails.ts +++ b/src/backend/queries/commitDetails.ts @@ -24,7 +24,9 @@ async function fetchCommitInfo( const stdout = await git.raw(["show", "--quiet", commitHash, `--format=${format}`]); const lines = stdout.split(eolRegex); let lastLine = lines.length - 1; - while (lastLine >= 0 && lines[lastLine] === "") lastLine--; + while (lastLine >= 0 && lines[lastLine] === "") { + lastLine--; + } const commitInfo = lines[0].split(gitLogSeparator); return { hash: commitInfo[0], @@ -80,7 +82,9 @@ export async function commitDetails( const fileLookup: { [file: string]: number } = {}; for (let i = 1; i < nameStatusLines.length - 1; i++) { const line = nameStatusLines[i].split("\t"); - if (line.length < 2) break; + if (line.length < 2) { + break; + } const oldFilePath = toPath(line[1]); const newFilePath = toPath(line[line.length - 1]); fileLookup[newFilePath] = details.fileChanges.length; @@ -95,7 +99,9 @@ export async function commitDetails( for (let i = 1; i < numStatLines.length - 1; i++) { const line = numStatLines[i].split("\t"); - if (line.length !== 3) break; + if (line.length !== 3) { + break; + } const fileName = line[2].replace(/(.*){.* => (.*)}/, "$1$2").replace(/.* => (.*)/, "$1"); if (typeof fileLookup[fileName] === "number") { details.fileChanges[fileLookup[fileName]].additions = parseInt(line[0]); diff --git a/src/backend/queries/loadCommits.ts b/src/backend/queries/loadCommits.ts index 9a38393..feedae8 100644 --- a/src/backend/queries/loadCommits.ts +++ b/src/backend/queries/loadCommits.ts @@ -23,14 +23,18 @@ type LoadCommitsInput = { async function getRefs(git: SimpleGit, showRemoteBranches: boolean): Promise { try { const args = ["show-ref"]; - if (!showRemoteBranches) args.push("--heads", "--tags"); + if (!showRemoteBranches) { + args.push("--heads", "--tags"); + } args.push("-d", "--head"); const stdout = await git.raw(args); const refData: GitRefData = { head: null, refs: [] }; const lines = stdout.split(eolRegex); for (let i = 0; i < lines.length - 1; i++) { const parts = lines[i].split(" "); - if (parts.length < 2) continue; + if (parts.length < 2) { + continue; + } const hash = parts.shift()!; const ref = parts.join(" "); if (ref.startsWith("refs/heads/")) { @@ -67,7 +71,9 @@ async function getLog( args.push(branch); } else { args.push("--branches", "--tags"); - if (showRemoteBranches) args.push("--remotes"); + if (showRemoteBranches) { + args.push("--remotes"); + } } try { const stdout = await git.raw(args); @@ -75,7 +81,9 @@ async function getLog( const commits: GitLogEntry[] = []; for (let i = 0; i < lines.length - 1; i++) { const line = lines[i].split(gitLogSeparator); - if (line.length !== 6) break; + if (line.length !== 6) { + break; + } commits.push({ hash: line[0], parentHashes: line[1].split(" "), @@ -94,7 +102,9 @@ async function getLog( async function getUnsavedChanges(git: SimpleGit) { try { const status = await git.status(); - if (status.files.length === 0) return null; + if (status.files.length === 0) { + return null; + } return { branch: status.current ?? "HEAD", changes: status.files.length }; } catch { return null; @@ -115,7 +125,9 @@ export async function loadCommits( let commits = rawCommits; const moreCommitsAvailable = commits.length === maxCommits + 1; - if (moreCommitsAvailable) commits = commits.slice(0, -1); + if (moreCommitsAvailable) { + commits = commits.slice(0, -1); + } if (refData.head !== null) { for (let i = 0; i < commits.length; i++) { diff --git a/src/backend/utils/promise.ts b/src/backend/utils/promise.ts index 15f09e1..e6313db 100644 --- a/src/backend/utils/promise.ts +++ b/src/backend/utils/promise.ts @@ -24,8 +24,11 @@ export function evalPromises( if (!rejected) { results[cur] = result; completed++; - if (nextPromise < data.length) startNext(); - else if (completed === data.length) resolve(results); + if (nextPromise < data.length) { + startNext(); + } else if (completed === data.length) { + resolve(results); + } } }) .catch(() => { @@ -33,7 +36,9 @@ export function evalPromises( rejected = true; }); } - for (let i = 0; i < maxParallel && i < data.length; i++) startNext(); + for (let i = 0; i < maxParallel && i < data.length; i++) { + startNext(); + } } }); } diff --git a/src/diffDocProvider.ts b/src/diffDocProvider.ts index 4bddc0b..77c625e 100644 --- a/src/diffDocProvider.ts +++ b/src/diffDocProvider.ts @@ -29,7 +29,9 @@ export class DiffDocProvider implements vscode.TextDocumentContentProvider { public provideTextDocumentContent(uri: vscode.Uri): string | Thenable { let document = this.docs.get(uri.toString()); - if (document) return document.value; + if (document) { + return document.value; + } let request = decodeDiffDocUri(uri); return this.gitClient() diff --git a/src/extension.ts b/src/extension.ts index cd4afe4..ac4a0e8 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -31,7 +31,9 @@ export function activate(context: vscode.ExtensionContext) { void (async () => { repoManager.removeReposNotInWorkspace(); - if (!(await repoManager.checkReposExist())) repoManager.sendRepos(); + if (!(await repoManager.checkReposExist())) { + repoManager.sendRepos(); + } await repoSearch.searchWorkspaceForRepos(); repoWatcher.startWatching(); })(); @@ -58,7 +60,9 @@ export function activate(context: vscode.ExtensionContext) { ); let bridge!: WebviewBridge; const repoFileWatcher = new RepoFileWatcher(() => { - if (panel.visible) bridge.post({ command: "refresh" }); + if (panel.visible) { + bridge.post({ command: "refresh" }); + } }); bridge = webviewBridgeFactory(panel.webview, repoFileWatcher); avatarManager.registerBridge(bridge.post.bind(bridge)); diff --git a/src/extension/messageHandler.ts b/src/extension/messageHandler.ts index 5a00af5..5cb8578 100644 --- a/src/extension/messageHandler.ts +++ b/src/extension/messageHandler.ts @@ -146,7 +146,9 @@ export function registerMessageHandlers( // --- Infrastructure handlers --- bridge.onMessage("selectRepo", (msg) => { - if (msg.repo === currentRepo) return; + if (msg.repo === currentRepo) { + return; + } currentRepo = msg.repo; gitClient.setRepo(msg.repo); extensionState.setLastActiveRepo(msg.repo); diff --git a/src/extension/repoManager.ts b/src/extension/repoManager.ts index 005cc61..7d4c14c 100644 --- a/src/extension/repoManager.ts +++ b/src/extension/repoManager.ts @@ -33,7 +33,9 @@ export function createRepoManager( const sorted = getRepos(); const numRepos = Object.keys(sorted).length; statusBarItem.setNumRepos(numRepos); - if (viewCallback !== null) viewCallback(sorted, numRepos); + if (viewCallback !== null) { + viewCallback(sorted, numRepos); + } } function removeRepo(repo: string) { @@ -52,7 +54,9 @@ export function createRepoManager( function isDirectoryWithinRepos(path: string) { const repoPaths = Object.keys(repos); for (let i = 0; i < repoPaths.length; i++) { - if (path === repoPaths[i] || path.startsWith(repoPaths[i] + "/")) return true; + if (path === repoPaths[i] || path.startsWith(repoPaths[i] + "/")) { + return true; + } } return false; } @@ -96,8 +100,9 @@ export function createRepoManager( if ( rootsExact.indexOf(repoPaths[i]) === -1 && !rootsFolder.find((x) => repoPaths[i].startsWith(x)) - ) + ) { removeRepo(repoPaths[i]); + } } } @@ -113,7 +118,9 @@ export function createRepoManager( changes = true; } } - if (changes) sendRepos(); + if (changes) { + sendRepos(); + } resolve(changes); } ); diff --git a/src/extension/webviewBridge.ts b/src/extension/webviewBridge.ts index 14f2c46..b7a23f9 100644 --- a/src/extension/webviewBridge.ts +++ b/src/extension/webviewBridge.ts @@ -8,7 +8,9 @@ export function webviewBridgeFactory(webview: vscode.Webview, repoFileWatcher: R webview.onDidReceiveMessage(async (msg: RequestMessage) => { const handler = handlers.get(msg.command); - if (!handler) return; + if (!handler) { + return; + } repoFileWatcher.mute(); await handler(msg); repoFileWatcher.unmute(); diff --git a/src/extension/webviewPanel.ts b/src/extension/webviewPanel.ts index 86ef040..cc92c91 100644 --- a/src/extension/webviewPanel.ts +++ b/src/extension/webviewPanel.ts @@ -68,7 +68,9 @@ export function createWebviewPanel(opts: { repoManager.deregisterViewCallback(); while (disposables.length) { const x = disposables.pop(); - if (x) x.dispose(); + if (x) { + x.dispose(); + } } } @@ -91,7 +93,9 @@ export function createWebviewPanel(opts: { ); repoManager.registerViewCallback((repos: GitRepoSet, numRepos: number) => { - if (!panel.visible) return; + if (!panel.visible) { + return; + } if ((numRepos === 0 && isGraphViewLoaded) || (numRepos > 0 && !isGraphViewLoaded)) { update(); } else { diff --git a/src/extension/workspaceSearch.ts b/src/extension/workspaceSearch.ts index 4364df6..ded0c8c 100644 --- a/src/extension/workspaceSearch.ts +++ b/src/extension/workspaceSearch.ts @@ -28,10 +28,14 @@ export function createRepoSearch(repoManager: RepoManager, config: Config) { if (typeof rootFolders !== "undefined") { for (let i = 0; i < rootFolders.length; i++) { const path = getPathFromUri(rootFolders[i].uri); - if (await searchDirectoryForRepos(path, maxDepthOfRepoSearch)) changes = true; + if (await searchDirectoryForRepos(path, maxDepthOfRepoSearch)) { + changes = true; + } } } - if (changes) repoManager.sendRepos(); + if (changes) { + repoManager.sendRepos(); + } } return { diff --git a/src/extension/workspaceWatcher.ts b/src/extension/workspaceWatcher.ts index d91fb92..d5f4773 100644 --- a/src/extension/workspaceWatcher.ts +++ b/src/extension/workspaceWatcher.ts @@ -29,12 +29,15 @@ export function createRepoWatcher( let changes = false; while ((path = createEventPaths.shift())) { if (await isDirectory(path)) { - if (await repoSearch.searchDirectoryForRepos(path, config.maxDepthOfRepoSearch())) + if (await repoSearch.searchDirectoryForRepos(path, config.maxDepthOfRepoSearch())) { changes = true; + } } } processCreateEventsTimeout = null; - if (changes) repoManager.sendRepos(); + if (changes) { + repoManager.sendRepos(); + } } async function processChangeEvents() { @@ -42,40 +45,66 @@ export function createRepoWatcher( let changes = false; while ((path = changeEventPaths.shift())) { if (!(await doesPathExist(path))) { - if (repoManager.removeReposWithinFolder(path)) changes = true; + if (repoManager.removeReposWithinFolder(path)) { + changes = true; + } } } processChangeEventsTimeout = null; - if (changes) repoManager.sendRepos(); + if (changes) { + repoManager.sendRepos(); + } } async function onWatcherCreate(uri: vscode.Uri) { let path = getPathFromUri(uri); - if (path.indexOf("/.git/") > -1) return; - if (path.endsWith("/.git")) path = path.slice(0, -5); - if (createEventPaths.indexOf(path) > -1) return; + if (path.indexOf("/.git/") > -1) { + return; + } + if (path.endsWith("/.git")) { + path = path.slice(0, -5); + } + if (createEventPaths.indexOf(path) > -1) { + return; + } createEventPaths.push(path); - if (processCreateEventsTimeout !== null) clearTimeout(processCreateEventsTimeout); + if (processCreateEventsTimeout !== null) { + clearTimeout(processCreateEventsTimeout); + } processCreateEventsTimeout = setTimeout(() => processCreateEvents(), debounceDelay); } function onWatcherChange(uri: vscode.Uri) { let path = getPathFromUri(uri); - if (path.indexOf("/.git/") > -1) return; - if (path.endsWith("/.git")) path = path.slice(0, -5); - if (changeEventPaths.indexOf(path) > -1) return; + if (path.indexOf("/.git/") > -1) { + return; + } + if (path.endsWith("/.git")) { + path = path.slice(0, -5); + } + if (changeEventPaths.indexOf(path) > -1) { + return; + } changeEventPaths.push(path); - if (processChangeEventsTimeout !== null) clearTimeout(processChangeEventsTimeout); + if (processChangeEventsTimeout !== null) { + clearTimeout(processChangeEventsTimeout); + } processChangeEventsTimeout = setTimeout(() => processChangeEvents(), debounceDelay); } function onWatcherDelete(uri: vscode.Uri) { let path = getPathFromUri(uri); - if (path.indexOf("/.git/") > -1) return; - if (path.endsWith("/.git")) path = path.slice(0, -5); - if (repoManager.removeReposWithinFolder(path)) repoManager.sendRepos(); + if (path.indexOf("/.git/") > -1) { + return; + } + if (path.endsWith("/.git")) { + path = path.slice(0, -5); + } + if (repoManager.removeReposWithinFolder(path)) { + repoManager.sendRepos(); + } } function startWatchingFolder(path: string) { @@ -97,21 +126,28 @@ export function createRepoWatcher( let changes = false; for (let i = 0; i < e.added.length; i++) { path = getPathFromUri(e.added[i].uri); - if (await repoSearch.searchDirectoryForRepos(path, config.maxDepthOfRepoSearch())) + if (await repoSearch.searchDirectoryForRepos(path, config.maxDepthOfRepoSearch())) { changes = true; + } startWatchingFolder(path); } - if (changes) repoManager.sendRepos(); + if (changes) { + repoManager.sendRepos(); + } } if (e.removed.length > 0) { let changes = false; let path: string; for (let i = 0; i < e.removed.length; i++) { path = getPathFromUri(e.removed[i].uri); - if (repoManager.removeReposWithinFolder(path)) changes = true; + if (repoManager.removeReposWithinFolder(path)) { + changes = true; + } stopWatchingFolder(path); } - if (changes) repoManager.sendRepos(); + if (changes) { + repoManager.sendRepos(); + } } }); diff --git a/src/extensionState.ts b/src/extensionState.ts index d77b990..6a0ffbc 100644 --- a/src/extensionState.ts +++ b/src/extensionState.ts @@ -27,7 +27,9 @@ export class ExtensionState { } else { fs.mkdir(this.globalStoragePath, () => { fs.mkdir(this.globalStoragePath + AVATAR_STORAGE_FOLDER, (mkdirErr) => { - if (!mkdirErr) this.avatarStorageAvailable = true; + if (!mkdirErr) { + this.avatarStorageAvailable = true; + } }); }); } @@ -73,7 +75,9 @@ export class ExtensionState { public clearAvatarCache() { this.globalState.update(AVATAR_CACHE, {}); fs.readdir(this.globalStoragePath + AVATAR_STORAGE_FOLDER, (err, files) => { - if (err) return; + if (err) { + return; + } for (let i = 0; i < files.length; i++) { fs.unlink(this.globalStoragePath + AVATAR_STORAGE_FOLDER + "/" + files[i], () => {}); } diff --git a/src/l10n.ts b/src/l10n.ts index 038e52e..96770f3 100644 --- a/src/l10n.ts +++ b/src/l10n.ts @@ -57,17 +57,23 @@ export function t( result = l10n.t(key, ...(args as Array)); } - if (result !== key) return result; + if (result !== key) { + return result; + } const translationPath = l10n.uri?.fsPath ? path.dirname(l10n.uri.fsPath) : _extensionPath ? path.join(_extensionPath, "l10n") : undefined; - if (!translationPath) return result; + if (!translationPath) { + return result; + } const enTranslations = loadEnglishTranslations(translationPath); const fallback = enTranslations[key]; - if (!fallback) return result; + if (!fallback) { + return result; + } if (args.length === 1 && typeof args[0] === "object") { return interpolate(fallback, args[0]); diff --git a/src/repoFileWatcher.ts b/src/repoFileWatcher.ts index 909f0da..90f8cb6 100644 --- a/src/repoFileWatcher.ts +++ b/src/repoFileWatcher.ts @@ -46,14 +46,19 @@ export class RepoFileWatcher { } private async refresh(uri: vscode.Uri) { - if (this.muted) return; + if (this.muted) { + return; + } if ( !getPathFromUri(uri) .replace(this.repo + "/", "") .match(fileChangeRegex) - ) + ) { return; - if (new Date().getTime() < this.resumeAt) return; + } + if (new Date().getTime() < this.resumeAt) { + return; + } if (this.refreshTimeout !== null) { clearTimeout(this.refreshTimeout); diff --git a/src/webview/dropdown.ts b/src/webview/dropdown.ts index c0fb403..0c388bc 100644 --- a/src/webview/dropdown.ts +++ b/src/webview/dropdown.ts @@ -54,7 +54,9 @@ export class Dropdown { document.addEventListener( "click", (e) => { - if (!e.target) return; + if (!e.target) { + return; + } if (e.target === this.currentValueElem) { this.dropdownVisible = !this.dropdownVisible; if (this.dropdownVisible) { @@ -62,7 +64,9 @@ export class Dropdown { this.filter(); } this.elem.classList.toggle("dropdownOpen"); - if (this.dropdownVisible) this.filterInput.focus(); + if (this.dropdownVisible) { + this.filterInput.focus(); + } } else if (this.dropdownVisible) { if ((e.target).closest(".dropdown") !== this.elem) { this.close(); @@ -90,7 +94,9 @@ export class Dropdown { document.addEventListener( "keyup", (e) => { - if (e.key === "Escape") this.close(); + if (e.key === "Escape") { + this.close(); + } }, true ); @@ -106,12 +112,16 @@ export class Dropdown { } } this.selectedOption = selectedOption; - if (options.length <= 1) this.close(); + if (options.length <= 1) { + this.close(); + } this.render(); } public refresh() { - if (this.options.length > 0) this.render(); + if (this.options.length > 0) { + this.render(); + } } private render() { @@ -148,7 +158,9 @@ export class Dropdown { 130 ) + "px"; this.menuElem.style.cssText = "right:0; overflow-y:auto; max-height:297px;"; - if (this.dropdownVisible) this.filter(); + if (this.dropdownVisible) { + this.filter(); + } } private filter() { @@ -158,7 +170,9 @@ export class Dropdown { for (let i = 0; i < this.options.length; i++) { match = this.options[i].name.toLowerCase().indexOf(val) > -1; (this.optionsElem.children[i]).style.display = match ? "block" : "none"; - if (match) matches = true; + if (match) { + matches = true; + } } this.filterInput.style.display = "block"; this.noResultsElem.style.display = matches ? "none" : "block"; diff --git a/src/webview/graph.ts b/src/webview/graph.ts index 31700f9..be4d42a 100644 --- a/src/webview/graph.ts +++ b/src/webview/graph.ts @@ -19,7 +19,9 @@ class Branch { public addLine(p1: Point, p2: Point, isCommitted: boolean, lockedFirst: boolean) { this.lines.push({ p1: p1, p2: p2, lockedFirst: lockedFirst }); if (isCommitted) { - if (p2.y < this.numUncommitted) this.numUncommitted = p2.y; + if (p2.y < this.numUncommitted) { + this.numUncommitted = p2.y; + } } else { this.numUncommitted++; } @@ -131,11 +133,14 @@ class Branch { } // If the path hasn't been started or the new point belongs to a different path, move to p1 - if (curPath === "" || (i > 0 && (x1 !== lines[i - 1].p2.x || y1 !== lines[i - 1].p2.y))) + if (curPath === "" || (i > 0 && (x1 !== lines[i - 1].p2.x || y1 !== lines[i - 1].p2.y))) { curPath += "M" + x1.toFixed(0) + "," + y1.toFixed(1); + } // If the path hasn't been assigned a colour, assign it - if (curColour === "") curColour = lines[i].isCommitted ? colour : "#808080"; + if (curColour === "") { + curColour = lines[i].isCommitted ? colour : "#808080"; + } if (x1 === x2) { // If the path is vertical, draw a straight line @@ -207,11 +212,15 @@ class Vertex { return this.parents.length > 0; } public getNextParent(): Vertex | null { - if (this.nextParent < this.parents.length) return this.parents[this.nextParent]; + if (this.nextParent < this.parents.length) { + return this.parents[this.nextParent]; + } return null; } public getLastParent(): Vertex | null { - if (this.nextParent < 1) return null; + if (this.nextParent < 1) { + return null; + } return this.parents[this.nextParent - 1]; } public registerParentProcessed() { @@ -249,8 +258,9 @@ class Vertex { public getPointConnectingTo(vertex: VertexOrNull, onBranch: Branch) { for (let i = 0; i < this.connections.length; i++) { - if (this.connections[i].connectsTo === vertex && this.connections[i].onBranch === onBranch) + if (this.connections[i].connectsTo === vertex && this.connections[i].onBranch === onBranch) { return { x: i, y: this.y }; + } } return null; } @@ -271,7 +281,9 @@ class Vertex { this.isCurrent = true; } public draw(svg: SVGElement, config: Config, expandOffset: boolean) { - if (this.onBranch === null) return; + if (this.onBranch === null) { + return; + } let circle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); let colour = this.isCommitted @@ -387,7 +399,9 @@ export class Graph { this.vertices[i].draw(group, this.config, expandedCommit !== null && i > expandedCommit.id); } - if (this.svgGroup !== null) this.svg.removeChild(this.svgGroup); + if (this.svgGroup !== null) { + this.svg.removeChild(this.svgGroup); + } this.svg.appendChild(group); this.svgGroup = group; this.setDimensions(width, this.getHeight(expandedCommit)); @@ -408,7 +422,9 @@ export class Graph { p; for (i = 0; i < this.vertices.length; i++) { p = this.vertices[i].getNextPoint(); - if (p.x > x) x = p.x; + if (p.x > x) { + x = p.x; + } } return x * this.config.grid.x; } @@ -502,7 +518,9 @@ export class Graph { parentVertex.addToBranch(branch, curPoint.x); vertex = parentVertex; parentVertex = vertex.getNextParent(); - if (parentVertexOnBranch) break; + if (parentVertexOnBranch) { + break; + } } } branch.setEnd(i); @@ -513,7 +531,9 @@ export class Graph { private findStart() { for (let i = 0; i < this.vertices.length; i++) { - if (this.vertices[i].getNextParent() !== null || this.vertices[i].isNotOnBranch()) return i; + if (this.vertices[i].getNextParent() !== null || this.vertices[i].isNotOnBranch()) { + return i; + } } return -1; } diff --git a/src/webview/main.ts b/src/webview/main.ts index f48b4c5..3d62622 100644 --- a/src/webview/main.ts +++ b/src/webview/main.ts @@ -247,8 +247,9 @@ class GitGraphView { avatarsNeeded: { [email: string]: string[] } = {}; for (i = 0; i < this.commits.length; i++) { this.commitLookup[this.commits[i].hash] = i; - if (this.expandedCommit !== null && this.expandedCommit.hash === this.commits[i].hash) + if (this.expandedCommit !== null && this.expandedCommit.hash === this.commits[i].hash) { expandedCommitVisible = true; + } if ( this.config.fetchAvatars && typeof this.avatars[this.commits[i].email] !== "string" && @@ -309,7 +310,9 @@ class GitGraphView { hard: boolean, loadedCallback: (changes: boolean, isRepo: boolean) => void ) { - if (this.loadBranchesCallback !== null) return; + if (this.loadBranchesCallback !== null) { + return; + } this.loadBranchesCallback = loadedCallback; sendMessage({ command: "selectRepo", repo: this.currentRepo }); sendMessage({ @@ -319,7 +322,9 @@ class GitGraphView { }); } private requestLoadCommits(hard: boolean, loadedCallback: (changes: boolean) => void) { - if (this.loadCommitsCallback !== null) return; + if (this.loadCommitsCallback !== null) { + return; + } this.loadCommitsCallback = loadedCallback; sendMessage({ command: "loadCommits", @@ -380,7 +385,9 @@ class GitGraphView { } private renderGraph() { let colHeadersElem = document.getElementById("tableColHeaders"); - if (colHeadersElem === null) return; + if (colHeadersElem === null) { + return; + } let headerHeight = colHeadersElem.clientHeight + 1, expandedCommitElem = this.expandedCommit !== null ? document.getElementById("commitDetails") : null; @@ -1024,21 +1031,33 @@ class GitGraphView { let mouseDeltaX = mouseEvent.clientX - mouseX; switch (col) { case 0: - if (columnWidths[0] + mouseDeltaX < 40) mouseDeltaX = -columnWidths[0] + 40; - if (cols[1].clientWidth - mouseDeltaX < 64) mouseDeltaX = cols[1].clientWidth - 64; + if (columnWidths[0] + mouseDeltaX < 40) { + mouseDeltaX = -columnWidths[0] + 40; + } + if (cols[1].clientWidth - mouseDeltaX < 64) { + mouseDeltaX = cols[1].clientWidth - 64; + } columnWidths[0] += mouseDeltaX; cols[0].style.width = columnWidths[0] + "px"; this.graph.limitMaxWidth(columnWidths[0] + 16); break; case 1: - if (cols[1].clientWidth + mouseDeltaX < 64) mouseDeltaX = -cols[1].clientWidth + 64; - if (columnWidths[1] - mouseDeltaX < 40) mouseDeltaX = columnWidths[1] - 40; + if (cols[1].clientWidth + mouseDeltaX < 64) { + mouseDeltaX = -cols[1].clientWidth + 64; + } + if (columnWidths[1] - mouseDeltaX < 40) { + mouseDeltaX = columnWidths[1] - 40; + } columnWidths[1] -= mouseDeltaX; cols[2].style.width = columnWidths[1] + "px"; break; default: - if (columnWidths[col - 1] + mouseDeltaX < 40) mouseDeltaX = -columnWidths[col - 1] + 40; - if (columnWidths[col] - mouseDeltaX < 40) mouseDeltaX = columnWidths[col] - 40; + if (columnWidths[col - 1] + mouseDeltaX < 40) { + mouseDeltaX = -columnWidths[col - 1] + 40; + } + if (columnWidths[col] - mouseDeltaX < 40) { + mouseDeltaX = columnWidths[col] - 40; + } columnWidths[col - 1] += mouseDeltaX; columnWidths[col] -= mouseDeltaX; cols[col].style.width = columnWidths[col - 1] + "px"; @@ -1106,9 +1125,12 @@ class GitGraphView { public hideCommitDetails() { if (this.expandedCommit !== null) { let elem = document.getElementById("commitDetails"); - if (typeof elem === "object" && elem !== null) elem.remove(); - if (typeof this.expandedCommit.srcElem === "object" && this.expandedCommit.srcElem !== null) + if (typeof elem === "object" && elem !== null) { + elem.remove(); + } + if (typeof this.expandedCommit.srcElem === "object" && this.expandedCommit.srcElem !== null) { this.expandedCommit.srcElem.classList.remove("commitDetailsOpen"); + } this.expandedCommit = null; this.saveState(); this.renderGraph(); @@ -1119,10 +1141,13 @@ class GitGraphView { this.expandedCommit === null || this.expandedCommit.srcElem === null || this.expandedCommit.hash !== commitDetails.hash - ) + ) { return; + } let elem = document.getElementById("commitDetails"); - if (typeof elem === "object" && elem !== null) elem.remove(); + if (typeof elem === "object" && elem !== null) { + elem.remove(); + } this.expandedCommit.commitDetails = commitDetails; this.expandedCommit.fileTree = fileTree; @@ -1150,11 +1175,12 @@ class GitGraphView { html += "" + l10n.detailDate + "" + new Date(commitDetails.date * 1000).toString() + "
"; html += "" + l10n.detailCommitter + "" + escapeHtml(commitDetails.committer) + ""; - if (typeof this.avatars[commitDetails.email] === "string") + if (typeof this.avatars[commitDetails.email] === "string") { html += ''; + } html += "

"; html += escapeHtml(commitDetails.body).replace(/\n/g, "
") + ""; html += @@ -1208,7 +1234,9 @@ class GitGraphView { }); addListenerToClass("gitFile", "click", (e) => { let sourceElem = (e.target).closest(".gitFile")!; - if (this.expandedCommit === null || !sourceElem.classList.contains("gitDiffPossible")) return; + if (this.expandedCommit === null || !sourceElem.classList.contains("gitDiffPossible")) { + return; + } sendMessage({ command: "viewDiff", repo: this.currentRepo!, @@ -1326,7 +1354,9 @@ window.addEventListener("message", (event) => { refreshGraphOrDisplayError(msg.status, l10n.unableToRevert); break; case "viewDiff": - if (msg.success === false) showErrorDialog(l10n.unableToViewDiff, null, null); + if (msg.success === false) { + showErrorDialog(l10n.unableToViewDiff, null, null); + } break; } }); @@ -1698,7 +1728,9 @@ function showFormDialog( ? ' placeholder="' + escapeHtml(input.placeholder) + '"' : "") + "/>"; - if (input.type === "text-ref") textRefInput = i; + if (input.type === "text-ref") { + textRefInput = i; + } } html += ""; } @@ -1708,8 +1740,9 @@ function showFormDialog( actionName, l10n.dialogCancel, () => { - if (dialog.className === "active noInput" || dialog.className === "active inputInvalid") + if (dialog.className === "active noInput" || dialog.className === "active inputInvalid") { return; + } let values = []; for (let i = 0; i < inputs.length; i++) { let input = inputs[i], @@ -1731,7 +1764,9 @@ function showFormDialog( if (textRefInput > -1) { let dialogInput = document.getElementById("dialogInput" + textRefInput), dialogAction = document.getElementById("dialogAction")!; - if (dialogInput.value === "") dialog.className = "active noInput"; + if (dialogInput.value === "") { + dialog.className = "active noInput"; + } dialogInput.focus(); dialogInput.addEventListener("keyup", () => { let noInput = dialogInput.value === "", @@ -1784,12 +1819,15 @@ function showDialog( '
' + dismissName + "
"; - if (actionName !== null && actioned !== null) + if (actionName !== null && actioned !== null) { document.getElementById("dialogAction")!.addEventListener("click", actioned); + } document.getElementById("dialogDismiss")!.addEventListener("click", hideDialog); dialogMenuSource = sourceElem; - if (dialogMenuSource !== null) dialogMenuSource.classList.add("dialogActive"); + if (dialogMenuSource !== null) { + dialogMenuSource.classList.add("dialogActive"); + } } function hideDialog() { dialogBacking.className = ""; @@ -1802,17 +1840,25 @@ function hideDialog() { } function hideDialogAndContextMenu() { - if (dialog.classList.contains("active")) hideDialog(); - if (contextMenu.classList.contains("active")) hideContextMenu(); + if (dialog.classList.contains("active")) { + hideDialog(); + } + if (contextMenu.classList.contains("active")) { + hideContextMenu(); + } } /* Global Listeners */ document.addEventListener("keyup", (e) => { - if (e.key === "Escape") hideDialogAndContextMenu(); + if (e.key === "Escape") { + hideDialogAndContextMenu(); + } }); document.addEventListener("click", hideContextMenuListener); document.addEventListener("contextmenu", hideContextMenuListener); document.addEventListener("mouseleave", hideContextMenuListener); function hideContextMenuListener() { - if (contextMenu.classList.contains("active")) hideContextMenu(); + if (contextMenu.classList.contains("active")) { + hideContextMenu(); + } } diff --git a/src/webview/utils/date.ts b/src/webview/utils/date.ts index ff117ed..de4bfc1 100644 --- a/src/webview/utils/date.ts +++ b/src/webview/utils/date.ts @@ -1,6 +1,8 @@ let getMonthCache: string[] | null = null; export function getMonth(): string[] { - if (getMonthCache) return getMonthCache; + if (getMonthCache) { + return getMonthCache; + } getMonthCache = [ l10n.monthJan, l10n.monthFeb, diff --git a/src/webview/utils/dom.ts b/src/webview/utils/dom.ts index ff470ee..79caf64 100644 --- a/src/webview/utils/dom.ts +++ b/src/webview/utils/dom.ts @@ -9,9 +9,13 @@ export function insertAfter(newNode: HTMLElement, referenceNode: HTMLElement) { referenceNode.parentNode!.insertBefore(newNode, referenceNode.nextSibling); } export function blinkHeadRow(headHash: string | null) { - if (!headHash) return; + if (!headHash) { + return; + } const row = document.querySelector(`tr.commit[data-hash="${headHash}"]`) as HTMLElement | null; - if (!row) return; + if (!row) { + return; + } row.classList.add("blinking"); // Matches CSS animation: 320ms * 2 iterations = 640ms, add small buffer window.setTimeout(() => row.classList.remove("blinking"), 700); diff --git a/src/webview/utils/git.ts b/src/webview/utils/git.ts index 8bcd9fa..4e03a22 100644 --- a/src/webview/utils/git.ts +++ b/src/webview/utils/git.ts @@ -2,9 +2,13 @@ export const refInvalid = /^[-/].*|[\\" ><~^:?*[]|\.\.|\/\/|\/\.|@{|[./]$|\.lock export const ELLIPSIS = "…"; export function arraysEqual(a: T[], b: T[], equalElements: (a: T, b: T) => boolean) { - if (a.length !== b.length) return false; + if (a.length !== b.length) { + return false; + } for (let i = 0; i < a.length; i++) { - if (!equalElements(a[i], b[i])) return false; + if (!equalElements(a[i], b[i])) { + return false; + } } return true; } diff --git a/tests/extension/repoManager.test.ts b/tests/extension/repoManager.test.ts index a855efe..9b7dc24 100644 --- a/tests/extension/repoManager.test.ts +++ b/tests/extension/repoManager.test.ts @@ -196,7 +196,9 @@ suite("repoManager", () => { }); teardown(() => { - if (fs.existsSync(repo)) fs.rmSync(repo, { recursive: true, force: true }); + if (fs.existsSync(repo)) { + fs.rmSync(repo, { recursive: true, force: true }); + } }); test("returns false and keeps repos when all repos still exist", async () => { diff --git a/tests/extension/workspaceSearch.test.ts b/tests/extension/workspaceSearch.test.ts index b30f36e..903ccd1 100644 --- a/tests/extension/workspaceSearch.test.ts +++ b/tests/extension/workspaceSearch.test.ts @@ -9,7 +9,9 @@ import { makeRepo } from "@tests/backend/helpers"; function makeStubs(initialRepoPaths: string[] = [], maxDepth = 2, gitPath = "git") { const repos: Record = {}; - for (const r of initialRepoPaths) repos[r] = { columnWidths: null }; + for (const r of initialRepoPaths) { + repos[r] = { columnWidths: null }; + } const added: string[] = []; let sendCount = 0; @@ -54,7 +56,9 @@ suite("workspaceSearch / searchDirectoryForRepos", () => { }); teardown(() => { - if (fs.existsSync(repo)) fs.rmSync(repo, { recursive: true, force: true }); + if (fs.existsSync(repo)) { + fs.rmSync(repo, { recursive: true, force: true }); + } }); test("returns true and adds repo when a git repo is found", async () => {