From 32bf7f38525a1919044e026cf63e8f5319071e15 Mon Sep 17 00:00:00 2001 From: Marcello Urbani Date: Thu, 13 Feb 2025 14:57:26 +0000 Subject: [PATCH 1/4] Add external code formatter support - Fixes #5433 --- package.json | 17 ++++++++- src/commands.ts | 3 ++ src/constants.ts | 12 +++++++ src/normalize.ts | 62 +++++++++++++++++++++++++++++++++ src/views/gitContentProvider.ts | 3 +- 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/normalize.ts diff --git a/package.json b/package.json index 1e8c2fe5..5ccbf446 100644 --- a/package.json +++ b/package.json @@ -408,6 +408,12 @@ }, "category": "Atlassian" }, + { + "command": "atlascode.bb.togglediffNormalize", + "title": "Normalize files", + "icon": "$(law)", + "category": "Atlassian" + }, { "command": "atlascode.debug.bitbucketSites", "title": "Show Bitbucket sites info", @@ -480,6 +486,11 @@ "command": "atlascode.bb.editThisFile", "when": "resourceScheme == atlascode.bbpr && config.atlascode.bitbucket.enabled", "group": "navigation" + }, + { + "command": "atlascode.bb.togglediffNormalize", + "group": "navigation", + "when": "isInDiffEditor && resourceScheme == atlascode.bbpr && atlascode:IsNormalizerEnabled" } ], "editor/context": [ @@ -811,6 +822,10 @@ "command": "atlascode.bb.toggleCommentsVisibility", "when": "false" }, + { + "command": "atlascode.bb.togglediffNormalize", + "when": "false" + }, { "command": "atlascode.jira.showIssueForKey", "when": "atlascode:isJiraAuthenticated && config.atlascode.jira.enabled" @@ -1575,4 +1590,4 @@ "webpack-node-externals": "^3.0.0" }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" -} +} \ No newline at end of file diff --git a/src/commands.ts b/src/commands.ts index db8bd167..9a48a3be 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -24,6 +24,7 @@ import { ConfigSection, ConfigSubSection } from './lib/ipc/models/config'; import { AbstractBaseNode } from './views/nodes/abstractBaseNode'; import { IssueNode } from './views/nodes/issueNode'; import { PipelineNode } from './views/pipelines/PipelinesTree'; +import { toggleDiffNormalize } from './normalize'; export enum Commands { BitbucketSelectContainer = 'atlascode.bb.selectContainer', @@ -51,6 +52,7 @@ export enum Commands { BitbucketMarkTaskComplete = 'atlascode.bb.markTaskComplete', BitbucketMarkTaskIncomplete = 'atlascode.bb.markTaskIncomplete', BitbucketToggleCommentsVisibility = 'atlascode.bb.toggleCommentsVisibility', + BitbucketToggleDiffNormalize = 'atlascode.bb.togglediffNormalize', EditThisFile = 'atlascode.bb.editThisFile', CreateIssue = 'atlascode.jira.createIssue', RefreshJiraExplorer = 'atlascode.jira.refreshExplorer', @@ -199,6 +201,7 @@ export function registerCommands(vscodeContext: ExtensionContext) { diffArgs[0](); commands.executeCommand('vscode.diff', ...diffArgs.slice(1)); }), + commands.registerCommand(Commands.BitbucketToggleDiffNormalize, toggleDiffNormalize), commands.registerCommand(Commands.RerunPipeline, (node: PipelineNode) => { rerunPipeline(node.pipeline); }), diff --git a/src/constants.ts b/src/constants.ts index 339bdce0..cf8cfb62 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -26,3 +26,15 @@ export const AuthInfoVersionKey = 'authInfoVersion'; export const ATLASCODE_TEST_USER_EMAIL = 'axontest2025@gmail.com'; export const ATLASCODE_TEST_HOST = 'axontest2025.atlassian.net'; +export enum CommandContext { + JiraExplorer = 'atlascode:jiraExplorerEnabled', + BitbucketExplorer = 'atlascode:bitbucketExplorerEnabled', + PipelineExplorer = 'atlascode:pipelineExplorerEnabled', + BitbucketIssuesExplorer = 'atlascode:bitbucketIssuesExplorerEnabled', + OpenIssuesTree = 'atlascode:openIssuesTreeEnabled', + AssignedIssuesTree = 'atlascode:assignedIssuesTreeEnabled', + JiraLoginTree = 'atlascode:jiraLoginTreeEnabled', + IsJiraAuthenticated = 'atlascode:isJiraAuthenticated', + IsBBAuthenticated = 'atlascode:isBBAuthenticated', + IsNormalizerEnabled = 'atlascode:IsNormalizerEnabled', +} diff --git a/src/normalize.ts b/src/normalize.ts new file mode 100644 index 00000000..a0b634b1 --- /dev/null +++ b/src/normalize.ts @@ -0,0 +1,62 @@ +import { commands, TabInputTextDiff, TextEditor, Uri, window } from 'vscode'; +import { CommandContext, setCommandContext } from './constants'; + +interface CodeNormalizer { + isRelevant: (u: Uri) => boolean; + normalize: (code: string, uri: Uri) => string; +} + +const normalizers: CodeNormalizer[] = []; + +const registerCodeNormalizer = (normalizer: CodeNormalizer) => { + if (normalizers.indexOf(normalizer) < 0) { + normalizers.push(normalizer); + } + return { + dispose: () => { + const idx = normalizers.indexOf(normalizer); + if (idx >= 0) { + normalizers.splice(idx, 1); + } + }, + }; +}; + +const enableDiffNormalize = (e?: TextEditor) => { + const relevant = e?.document.uri.scheme === 'atlascode.bbpr'; + const active = relevant && normalizers.some((n) => n.isRelevant(e.document.uri)); + setCommandContext(CommandContext.IsNormalizerEnabled, active); +}; + +const toggleNorm = (u: Uri) => { + const q = JSON.parse(u.query); + if (q.normalized) { + delete q.normalized; + } else { + q.normalized = true; + } + return u.with({ query: JSON.stringify(q) }); +}; + +export const toggleDiffNormalize = () => { + try { + const tab = window.tabGroups.activeTabGroup.activeTab; + if (tab?.input instanceof TabInputTextDiff) { + const { original, modified } = tab.input; + return commands.executeCommand('vscode.diff', toggleNorm(original), toggleNorm(modified), tab.label); + } + } catch (error) {} + return; +}; + +export const normalize = (original: string, uri: Uri) => { + for (const n of normalizers) { + if (n.isRelevant(uri)) { + return n.normalize(original, uri); + } + } + return original; +}; + +export const api = { registerCodeNormalizer }; +window.onDidChangeActiveTextEditor(enableDiffNormalize); diff --git a/src/views/gitContentProvider.ts b/src/views/gitContentProvider.ts index b18267b4..da1e9ee9 100644 --- a/src/views/gitContentProvider.ts +++ b/src/views/gitContentProvider.ts @@ -5,6 +5,7 @@ import { BitbucketContext } from '../bitbucket/bbContext'; import { clientForSite } from '../bitbucket/bbUtils'; import { Container } from '../container'; import { PRFileDiffQueryParams } from './pullrequest/diffViewHelper'; +import { normalize } from 'src/normalize'; //This class is responsible for fetching the text of a specific version of a file which may not be on your machine //Everytime the vscode.diff is invoked in this extension, it's using this file to fetch the data for both files. @@ -58,6 +59,6 @@ export class GitContentProvider implements vscode.TextDocumentContentProvider { ); } - return content || ''; + return normalize(content || '', uri); } } From ec374cab3407f5e1926f4418f3e3da1c9d6ea414 Mon Sep 17 00:00:00 2001 From: Marcello Urbani Date: Thu, 13 Feb 2025 14:57:26 +0000 Subject: [PATCH 2/4] return api --- src/extension.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/extension.ts b/src/extension.ts index f29eb7a0..52ddf3be 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -23,6 +23,7 @@ import { registerResources } from './resources'; import { GitExtension } from './typings/git'; import { pid } from 'process'; import { startListening } from './atlclients/negotiate'; +import { api } from './normalize'; const AnalyticDelay = 5000; @@ -86,6 +87,7 @@ export async function activate(context: ExtensionContext) { duration[0] * 1000 + Math.floor(duration[1] / 1000000) } ms`, ); + return api; } async function activateBitbucketFeatures() { From 47592b299db5acf797644217f0deed8287089f97 Mon Sep 17 00:00:00 2001 From: Marcello Urbani Date: Thu, 13 Feb 2025 14:57:26 +0000 Subject: [PATCH 3/4] allow async formatters --- src/normalize.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/normalize.ts b/src/normalize.ts index a0b634b1..8291ed3d 100644 --- a/src/normalize.ts +++ b/src/normalize.ts @@ -3,7 +3,7 @@ import { CommandContext, setCommandContext } from './constants'; interface CodeNormalizer { isRelevant: (u: Uri) => boolean; - normalize: (code: string, uri: Uri) => string; + normalize: (code: string, uri: Uri) => string | Promise; } const normalizers: CodeNormalizer[] = []; From a5769a44ad70cd5611c13702d41099c6dc2eab34 Mon Sep 17 00:00:00 2001 From: Marcello Urbani Date: Thu, 13 Feb 2025 14:57:26 +0000 Subject: [PATCH 4/4] Corrupted diff when a file path includes unusual characters Fixes #111 --- src/normalize.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/normalize.ts b/src/normalize.ts index 8291ed3d..25e8d1d5 100644 --- a/src/normalize.ts +++ b/src/normalize.ts @@ -1,5 +1,6 @@ import { commands, TabInputTextDiff, TextEditor, Uri, window } from 'vscode'; -import { CommandContext, setCommandContext } from './constants'; +import { CommandContext } from './constants'; +import { Container } from './container'; interface CodeNormalizer { isRelevant: (u: Uri) => boolean; @@ -8,6 +9,10 @@ interface CodeNormalizer { const normalizers: CodeNormalizer[] = []; +function setCommandContext(key: CommandContext | string, value: any) { + return commands.executeCommand('setContext', key, value); +} + const registerCodeNormalizer = (normalizer: CodeNormalizer) => { if (normalizers.indexOf(normalizer) < 0) { normalizers.push(normalizer); @@ -43,7 +48,12 @@ export const toggleDiffNormalize = () => { const tab = window.tabGroups.activeTabGroup.activeTab; if (tab?.input instanceof TabInputTextDiff) { const { original, modified } = tab.input; - return commands.executeCommand('vscode.diff', toggleNorm(original), toggleNorm(modified), tab.label); + const controller = Container.bitbucketContext.prCommentController; + const origN = toggleNorm(original); + const modifN = toggleNorm(modified); + controller.provideComments(origN); + controller.provideComments(modifN); + return commands.executeCommand('vscode.diff', origN, modifN, tab.label); } } catch (error) {} return;