Cline源碼分析

Cline源碼分析 --- vscode插件開發與cline的界面系統

  • vscode插件開發基礎知識
    • 開發基礎?
    • 核心概念
    • 核心API
    • 調試與發布
      • 調試
    • 學習路線
    • React開發界面
    • 前端代碼分析
      • package.json
      • view/title(視圖標題欄菜單)?
      • editor/title(編輯器標題欄菜單)?
      • editor/context(編輯器右鍵菜單)?
      • terminal/context(終端右鍵菜單)?
      • extension.ts
        • 視圖加載機制:
        • 注冊菜單點擊對應的命令

vscode插件開發基礎知識

開發基礎?

?語言要求?

主語言:TypeScript(推薦)或 JavaScript
配置文件:JSON(package.json)
?必備工具?

Node.js(≥ 16.x)
VS Code(建議最新版)
腳手架工具:

npm install -g yo generator-code

?## 項目初始化

?創建項目?

yo code

選擇插件類型(例如:“New Extension (TypeScript)”)

?項目結構?
├── .vscode # VS Code 調試配置
├── src
│ └── extension.ts # 插件入口文件
├── package.json # 插件清單文件
├── tsconfig.json # TypeScript 配置
└── node_modules

核心概念

  1. ?激活事件(Activation Events)?
    定義插件何時被加載
"activationEvents": ["onCommand:myExtension.helloWorld", // 命令觸發加載"onLanguage:javascript",            // 打開JS文件時加載"*"                                  // 啟動即加載(不推薦)
]
  1. ?貢獻點(Contribution Points)?
    通過 package.json 擴展 VS Code 功能:
"contributes": {"commands": [{"command": "myExtension.helloWorld","title": "Hello World"}],"menus": {"editor/context": [{"command": "myExtension.helloWorld","group": "navigation"}]}
}
  1. ?命令(Commands)?
    注冊命令:
vscode.commands.registerCommand('myExtension.helloWorld', () => {vscode.window.showInformationMessage('Hello World!');
});
  1. ?生命周期?
    ?激活?:activate() 函數
    ?銷毀?:返回 deactivate() 清理資源
export function activate(context: vscode.ExtensionContext) {// 初始化代碼
}

核心API

?模塊? ?功能? ?常用方法?
vscode.window 界面交互 showInformationMessage createWebview
vscode.workspace 文件/編輯器操作 openTextDocument onDidChangeTextDocument
vscode.languages 語言支持 registerHoverProvider registerCompletionItemProvider
vscode.debug 調試相關 startDebugging onDidTerminateDebugSession
?

調試與發布

調試

按 F5 啟動調試實例
使用 VS Code 的調試斷點
?發布?

npm install -g vsce
vsce package  # 生成 .vsix 文件
vsce publish  # 發布到市場

學習路線

?官方資源?

插件API文檔
示例代碼庫
?實戰建議?

從修改官方示例開始
優先使用 TypeScript 獲得更好類型提示
善用 Ctrl+Space 查看 API 自動補全

React開發界面

前端代碼分析

package.json

		"viewsContainers": {"activitybar": [{"id": "claude-dev-ActivityBar","title": "Cline","icon": "assets/icons/icon.svg"}]},"views": {"claude-dev-ActivityBar": [{"type": "webview","id": "claude-dev.SidebarProvider","name": ""}]}

定義插件的視圖id:claude-dev-ActivityBar,以及插件顯示圖標。插件視圖提供者ID:claude-dev.SidebarProvider
菜單注冊的代碼如下:

"menus": {"view/title": [{"command": "cline.plusButtonClicked","group": "navigation@1","when": "view == claude-dev.SidebarProvider"},{"command": "cline.mcpButtonClicked","group": "navigation@2","when": "view == claude-dev.SidebarProvider"},{"command": "cline.historyButtonClicked","group": "navigation@3","when": "view == claude-dev.SidebarProvider"},{"command": "cline.popoutButtonClicked","group": "navigation@4","when": "view == claude-dev.SidebarProvider"},{"command": "cline.accountButtonClicked","group": "navigation@5","when": "view == claude-dev.SidebarProvider"},{"command": "cline.settingsButtonClicked","group": "navigation@6","when": "view == claude-dev.SidebarProvider"}],"editor/title": [{"command": "cline.plusButtonClicked","group": "navigation@1","when": "activeWebviewPanelId == claude-dev.TabPanelProvider"},{"command": "cline.mcpButtonClicked","group": "navigation@2","when": "activeWebviewPanelId == claude-dev.TabPanelProvider"},{"command": "cline.historyButtonClicked","group": "navigation@3","when": "activeWebviewPanelId == claude-dev.TabPanelProvider"},{"command": "cline.popoutButtonClicked","group": "navigation@4","when": "activeWebviewPanelId == claude-dev.TabPanelProvider"},{"command": "cline.accountButtonClicked","group": "navigation@5","when": "activeWebviewPanelId == claude-dev.TabPanelProvider"},{"command": "cline.settingsButtonClicked","group": "navigation@6","when": "activeWebviewPanelId == claude-dev.TabPanelProvider"}],"editor/context": [{"command": "cline.addToChat","group": "navigation","when": "editorHasSelection"}],"terminal/context": [{"command": "cline.addTerminalOutputToChat","group": "navigation"}]}

