Ver Fonte

Extension activation cleanup

cte há 11 meses atrás
pai
commit
aa806fdc17

+ 32 - 0
src/activate/handleUri.ts

@@ -0,0 +1,32 @@
+import * as vscode from "vscode"
+
+import { ClineProvider } from "../core/webview/ClineProvider"
+
+export const handleUri = async (uri: vscode.Uri) => {
+	const path = uri.path
+	const query = new URLSearchParams(uri.query.replace(/\+/g, "%2B"))
+	const visibleProvider = ClineProvider.getVisibleInstance()
+
+	if (!visibleProvider) {
+		return
+	}
+
+	switch (path) {
+		case "/glama": {
+			const code = query.get("code")
+			if (code) {
+				await visibleProvider.handleGlamaCallback(code)
+			}
+			break
+		}
+		case "/openrouter": {
+			const code = query.get("code")
+			if (code) {
+				await visibleProvider.handleOpenRouterCallback(code)
+			}
+			break
+		}
+		default:
+			break
+	}
+}

+ 3 - 0
src/activate/index.ts

@@ -0,0 +1,3 @@
+export { handleUri } from "./handleUri"
+export { registerCommands } from "./registerCommands"
+export { registerCodeActions } from "./registerCodeActions"

+ 91 - 0
src/activate/registerCodeActions.ts

@@ -0,0 +1,91 @@
+import * as vscode from "vscode"
+
+import { ACTION_NAMES, COMMAND_IDS } from "../core/CodeActionProvider"
+import { EditorUtils } from "../core/EditorUtils"
+import { ClineProvider } from "../core/webview/ClineProvider"
+
+export const registerCodeActions = (context: vscode.ExtensionContext) => {
+	registerCodeActionPair(
+		context,
+		COMMAND_IDS.EXPLAIN,
+		"EXPLAIN",
+		"What would you like Roo to explain?",
+		"E.g. How does the error handling work?",
+	)
+
+	registerCodeActionPair(
+		context,
+		COMMAND_IDS.FIX,
+		"FIX",
+		"What would you like Roo to fix?",
+		"E.g. Maintain backward compatibility",
+	)
+
+	registerCodeActionPair(
+		context,
+		COMMAND_IDS.IMPROVE,
+		"IMPROVE",
+		"What would you like Roo to improve?",
+		"E.g. Focus on performance optimization",
+	)
+
+	registerCodeAction(context, COMMAND_IDS.ADD_TO_CONTEXT, "ADD_TO_CONTEXT")
+}
+
+const registerCodeAction = (
+	context: vscode.ExtensionContext,
+	command: string,
+	promptType: keyof typeof ACTION_NAMES,
+	inputPrompt?: string,
+	inputPlaceholder?: string,
+) => {
+	let userInput: string | undefined
+
+	context.subscriptions.push(
+		vscode.commands.registerCommand(command, async (...args: any[]) => {
+			if (inputPrompt) {
+				userInput = await vscode.window.showInputBox({
+					prompt: inputPrompt,
+					placeHolder: inputPlaceholder,
+				})
+			}
+
+			// Handle both code action and direct command cases.
+			let filePath: string
+			let selectedText: string
+			let diagnostics: any[] | undefined
+
+			if (args.length > 1) {
+				// Called from code action.
+				;[filePath, selectedText, diagnostics] = args
+			} else {
+				// Called directly from command palette.
+				const context = EditorUtils.getEditorContext()
+				if (!context) return
+				;({ filePath, selectedText, diagnostics } = context)
+			}
+
+			const params = {
+				...{ filePath, selectedText },
+				...(diagnostics ? { diagnostics } : {}),
+				...(userInput ? { userInput } : {}),
+			}
+
+			await ClineProvider.handleCodeAction(command, promptType, params)
+		}),
+	)
+}
+
+const registerCodeActionPair = (
+	context: vscode.ExtensionContext,
+	baseCommand: string,
+	promptType: keyof typeof ACTION_NAMES,
+	inputPrompt?: string,
+	inputPlaceholder?: string,
+) => {
+	// Register new task version.
+	registerCodeAction(context, baseCommand, promptType, inputPrompt, inputPlaceholder)
+
+	// Register current task version.
+	registerCodeAction(context, `${baseCommand}InCurrentTask`, promptType, inputPrompt, inputPlaceholder)
+}

