先说结论
C:\Users\...\AppData\Roaming\Code\User\workspaceStorage
这个文件夹下有一些digest英文字母文件夹
一般按修改时间排序就能找到自己所想要导出的项目
里边有俩文件
workspace.json就是纯文本
state.vscdb是个SQLite数据库,可以用DB Browser for SQLite打开
里边的workbench.search.history即保存了搜索历史记录
下拉列表
https://github.com/microsoft/vscode/issues/23099
首先看上边这个issues,是请求搜索历史的下拉列表,7年了还没实现,我自己研究研究吧
history.ts
https://github.com/microsoft/vscode/blob/main/src/vs/base/common/history.ts
这个文件 两个class
主要看上边这个class
下边的HistoryNavigator2,是SCM用的
https://github.com/microsoft/vscode/commit/4af42491069dcbf0881b7993ee18a180b790f861
https://github.com/microsoft/vscode/blob/9c3cc8b9948d52f04836997a7de01dbd9bb2a7bf/src/vs/workbench/contrib/interactive/browser/interactiveHistoryService.ts#L6
SCM 通常指的是版本控制系统(Source Code Management)
大概是指左侧栏的源代码管理里的搜索
相关代码
https://github.com/microsoft/vscode/blob/main/src/vs/base/browser/ui/inputbox/inputBox.ts
https://github.com/microsoft/vscode/blob/main/src/vs/workbench/parts/search/browser/searchWidget.ts
https://github.com/microsoft/vscode/blob/main/src/vs/workbench/contrib/interactive/browser/interactiveHistoryService.ts
HistoryInputBox
调用层次/调用关系:(vscode没法同时看call和called两个方向)(发现这个call hierarchy调用层次结构,识别的不对。。。会缺少一些调用方。用查找引用就能找到)
abstractTree.ts
src\vs\base\browser\ui\tree\abstractTree.ts
我仔细看了看,发现这个文件里的这个FindWidget不太对,对应的是
https://superuser.com/questions/1748097/vs-code-disable-tree-view-find-explorer-search
FindInput
vs\base\browser\ui\findinput\findInput.ts
extends的结果 调用层次结构识别不到
vs\workbench\contrib\search\browser\searchWidget.ts
vs\workbench\contrib\search\browser\searchView.ts
终于找到了(好像不太对)
/**
* 每当在给定范围和可选键上更新或删除数据时触发。
*
* @param scope the `StorageScope` to listen to changes
* @param key the optional key to filter for or all keys of the scope if `undefined`
*/
onDidChangeValue
this._register(this.storageService.onDidChangeValue(StorageScope.WORKSPACE, SearchHistoryService.SEARCH_HISTORY_KEY, this._register(new DisposableStore()))(() => {
const restoredHistory = this.searchHistoryService.load();
if (restoredHistory.include) {
this.inputPatternIncludes.prependHistory(restoredHistory.include);
}
if (restoredHistory.exclude) {
this.inputPatternExcludes.prependHistory(restoredHistory.exclude);
}
if (restoredHistory.search) {
this.searchWidget.prependSearchHistory(restoredHistory.search);
}
if (restoredHistory.replace) {
this.searchWidget.prependReplaceHistory(restoredHistory.replace);
}
}));
vs\workbench\contrib\search\common\searchHistoryService.ts
调用方意思就是,下边的子项函数会调用load
调用来自意思就是,load会调用下边的子项函数
export class SearchHistoryService implements ISearchHistoryService { // 前边带大写字母I的都是interface接口
declare readonly _serviceBrand: undefined;
public static readonly SEARCH_HISTORY_KEY = 'workbench.search.history';
private readonly _onDidClearHistory = new Emitter<void>();
readonly onDidClearHistory: Event<void> = this._onDidClearHistory.event;
constructor(
@IStorageService private readonly storageService: IStorageService
) { }
clearHistory(): void {
this.storageService.remove(SearchHistoryService.SEARCH_HISTORY_KEY, StorageScope.WORKSPACE);
this._onDidClearHistory.fire();
}
load(): ISearchHistoryValues {
let result: ISearchHistoryValues | undefined;
const raw = this.storageService.get(SearchHistoryService.SEARCH_HISTORY_KEY, StorageScope.WORKSPACE);
@IStorageService
export const IStorageService = createDecorator<IStorageService>('storageService');
这块装饰器createDecorator太复杂了,以及SearchHistoryService什么时候创建/初始化的的问题,涉及到vscode整个的设计、依赖注入,我看了看没太看懂
具体可见下边的链接
https://imwangfu.com/2022/05/vscode-di2.html
https://zhuanlan.zhihu.com/p/96902077
vs\workbench\contrib\search\browser\search.contribution.ts
registerSingleton(ISearchHistoryService, SearchHistoryService, InstantiationType.Delayed);
这种情况,调用层次识别不到
这段代码看起来是在某个依赖注入容器中注册一个单例服务的操作。让我解释一下其中的各个部分:
- `registerSingleton`: 这是一个函数或方法,用于在依赖注入容器中注册一个单例服务。通常,依赖注入容器用于管理应用程序中的依赖关系,并在需要时提供相应的实例。
- `ISearchHistoryService`: 这是一个接口(或抽象类)的引用,它定义了一个搜索历史服务的契约或合同。在依赖注入中,通常会使用接口或抽象类来描述服务的行为,而具体的实现则通过实现该接口或继承该抽象类来完成。
- `SearchHistoryService`: 这是实现了 `ISearchHistoryService` 接口的具体服务类的引用。它是实际提供服务的类,其中包含了实现了搜索历史功能的代码。
- `InstantiationType.Delayed`: 这是一个参数,用于指定服务的实例化方式。在这种情况下,`Delayed` 可能表示延迟实例化,即在需要时才会创建服务的实例。这种实例化方式可以帮助优化性能,避免在应用程序启动时就创建所有的服务实例。
综合起来,这段代码的作用是在依赖注入容器中注册一个单例服务,该服务实现了 `ISearchHistoryService` 接口,并使用延迟实例化方式。这样,在应用程序中的其他地方就可以通过依赖注入容器获取 `ISearchHistoryService` 接口的实例,并使用其中定义的方法来访问搜索历史记录。
ticino.blob.core.windows.net
动态语言有个优点就是好调试,c/c++还得整个编译一个带调试符号的版本exe,否则符号信息/函数名全没了,就剩下汇编。js编译后好歹还会剩下一些高级语言的特征。
而且vscode这里的调试sourcemap还能自动加载官方提供的,不必像vue那样重新编译一遍出来符号,官方不提供sourcemap。
typescript 继承 编译为js
export class Component extends Themable {
this._register(storageService.onWillSaveState(() => {
// Ask the component to persist state into the memento
this.saveState();
export class ViewPaneContainer extends Component implements IViewPaneContainer {
protected override saveState(): void {
this.panes.forEach((view) => view.saveState());
this.storageService.store(this.visibleViewsStorageId, this.length, StorageScope.WORKSPACE, StorageTarget.MACHINE);
}
这里ViewPaneContainer继承了Component,在js实际运行时,调用栈是这样的(调用栈这里显示的没有替换为sourcemap的原始函数名)
是Component的saveState函数调用了ViewPaneContainer的saveState函数(跟我以前java中的重写不太一样,应该是js原生不支持继承所以转换成了这样)
调用层次结构
还是就是vscode的调用层次结构,对这种 接口/抽象类 类型的成员变量.调用一个方法(实际是多态,父类型引用指向子类型的实例,子类重写该方法),这种情况,根本识别不出来
(parameter) view: ViewPane
this.panes.forEach((view) => view.saveState());
export abstract class ViewPane extends Pane implements IView {
export class SearchView extends ViewPane {
vs\workbench\contrib\search\common\searchHistoryService.ts
vs\platform\storage\common\storage.ts
export interface ISearchHistoryService {
readonly _serviceBrand: undefined;
onDidClearHistory: Event<void>;
clearHistory(): void;
load(): ISearchHistoryValues;
save(history: ISearchHistoryValues): void;
}
在save上点击查找所有实现,找不到重写的save方法。需要点击查找所有引用
vs\platform\storage\common\storageService.ts
对于override导致的多态,导致调用层次结构无法识别的问题。反向是能识别的,但是正向识别不了,大概是因为由于多态,不确定在多个重写的方法中到底用哪个。
vs\base\parts\storage\common\storage.ts
this.pendingInserts.set(key, valueStr);