view/title(視圖標題欄菜單)?

?功能定義?
控制自定義視圖(如側邊欄、面板)標題欄的按鈕或下拉菜單,常用于擴展視圖操作能力。

editor/title(編輯器標題欄菜單)?

?功能定義?
控制編輯器標簽頁(Tab)右側的操作區域,用于擴展文件相關操作。

editor/context(編輯器右鍵菜單)?

?功能定義?
控制代碼編輯區域的右鍵上下文菜單項,常用于代碼操作、格式化等場景。

terminal/context(終端右鍵菜單)?

?功能定義?
控制集成終端(Terminal)的右鍵上下文菜單項,適用于終端操作增強。

從代碼來看主要是view/title和editor/title里面分別定義了當顯示為view和activeWebviewPanelId 是的6個菜單,也就是Cline的主菜單項目:新建task,mcp服務器,任務歷史,在編輯器打開,Cline賬號和設置面板。
以下是 activeWebviewPanelId 與 view 兩個上下文條件的核心區別解析:

?一、作用區域差異?
?條件表達式?	?作用區域?	?典型應用場景?
"when": "view == claude-dev.SidebarProvider"	?側邊欄視圖容器?	控制側邊欄自定義視圖的顯示邏輯(如工具欄按鈕)?
"when": "activeWebviewPanelId == claude-dev.TabPanelProvider"	?編輯器主區域?	控制 Webview 面板的激活狀態(如標簽頁操作)?
?二、上下文鍵含義?
?view?對應通過 package.json 的 contributes.views 注冊的側邊欄視圖容器 ID?17
示例配置:
json
Copy Code
"contributes": {"views": {"explorer": [{"id": "claude-dev.SidebarProvider","name": "Claude 側邊欄"}]}
}
?activeWebviewPanelId?對應通過代碼動態創建的 Webview 面板 ID(vscode.window.createWebviewPanel 的 viewType 參數)?58
示例代碼:
typescript
Copy Code
vscode.window.createWebviewPanel('claude-dev.TabPanelProvider', // 此處定義ID'Claude 面板',vscode.ViewColumn.One
);
?三、觸發場景示例?
1. ?側邊欄視圖 (view)?
json
Copy Code
"menus": {"view/title": [{"command": "claude-dev.refreshSidebar","when": "view == claude-dev.SidebarProvider"}]
}
僅在側邊欄的「Claude 側邊欄」視圖中顯示「刷新」按鈕?17
2. ?Webview 面板 (activeWebviewPanelId)?
json
Copy Code
"commands": [{"command": "claude-dev.closePanel","title": "關閉面板","enablement": "activeWebviewPanelId == claude-dev.TabPanelProvider"
}]
當用戶聚焦在 claude-dev.TabPanelProvider 面板時,允許執行關閉命令?58
?四、關鍵注意事項?
?視圖類型限制?view 僅適用于側邊欄/面板等靜態視圖容器
activeWebviewPanelId 專用于動態創建的 Webview 交互面板?58
?生命周期差異?側邊欄視圖 (view) 在插件激活期間持續存在
Webview 面板 (activeWebviewPanelId) 隨用戶打開/關閉動態變化?

extension.ts

這個是插件的入口文件,

方法export function activate(context: vscode.ExtensionContext)定義了插件加載時執行的代碼。

視圖加載機制:
	context.subscriptions.push(vscode.window.registerWebviewViewProvider(ClineProvider.sideBarId, sidebarProvider, {webviewOptions: { retainContextWhenHidden: true },}),)
