Skip to content

Commit

Permalink
fix(bookmark): 修复Refactor指令中的Move to new file 书签异常问题
Browse files Browse the repository at this point in the history
  • Loading branch information
czfadmin committed Nov 29, 2024
1 parent 5ba1de7 commit f387388
Show file tree
Hide file tree
Showing 14 changed files with 1,207 additions and 649 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@
"@types/glob": "^8.1.0",
"@types/lodash": "^4.14.199",
"@types/mocha": "^10.0.1",
"@types/node": "16.x",
"@types/node": "^22.10.1",
"@types/uuid": "^9.0.4",
"@types/vscode": "^1.82.0",
"@typescript-eslint/eslint-plugin": "^5.59.1",
Expand Down
67 changes: 49 additions & 18 deletions src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from './utils/bookmark';
import {registerExtensionCustomContextByKey} from './context';
import {resolveBookmarkController} from './bootstrap';
import resolveServiceManager from './services/ServiceManager';
import resolveServiceManager, {ServiceManager} from './services/ServiceManager';

let onDidChangeVisibleTextEditors: Disposable | undefined;
let onDidSaveTextDocumentDisposable: Disposable | undefined;
Expand Down Expand Up @@ -149,14 +149,37 @@ export function updateBookmarkInfoWhenTextChangeListener() {
onDidChangeTextDocumentDisposable = workspace.onDidChangeTextDocument(e => {
const {contentChanges, document} = e;
// 代表存在文档发生变化
if (contentChanges.length) {
const bookmarks = controller.getBookmarkStoreByFileUri(document.uri);
if (!bookmarks.length) {
if (!contentChanges.length || document.uri.scheme !== 'file') {
return;
}

const bookmarks = controller.getBookmarkStoreByFileUri(document.uri);

if (!bookmarks.length) {
return;
}

// 配合当使用`command(refactor:moveToNewFile)`指令, 更新书签数据
if (bookmarks.length === 1 && locker.didCreate) {
locker.didCreate = false;
const bookmark = bookmarks[0];

// 寻找第一个相同的内容的书签作为书签的新的 `range`
for (let idx = 0; idx < document.lineCount; idx++) {
const line = document.lineAt(idx);
if (
line.text.length &&
bookmark.selectionContent.includes(line.text.trim())
) {
bookmark.updateRangesOrOptions(line.range);
}
return;
}
for (let change of contentChanges) {
updateBookmarksGroupByChangedLine(e, change);
}
return;
}

for (let change of contentChanges) {
updateBookmarksGroupByChangedLine(e, change);
}
});
}
Expand Down Expand Up @@ -191,7 +214,7 @@ export function updateFilesRenameAndDeleteListeners() {
// 监听文件删除
onDidDeleteFilesDisposable = workspace.onDidDeleteFiles(e => {
const {files} = e;
const excludeFolders = ['node_modules', '.vscode', 'dist', '.git'];
const excludeFolders = ['node_modules', '.vscode', 'dist', '.git', 'out'];
if (!files.length) {
return;
}
Expand All @@ -204,24 +227,21 @@ export function updateFilesRenameAndDeleteListeners() {
}
});

workspace.onWillDeleteFiles(e => {});

/**
* 在进行refactor中将文件移动到一个新的文件,
* 在进行refactor中将当前打开的文件中的书签移动到一个新的文件,
* - 通过对当前的打开的文档激活的行, 判断当前行时候存在书签,
* - 如果有书签, 需要当前的书签的数据移动到新的文件, 此时进行对当前行的内容和新的文件中的内容进行正则匹配, 完成书签位置调整
* - 如果没用, 更新当前激活的文件中的存在的书签的数据, 此时已经有`updateBookmarkInfoWhenTextChangeListener` 监听的事件进行处理.
*/
workspace.onDidCreateFiles((e: FileCreateEvent) => {
locker.willCreate = false;
const {files} = e;
console.log(
'workspace.onDidCreateFiles:',
files,
window.activeTextEditor?.selection.active.line,
);

locker.willCreate = false;

const activeTextEditor = window.activeTextEditor;
if (!activeTextEditor) {
return;
Expand All @@ -231,13 +251,12 @@ export function updateFilesRenameAndDeleteListeners() {

const existingBookmark = getBookmarkFromLineNumber(activeLine);

console.log('当前书签: ', existingBookmark);

if (!existingBookmark) {
return;
}

existingBookmark.updateFileUri(files[0]);
locker.didCreate = true;
});

workspace.onWillCreateFiles((e: FileWillCreateEvent) => {
Expand All @@ -250,9 +269,21 @@ export function updateFilesRenameAndDeleteListeners() {
locker.willCreate = true;
});

// workspace.onWillSaveTextDocument(e => {
// console.log("workspace.onWillSaveTextDocument:", e, window.activeTextEditor?.selection.active.line)
// })
workspace.onWillSaveTextDocument(e => {
console.log(
'workspace.onWillSaveTextDocument:',
e,
window.activeTextEditor?.selection.active.line,
);
});

workspace.onDidSaveTextDocument(e => {
console.log(
'workspace.onDidSaveTextDocument:',
e,
window.activeTextEditor?.selection.active.line,
);
});
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/services/BaseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {ServiceManager} from './ServiceManager';

export abstract class BaseService implements ILifecyle {
public readonly sm: ServiceManager;
public readonly _logger: LoggerService;
public readonly logger: LoggerService;

public readonly _disposers: (IDisposable | IDisposer)[] = [];

Expand All @@ -19,7 +19,7 @@ export abstract class BaseService implements ILifecyle {

constructor(name: string, sm: ServiceManager) {
this.sm = sm;
this._logger = new LoggerService(name);
this.logger = new LoggerService(name);
}

initial() {}
Expand Down
33 changes: 27 additions & 6 deletions src/services/DecorationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default class DecorationService extends BaseService {
]);
});
} catch (error) {
this._logger.error(error);
this.logger.error(error);
}
}

Expand Down Expand Up @@ -178,14 +178,29 @@ export default class DecorationService extends BaseService {
return decoration;
}

/**
* @zh 根据书签更新书签装饰器
* @param bookmark 待更新的书签装饰器
* @returns
*/
updateTextDecoration(bookmark: Instance<typeof Bookmark>) {
const editor = window.visibleTextEditors.find(
it => it.document.uri.fsPath === bookmark.fileId,
);
const prevTextDecoration = this._decorations.get(bookmark.id);

if (!editor) {
if (!prevTextDecoration) {
return;
}
for (let editor of window.visibleTextEditors) {
editor.setDecorations(prevTextDecoration, []);
}
this._decorations.delete(bookmark.id);
prevTextDecoration.dispose();
return;
}
const prevTextDecoration = this._decorations.get(bookmark.id);

if (prevTextDecoration) {
editor.setDecorations(prevTextDecoration, []);
prevTextDecoration.dispose();
Expand All @@ -210,10 +225,16 @@ export default class DecorationService extends BaseService {
if (!textDecoration) {
return;
}
const editor = window.visibleTextEditors.find(
it => it.document.uri.fsPath === bookmark.fileId,
);
if (editor) {

if (
!window.visibleTextEditors.length &&
this._decorations.has(bookmark.id)
) {
this._decorations.delete(bookmark.id);
textDecoration.dispose();
}

for (let editor of window.visibleTextEditors) {
editor.setDecorations(textDecoration, []);
}

Expand Down
115 changes: 62 additions & 53 deletions src/services/GitService.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,87 @@
import fs from 'node:fs';
import path from 'node:path';
import {
Disposable,
workspace,
WorkspaceFolder,
Event,
EventEmitter,
FileSystemWatcher,
} from 'vscode';
import {WorkspaceFolder, Event, EventEmitter, extensions} from 'vscode';
import {ServiceManager} from './ServiceManager';
import {BaseService} from './BaseService';
import {API, GitExtension} from '../types';

/**
* Git 相关的服务类
*/
export default class GitService extends BaseService {
repos: WorkspaceFolder[] = [];
private _fsWatcher: FileSystemWatcher | undefined;
private _onDidReposChangeEvent: EventEmitter<WorkspaceFolder[]> =
new EventEmitter<WorkspaceFolder[]>();

private _gitExtension: GitExtension | undefined;

private _git: API | undefined;

onDidReposChangeEvent: Event<WorkspaceFolder[]> =
this._onDidReposChangeEvent.event;

private _branch: string = '';

get branch() {
return this._branch;
}

get git() {
if (!this._git) {
this._git = this._gitExtension?.getAPI(1);
}
return this._git;
}

get gitExtension() {
if (!this._gitExtension) {
try {
this._gitExtension =
extensions.getExtension<GitExtension>('vscode.git')!.exports;
} catch (e) {
this.logger.error(e);
}
}
return this._gitExtension;
}

constructor(sm: ServiceManager) {
super(GitService.name, sm);
this._init();
workspace.onDidChangeWorkspaceFolders(ev => {
const {added, removed} = ev;
let isChanged = false;
for (let wsFolder of added) {
if (this._checkFolderIsRepo(wsFolder.uri.fsPath)) {
this.repos.push(wsFolder);
if (!isChanged) {
isChanged = true;
}
}
}
for (let wsFolder of removed) {
if (this._checkFolderIsRepo(wsFolder.uri.fsPath)) {
this.repos = this.repos.filter(
it => it.uri.fsPath === wsFolder.uri.fsPath,
);
if (!isChanged) {
isChanged = true;
}
}
}
if (isChanged) {
this._onDidReposChangeEvent.fire(this.repos);
}
});
}

private _init() {
const workspaceFolders = workspace.workspaceFolders || [];
if (!workspaceFolders.length) {
return;
}
for (let wsFolder of workspaceFolders) {
const wsPath = wsFolder.uri.fsPath;
if (
this._checkFolderIsRepo(wsFolder.uri.fsPath) &&
!this.repos.find(it => it.uri.fsPath === wsPath)
) {
this.repos.push(wsFolder);
const _gitExt = extensions.all.find(it => it.id === 'vscode.git');
if (_gitExt) {
if (!_gitExt.isActive) {
_gitExt.activate().then(e => {
this._gitExtension = e as GitExtension;
this._git = this._gitExtension.getAPI(1);
});
} else {
this._gitExtension =
extensions.getExtension<GitExtension>('vscode.git')!.exports;
this._git = this._gitExtension.getAPI(1);
}
}
}

private _checkFolderIsRepo(p: string) {
return fs.existsSync(path.resolve(p, '.git'));
}
this.addToDisposers(
extensions.onDidChange(e => {
try {
const _gitExtension = extensions.all.find(
it => it.id === 'vscode.git',
);
if (!_gitExtension || _gitExtension.isActive || this._gitExtension) {
return;
}

dispose() {
this._fsWatcher?.dispose();
this._gitExtension =
extensions.getExtension<GitExtension>('vscode.git')!.exports;
this._git = this._gitExtension.getAPI(1);
} catch (error) {
this.logger.error(error);
}
}),
);
}

dispose() {}
}
2 changes: 1 addition & 1 deletion src/services/IconsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ export class IconsService extends BaseService {
try {
return await ofetch(url);
} catch (error) {
this._logger.error(error);
this.logger.error(error);
return error;
}
}
Expand Down
29 changes: 29 additions & 0 deletions src/stores/BookmarkSCMCommitInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {Instance, types} from 'mobx-state-tree';
/**
* @zh 书签源代码控制提交信息
*/
export const BookmarkSCMCommitInfo = types
.model('BookmarkSCMCommitInfo', {
/**
* @zh 创建书签时的提交的HASH
*/
commitHash: types.string,

/**
* @zh 创建书签时的分支
*/
branch: types.string,

/**
* @zh 书签快照, 跟随`commitHash`
*/
snapshot: types.string,
})
.views(self => {
return {};
})
.actions(self => {
return {};
});

export type BookmarkSCMCommitInfoType = Instance<typeof BookmarkSCMCommitInfo>;
Loading

0 comments on commit f387388

Please sign in to comment.