+ 83 - 0
src/activate/registerCommands.ts

@@ -0,0 +1,83 @@
+import * as vscode from "vscode"
+import delay from "delay"
+
+import { ClineProvider } from "../core/webview/ClineProvider"
+
+export type RegisterCommandOptions = {
+	context: vscode.ExtensionContext
+	outputChannel: vscode.OutputChannel
+	provider: ClineProvider
+}
+
+export const registerCommands = (options: RegisterCommandOptions) => {
+	const { context, outputChannel } = options
+
+	for (const [command, callback] of Object.entries(getCommandsMap(options))) {
+		context.subscriptions.push(vscode.commands.registerCommand(command, callback))
+	}
+}
+
+const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOptions) => {
+	return {
+		"roo-cline.plusButtonClicked": async () => {
+			await provider.clearTask()
+			await provider.postStateToWebview()
+			await provider.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
+		},
+		"roo-cline.mcpButtonClicked": () => {
+			provider.postMessageToWebview({ type: "action", action: "mcpButtonClicked" })
+		},
+		"roo-cline.promptsButtonClicked": () => {
+			provider.postMessageToWebview({ type: "action", action: "promptsButtonClicked" })
+		},
+		"roo-cline.popoutButtonClicked": () => openClineInNewTab({ context, outputChannel }),
+		"roo-cline.openInNewTab": () => openClineInNewTab({ context, outputChannel }),
+		"roo-cline.settingsButtonClicked": () => {
+			provider.postMessageToWebview({ type: "action", action: "settingsButtonClicked" })
+		},
+		"roo-cline.historyButtonClicked": () => {
+			provider.postMessageToWebview({ type: "action", action: "historyButtonClicked" })
+		},
+	}
+}
+
+const openClineInNewTab = async ({ context, outputChannel }: Omit<RegisterCommandOptions, "provider">) => {
+	outputChannel.appendLine("Opening Roo Code in new tab")
+
+	// (This example uses webviewProvider activation event which is necessary to
+	// deserialize cached webview, but since we use retainContextWhenHidden, we
+	// don't need to use that event).
+	// https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts
+	const tabProvider = new ClineProvider(context, outputChannel)
+	// const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined
+	const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0))
+
+	// Check if there are any visible text editors, otherwise open a new group
+	// to the right.
+	const hasVisibleEditors = vscode.window.visibleTextEditors.length > 0
+
+	if (!hasVisibleEditors) {
+		await vscode.commands.executeCommand("workbench.action.newGroupRight")
+	}
+
+	const targetCol = hasVisibleEditors ? Math.max(lastCol + 1, 1) : vscode.ViewColumn.Two
+
+	const panel = vscode.window.createWebviewPanel(ClineProvider.tabPanelId, "Roo Code", targetCol, {
+		enableScripts: true,
+		retainContextWhenHidden: true,
+		localResourceRoots: [context.extensionUri],
+	})
+
+	// TODO: use better svg icon with light and dark variants (see
+	// https://stackoverflow.com/questions/58365687/vscode-extension-iconpath).
+	panel.iconPath = {
+		light: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "rocket.png"),
+		dark: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "rocket.png"),
+	}
+
+	tabProvider.resolveWebviewView(panel)
+
+	// Lock the editor group so clicking on files doesn't open them over the panel
+	await delay(100)
+	await vscode.commands.executeCommand("workbench.action.lockEditorGroup")
+}

+ 1 - 1
src/core/CodeActionProvider.ts

@@ -9,7 +9,7 @@ export const ACTION_NAMES = {
 	ADD_TO_CONTEXT: "Roo Code: Add to Context",
 } as const
 