以上代碼是注冊試圖提供者的代碼,下面是對應vscode機制的解析:
?一、代碼執行階段的作用?
typescript
Copy Code
context.subscriptions.push(vscode.window.registerWebviewViewProvider(ClineProvider.sideBarId, sidebarProvider, { webviewOptions: { retainContextWhenHidden: true } })
)
?1. 注冊階段?
操作	結果
注冊視圖類型	將 ClineProvider.sideBarId 加入 VS Code 的可用視圖列表
配置持久化選項	retainContextWhenHidden 控制視圖隱藏時是否保持 Webview 實例
?未創建 Webview 實例?	此時僅注冊元信息,不分配任何 DOM 資源
?2. 觸發加載的條件?
場景	加載時機
用戶手動激活視圖	點擊側邊欄對應圖標時創建 Webview
插件主動調用 reveal()	通過 vscode.commands.executeCommand('workbench.view.extension.viewId')
VS Code 恢復上次會話狀態	當用戶重新打開包含該視圖的工作區時自動加載(需配置 "visible": true)
?二、生命周期控制參數解析?
?retainContextWhenHidden 的作用?
typescript
Copy Code
{ retainContextWhenHidden: true }
值	內存管理策略	適用場景
true	視圖隱藏時保留 Webview 的 DOM 狀態,再次顯示時無需重新初始化	包含復雜表單/圖表的交互式視圖
false	視圖隱藏后立即銷毀 Webview 實例,再次顯示時觸發 resolveWebviewView 重新創建	簡單靜態內容視圖
?三、視圖加載流程驗證方法?
?1. 調試技巧?
typescript
Copy Code
// 在 WebviewViewProvider 實現中增加日志
class SidebarProvider implements vscode.WebviewViewProvider {resolveWebviewView(webviewView: vscode.WebviewView) {console.log('Webview 實例化:', Date.now()); // 首次加載時觸發}
}
?2. 行為觀察?
執行注冊代碼后檢查 VS Code 內存占用(無明顯增長)
首次點擊側邊欄圖標時觀察到:
內存占用上升
開發者工具中可見新 Webview 的 DOM 元素
?四、強制預加載的實現方式?
typescript
Copy Code
// 注冊后立即嘗試顯示視圖(不推薦)
setTimeout(() => {vscode.commands.executeCommand('workbench.view.extension.' + ClineProvider.sideBarId);
}, 1000);
方案	優點	缺點
主動顯示	確保視圖即時可用	破壞用戶體驗,可能導致界面閃爍
按需加載	節省資源,自然交互	首次顯示有短暫延遲(通常 100-300ms)
通過這種機制,VS Code 實現了插件視圖的高效資源管理,開發者需要根據具體場景平衡即時性和性能消耗^^
注冊菜單點擊對應的命令
context.subscriptions.push(vscode.commands.registerCommand("cline.plusButtonClicked", async () => {Logger.log("Plus button Clicked")const visibleProvider = ClineProvider.getVisibleInstance()if (!visibleProvider) {Logger.log("Cannot find any visible Cline instances.")return}await visibleProvider.clearTask()await visibleProvider.postStateToWebview()await visibleProvider.postMessageToWebview({type: "action",action: "chatButtonClicked",})}),)context.subscriptions.push(vscode.commands.registerCommand("cline.mcpButtonClicked", () => {const visibleProvider = ClineProvider.getVisibleInstance()if (!visibleProvider) {Logger.log("Cannot find any visible Cline instances.")return}visibleProvider.postMessageToWebview({type: "action",action: "mcpButtonClicked",})}),)const openClineInNewTab = async () => {Logger.log("Opening Cline 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.tsconst tabProvider = new ClineProvider(context, outputChannel)//const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefinedconst 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 rightconst hasVisibleEditors = vscode.window.visibleTextEditors.length > 0if (!hasVisibleEditors) {await vscode.commands.executeCommand("workbench.action.newGroupRight")}const targetCol = hasVisibleEditors ? Math.max(lastCol + 1, 1) : vscode.ViewColumn.Twoconst panel = vscode.window.createWebviewPanel(ClineProvider.tabPanelId, "Cline", 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", "robot_panel_light.png"),dark: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "robot_panel_dark.png"),}tabProvider.resolveWebviewView(panel)// Lock the editor group so clicking on files doesn't open them over the panelawait setTimeoutPromise(100)await vscode.commands.executeCommand("workbench.action.lockEditorGroup")}context.subscriptions.push(vscode.commands.registerCommand("cline.popoutButtonClicked", openClineInNewTab))context.subscriptions.push(vscode.commands.registerCommand("cline.openInNewTab", openClineInNewTab))context.subscriptions.push(vscode.commands.registerCommand("cline.settingsButtonClicked", () => {//vscode.window.showInformationMessage(message)const visibleClineProvider = ClineProvider.getVisibleInstance()if (!visibleClineProvider) {Logger.log("Cannot find any visible Cline instances.")return}visibleClineProvider.postMessageToWebview({type: "action",action: "settingsButtonClicked",})}),)context.subscriptions.push(vscode.commands.registerCommand("cline.historyButtonClicked", () => {const visibleProvider = ClineProvider.getVisibleInstance()if (!visibleProvider) {Logger.log("Cannot find any visible Cline instances.")return}visibleProvider.postMessageToWebview({type: "action",action: "historyButtonClicked",})}),)context.subscriptions.push(vscode.commands.registerCommand("cline.accountButtonClicked", () => {const visibleProvider = ClineProvider.getVisibleInstance()if (!visibleProvider) {Logger.log("Cannot find any visible Cline instances.")return}visibleProvider.postMessageToWebview({type: "action",action: "accountButtonClicked",})}),)

這里主要是注冊了6個菜單對應的命令處理邏輯。大部分與視圖相關的代碼基本上就在這里了,active函數剩余的部分在下一篇內容中分析。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/75435.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75435.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/75435.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

k8s EmptyDir(空目錄)詳解

1. 定義與特性 emptyDir 是 Kubernetes 中一種臨時存儲卷類型,其生命周期與 Pod 完全綁定。當 Pod 被創建時,emptyDir 會在節點上生成一個空目錄;當 Pod 被刪除時,該目錄及其數據會被永久清除。它主要用于同一 Pod 內多個容器間的…

【idea】實用插件

SonarLint SonarLint:代碼質量掃描工具 使用 SonarLint 可以幫助我們發現代碼的問題,并且還提供了相應的解決方案. 對于每一個問題,SonarLint 都給出了示例,還有相應的解決方案,教我們怎么修改,極大的方便了我們的開發…

【mysql 的安裝及使用】

MySQL 9.0 一、下載MySQL[MySQL 9.0 下載] [(https://dev.mysql.com/downloads/mysql/)選擇自定義,選擇合適安裝路徑二、檢查安裝情況配置環境變量打開命令行查看版本創建數據庫在MySQL中,可以使用create database語句來創建數據庫。以下是創建一個名為my_db的數據庫的示例:…

leetcode118.楊輝三角

思路源自 【LeetCode 每日一題】118. 楊輝三角 | 手寫圖解版思路 代碼講解 class Solution {public List<List<Integer>> generate(int numRows) {List<List<Integer>> result new ArrayList<>();for (int i 0; i < numRows; i) {List<…

【git】git pull 和 git rebase

git pull 和 git rebase 都是 Git 中用于同步代碼的命令&#xff0c;但它們的工作方式和適用場景有顯著區別。以下是兩者的詳細對比&#xff1a; 1. 核心區別 特性git pullgit rebase本質git fetch git merge&#xff08;默認&#xff09;將當前分支的提交“重新播放”到目標…

DIY搭建網站(學術個人介紹主頁)

本教程介紹了如何創建并管理一個基于GitHub Pages的個人網站。首先&#xff0c;需要在GitHub上創建一個遵循特定命名規則的新倉庫&#xff0c;例如用戶名.github.io&#xff0c;以便建立個人站點。接著&#xff0c;通過Fork一個開源模板代碼倉庫并添加index.html文件來構建主頁…

數據結構初階:二叉樹的前中后序三種遍歷(遞歸的暴力美學)

想要實現二叉樹的遍歷可以創建一個鏈式結構的二叉樹 回顧一下二叉樹的概念&#xff0c;二叉樹分為空樹和非空二叉樹&#xff0c;非空二叉樹由根節點、根節點的左子樹和根節點的右子樹組成。 typedef char BTDataType; // 數據類型 typedef struct BinaryTreeNode {B…

WebUI問題總結

修改WebUI代碼時遇到的一些問題以及解決辦法 1. thttpd服務器環境的搭建 可參考《thttpd安裝與啟動流程》這一篇文章 其中遇到的問題有 thttpd版本問題&#xff1a;版本過舊會導致安裝失敗&#xff0c;盡量安裝新版本thttpd的啟動命令失敗的話要加上sudo修改文件權限&#…

【C++重點】deque

C queue 容器介紹 queue 是 C 標準庫中的一個容器適配器&#xff0c;它實現了先進先出&#xff08;FIFO&#xff09;數據結構。即&#xff0c;元素按照插入的順序排隊&#xff0c;首先插入的元素最先出隊。queue 適用于需要排隊處理任務的場景&#xff0c;比如消息隊列、任務調…

透過 /proc 看見內核:Linux 虛擬文件系統與 systemd 初始化初探

當我們在終端中輸入 ps、top、cat /proc/cpuinfo 等命令時&#xff0c;是否思考過這些信息來自哪里&#xff1f;為什么無需啟動任何守護進程&#xff0c;就能實時讀取系統負載、內存占用&#xff0c;甚至內核版本&#xff1f;這一切的答案&#xff0c;都藏在 Linux 系統中的一個…

操作系統(中斷 異常 陷阱) ─── linux第28課

目錄 1.硬件中斷 2. 時鐘中斷 3. OS本質 4. 軟件中斷 缺頁中斷&#xff1f;內存碎片處理&#xff1f;除零野指針錯誤&#xff1f; 操作系統本質總結 操作系統是對軟件硬件資源管理的軟件 1.硬件中斷 中斷向量表(IDT)就是操作系統的?部分&#xff0c;啟動就加載到內存中了…

文件分片上傳

1前端 <inputtype"file"accept".mp4"ref"videoInput"change"handleVideoChange"style"display: none;">2生成hash // 根據整個文件的文件名和大小組合的字符串生成hash值&#xff0c;大概率確定文件的唯一性fhash(f…

機器學習的一百個概念(5)數據增強

前言 本文隸屬于專欄《機器學習的一百個概念》&#xff0c;該專欄為筆者原創&#xff0c;引用請注明來源&#xff0c;不足和錯誤之處請在評論區幫忙指出&#xff0c;謝謝&#xff01; 本專欄目錄結構和參考文獻請見[《機器學習的一百個概念》 ima 知識庫 知識庫廣場搜索&…

基于微信小程序的智慧鄉村旅游服務平臺【附源碼】

基于微信小程序的智慧鄉村旅游服務平臺&#xff08;源碼L文說明文檔&#xff09; 目錄 4系統設計 4.1系統功能設計 4.2系統結構 4.3.數據庫設計 4.3.1數據庫實體 4.3.2數據庫設計表 5系統詳細實現 5.1 管理員模塊的實現 5.1.1旅游景點管理…

數據驅動的智能BMS革新:機器學習賦能電池健康預測與安全協同優化

傳統電池管理系統&#xff08;BMS&#xff09;依賴等效電路模型和固定參數算法&#xff0c;面臨電化學機理復雜、老化行為非線性、多工況適應性差等瓶頸。例如&#xff0c;健康狀態&#xff08;SOH&#xff09;和荷電狀態&#xff08;SOC&#xff09;估算易受溫度、循環次數及電…

使用JSON.stringify報錯:Uncaught TypeError: cyclic object value

具體錯誤 Uncaught TypeError: cyclic object valueonMouseOver Amap.vue:125renderMarker Amap.vue:84emit maps:1emit maps:1ci maps:1ui maps:1fireEvent maps:1jL maps:1Xt maps:1T maps:1<anonymous> amap.vue:49promise callback*nextTick runtime-core.esm-bundl…

Spring Boot 工程創建詳解

2025/4/2 向全棧工程師邁進&#xff01; 一、SpingBoot工程文件的創建 點擊Project Structure 然后按著如下點擊 最后選擇Spring Boot &#xff0c;同時記得選擇是Maven和jar&#xff0c;而不是war。因為Boot工程內置了Tomcat&#xff0c;所以不需要war。 緊接著選擇Spring We…

Java 8 的流(Stream API)簡介

Java 8 引入的 Stream API 是一個強大的工具&#xff0c;用于處理集合&#xff08;如 List、Set&#xff09;中的元素。它支持各種操作&#xff0c;包括過濾、排序、映射等&#xff0c;并且能夠以聲明式的方式表達復雜的查詢操作。流操作可以是中間操作&#xff08;返回流以便進…

4. Flink SQL訪問HiveCatalog

一. 實驗環境 Flink版本: 1.19.1 Hive版本: 2.1.3 Hadoop版本: 3.2.4二. 操作步驟 1.上傳所需的jar包到Flink lib目錄下 [roothadoop3 ~]# mv flink-sql-connector-hive-3.1.3_2.12-1.19.1.jar /www/flink-1.19.1/lib [roothadoop3 ~]# mv hadoop-mapreduce-client-core-3.2…

虛擬試衣間-云尚衣櫥小程序-衣櫥管理實現

衣櫥管理實現 目標 (Goal): 用戶 (User): 能通過 UniApp 小程序上傳衣服圖片。 后端 (Backend): 接收圖片,存到云存儲,并將圖片信息(URL、用戶ID等)存入數據庫。 用戶 (User): 能在小程序里看到自己上傳的所有衣服圖片列表。 技術棧細化 (Refined Tech Stack for this Pha…