-const COMMAND_IDS = {
+export const COMMAND_IDS = {
 	EXPLAIN: "roo-cline.explainCode",
 	FIX: "roo-cline.fixCode",
 	IMPROVE: "roo-cline.improveCode",

+ 37 - 212
src/extension.ts

@@ -1,37 +1,33 @@
-// The module 'vscode' contains the VS Code extensibility API
-// Import the module and reference it with the alias vscode in your code below
-import delay from "delay"
 import * as vscode from "vscode"
+
 import { ClineProvider } from "./core/webview/ClineProvider"
 import { createClineAPI } from "./exports"
-import "./utils/path" // necessary to have access to String.prototype.toPosix
-import { ACTION_NAMES, CodeActionProvider } from "./core/CodeActionProvider"
-import { EditorUtils } from "./core/EditorUtils"
+import "./utils/path" // Necessary to have access to String.prototype.toPosix.
+import { CodeActionProvider } from "./core/CodeActionProvider"
 import { DIFF_VIEW_URI_SCHEME } from "./integrations/editor/DiffViewProvider"
+import { handleUri, registerCommands, registerCodeActions } from "./activate"
 
-/*
-Built using https://github.com/microsoft/vscode-webview-ui-toolkit
-
-Inspired by
-https://github.com/microsoft/vscode-webview-ui-toolkit-samples/tree/main/default/weather-webview
-https://github.com/microsoft/vscode-webview-ui-toolkit-samples/tree/main/frameworks/hello-world-react-cra
-
-*/
+/**
+ * Built using https://github.com/microsoft/vscode-webview-ui-toolkit
+ *
+ * Inspired by:
+ *  - https://github.com/microsoft/vscode-webview-ui-toolkit-samples/tree/main/default/weather-webview
+ *  - https://github.com/microsoft/vscode-webview-ui-toolkit-samples/tree/main/frameworks/hello-world-react-cra
+ */
 
 let outputChannel: vscode.OutputChannel
 
-// This method is called when your extension is activated
-// Your extension is activated the very first time the command is executed
+// This method is called when your extension is activated.
+// Your extension is activated the very first time the command is executed.
 export function activate(context: vscode.ExtensionContext) {
 	outputChannel = vscode.window.createOutputChannel("Roo-Code")
 	context.subscriptions.push(outputChannel)
-
 	outputChannel.appendLine("Roo-Code extension activated")
 
-	// Get default commands from configuration
+	// Get default commands from configuration.
 	const defaultCommands = vscode.workspace.getConfiguration("roo-cline").get<string[]>("allowedCommands") || []
 
-	// Initialize global state if not already set
+	// Initialize global state if not already set.
 	if (!context.globalState.get("allowedCommands")) {
 		context.globalState.update("allowedCommands", defaultCommands)
 	}
@@ -44,220 +40,49 @@ export function activate(context: vscode.ExtensionContext) {
 		}),
 	)
 
-	context.subscriptions.push(
-		vscode.commands.registerCommand("roo-cline.plusButtonClicked", async () => {
-			outputChannel.appendLine("Plus button Clicked")
-			await sidebarProvider.clearTask()
-			await sidebarProvider.postStateToWebview()
-			await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
-		}),
-	)
-
-	context.subscriptions.push(
-		vscode.commands.registerCommand("roo-cline.mcpButtonClicked", () => {
-			sidebarProvider.postMessageToWebview({ type: "action", action: "mcpButtonClicked" })
-		}),
-	)
-
-	context.subscriptions.push(
-		vscode.commands.registerCommand("roo-cline.promptsButtonClicked", () => {
-			sidebarProvider.postMessageToWebview({ type: "action", action: "promptsButtonClicked" })
-		}),
-	)
-
-	const openClineInNewTab = async () => {
-		outputChannel.appendLine("Opening Roo Code in new tab")
-		// (this example uses webviewProvider activation event which is necessary to deserialize cached webview, but since we use retainContextWhenHidden, we don't need to use that event)
-		// https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts
-		const tabProvider = new ClineProvider(context, outputChannel)
-		//const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined
-		const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0))
-
-		// Check if there are any visible text editors, otherwise open a new group to the right
-		const hasVisibleEditors = vscode.window.visibleTextEditors.length > 0
-		if (!hasVisibleEditors) {
-			await vscode.commands.executeCommand("workbench.action.newGroupRight")
-		}
-		const targetCol = hasVisibleEditors ? Math.max(lastCol + 1, 1) : vscode.ViewColumn.Two
-
-		const panel = vscode.window.createWebviewPanel(ClineProvider.tabPanelId, "Roo Code", targetCol, {
-			enableScripts: true,
-			retainContextWhenHidden: true,
-			localResourceRoots: [context.extensionUri],
-		})
-		// TODO: use better svg icon with light and dark variants (see https://stackoverflow.com/questions/58365687/vscode-extension-iconpath)
-
-		panel.iconPath = {
-			light: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "rocket.png"),
-			dark: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "rocket.png"),
-		}
-		tabProvider.resolveWebviewView(panel)
-
-		// Lock the editor group so clicking on files doesn't open them over the panel
-		await delay(100)
-		await vscode.commands.executeCommand("workbench.action.lockEditorGroup")
-	}
-
-	context.subscriptions.push(vscode.commands.registerCommand("roo-cline.popoutButtonClicked", openClineInNewTab))
-	context.subscriptions.push(vscode.commands.registerCommand("roo-cline.openInNewTab", openClineInNewTab))
-
-	context.subscriptions.push(
-		vscode.commands.registerCommand("roo-cline.settingsButtonClicked", () => {
-			//vscode.window.showInformationMessage(message)
-			sidebarProvider.postMessageToWebview({ type: "action", action: "settingsButtonClicked" })
-		}),
-	)
-
-	context.subscriptions.push(
-		vscode.commands.registerCommand("roo-cline.historyButtonClicked", () => {
-			sidebarProvider.postMessageToWebview({ type: "action", action: "historyButtonClicked" })
-		}),
-	)
-
-	/*
-	We use the text document content provider API to show the left side for diff view by creating a virtual document for the original content. This makes it readonly so users know to edit the right side if they want to keep their changes.
-
-	- This API allows you to create readonly documents in VSCode from arbitrary sources, and works by claiming an uri-scheme for which your provider then returns text contents. The scheme must be provided when registering a provider and cannot change afterwards.
-	- Note how the provider doesn't create uris for virtual documents - its role is to provide contents given such an uri. In return, content providers are wired into the open document logic so that providers are always considered.
-	https://code.visualstudio.com/api/extension-guides/virtual-documents
-	*/
+	registerCommands({ context, outputChannel, provider: sidebarProvider })
+
+	/**
+	 * We use the text document content provider API to show the left side for diff
+	 * view by creating a virtual document for the original content. This makes it
+	 * readonly so users know to edit the right side if they want to keep their changes.
+	 *
+	 * This API allows you to create readonly documents in VSCode from arbitrary
+	 * sources, and works by claiming an uri-scheme for which your provider then
+	 * returns text contents. The scheme must be provided when registering a
+	 * provider and cannot change afterwards.
+	 *
+	 * Note how the provider doesn't create uris for virtual documents - its role
+	 * is to provide contents given such an uri. In return, content providers are
+	 * wired into the open document logic so that providers are always considered.
+	 *
+	 * https://code.visualstudio.com/api/extension-guides/virtual-documents
+	 */
 	const diffContentProvider = new (class implements vscode.TextDocumentContentProvider {
 		provideTextDocumentContent(uri: vscode.Uri): string {
 			return Buffer.from(uri.query, "base64").toString("utf-8")
 		}
 	})()
+
 	context.subscriptions.push(
 		vscode.workspace.registerTextDocumentContentProvider(DIFF_VIEW_URI_SCHEME, diffContentProvider),
 	)
 
-	// URI Handler
-	const handleUri = async (uri: vscode.Uri) => {
-		const path = uri.path
-		const query = new URLSearchParams(uri.query.replace(/\+/g, "%2B"))
-		const visibleProvider = ClineProvider.getVisibleInstance()
-		if (!visibleProvider) {
-			return
-		}
-		switch (path) {
-			case "/glama": {
-				const code = query.get("code")
-				if (code) {
-					await visibleProvider.handleGlamaCallback(code)
-				}
-				break
-			}
-
-			case "/openrouter": {
-				const code = query.get("code")
-				if (code) {
-					await visibleProvider.handleOpenRouterCallback(code)
-				}
-				break
-			}
-			default:
-				break
-		}
-	}
 	context.subscriptions.push(vscode.window.registerUriHandler({ handleUri }))
 
-	// Register code actions provider
+	// Register code actions provider.
 	context.subscriptions.push(
 		vscode.languages.registerCodeActionsProvider({ pattern: "**/*" }, new CodeActionProvider(), {
 			providedCodeActionKinds: CodeActionProvider.providedCodeActionKinds,
 		}),
 	)
 
-	// Helper function to handle code actions
-	const registerCodeAction = (
-		context: vscode.ExtensionContext,
-		command: string,
-		promptType: keyof typeof ACTION_NAMES,
-		inputPrompt?: string,
-		inputPlaceholder?: string,
-	) => {
-		let userInput: string | undefined
-
-		context.subscriptions.push(
-			vscode.commands.registerCommand(command, async (...args: any[]) => {
-				if (inputPrompt) {
-					userInput = await vscode.window.showInputBox({
-						prompt: inputPrompt,
-						placeHolder: inputPlaceholder,
-					})
-				}
-
-				// Handle both code action and direct command cases
-				let filePath: string
-				let selectedText: string
-				let diagnostics: any[] | undefined
-
-				if (args.length > 1) {
-					// Called from code action
-					;[filePath, selectedText, diagnostics] = args
-				} else {
-					// Called directly from command palette
-					const context = EditorUtils.getEditorContext()
-					if (!context) return
-					;({ filePath, selectedText, diagnostics } = context)
-				}
-
-				const params = {
-					...{ filePath, selectedText },
-					...(diagnostics ? { diagnostics } : {}),
-					...(userInput ? { userInput } : {}),
-				}
-
-				await ClineProvider.handleCodeAction(command, promptType, params)
-			}),
-		)
-	}
-
-	// Helper function to register both versions of a code action
-	const registerCodeActionPair = (
-		context: vscode.ExtensionContext,
-		baseCommand: string,
-		promptType: keyof typeof ACTION_NAMES,
-		inputPrompt?: string,
-		inputPlaceholder?: string,
-	) => {
-		// Register new task version
-		registerCodeAction(context, baseCommand, promptType, inputPrompt, inputPlaceholder)
-
-		// Register current task version
-		registerCodeAction(context, `${baseCommand}InCurrentTask`, promptType, inputPrompt, inputPlaceholder)
-	}
-
-	// Register code action commands
-	registerCodeActionPair(
-		context,
-		"roo-cline.explainCode",
-		"EXPLAIN",
-		"What would you like Roo to explain?",
-		"E.g. How does the error handling work?",
-	)
-
-	registerCodeActionPair(
-		context,
-		"roo-cline.fixCode",
-		"FIX",
-		"What would you like Roo to fix?",
-		"E.g. Maintain backward compatibility",
-	)
-
-	registerCodeActionPair(
-		context,
-		"roo-cline.improveCode",
-		"IMPROVE",
-		"What would you like Roo to improve?",
-		"E.g. Focus on performance optimization",
-	)
-
-	registerCodeAction(context, "roo-cline.addToContext", "ADD_TO_CONTEXT")
+	registerCodeActions(context)
 
 	return createClineAPI(outputChannel, sidebarProvider)
 }
 
-// This method is called when your extension is deactivated
+// This method is called when your extension is deactivated.
 export function deactivate() {
 	outputChannel.appendLine("Roo-Code extension deactivated")
 }