Skip to content

Commit

Permalink
Merge pull request #156 from jiayinzhang-mint/master
Browse files Browse the repository at this point in the history
Implement rename functionality
  • Loading branch information
zxh0 authored Jul 4, 2023
2 parents f808059 + c71b00c commit 445cf36
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/proto3Main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import { PROTO3_MODE } from './proto3Mode';
import { Proto3DefinitionProvider } from './proto3Definition';
import { Proto3Configuration } from './proto3Configuration';
import { Proto3DocumentSymbolProvider } from './proto3SymbolProvider';
import { Proto3RenameProvider } from './proto3Rename';

export function activate(ctx: vscode.ExtensionContext): void {

ctx.subscriptions.push(vscode.languages.registerCompletionItemProvider(PROTO3_MODE, new Proto3CompletionItemProvider(), '.', '\"'));
ctx.subscriptions.push(vscode.languages.registerDefinitionProvider(PROTO3_MODE, new Proto3DefinitionProvider()));
ctx.subscriptions.push(vscode.languages.registerRenameProvider(PROTO3_MODE, new Proto3RenameProvider()));

const diagnosticProvider = new Proto3LanguageDiagnosticProvider();

Expand Down
103 changes: 103 additions & 0 deletions src/proto3Rename.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"use strict";

import fs = require("fs");
import path = require("path");
import vscode = require("vscode");
import fg = require("fast-glob");

export class Proto3RenameProvider implements vscode.RenameProvider {
provideRenameEdits(
document: vscode.TextDocument,
position: vscode.Position,
newName: string,
token: vscode.CancellationToken
): vscode.ProviderResult<vscode.WorkspaceEdit> {
const wordRange = document.getWordRangeAtPosition(position);
const word = document.getText(wordRange);
const edits = new vscode.WorkspaceEdit();
const regex = new RegExp(`\\b${word}\\b`, "g");
for (let i = 0; i < document.lineCount; i++) {
const line = document.lineAt(i);
const match = regex.exec(line.text);
if (match) {
const start = new vscode.Position(i, match.index);
const end = new vscode.Position(i, match.index + match[0].length);
const range = new vscode.Range(start, end);
edits.replace(document.uri, range, newName);
}
}

// update files that import this file
this.updateChildren(document, regex, edits, newName);

// update the file that is imported by this file
this.updateParents(document, regex, edits, newName);

return edits;
}

private updateParents(document: vscode.TextDocument, regex: RegExp, edits: vscode.WorkspaceEdit, newName: string) {
const importFileRegex = new RegExp(`import\\s+"(.+)"`);
for (let i = 0; i < document.lineCount; i++) {
const line = document.lineAt(i);
const match = importFileRegex.exec(line.text);
if (match) {
const importFile = match[1];
const importFileUri = vscode.Uri.file(path.join(path.dirname(document.uri.fsPath), importFile));
const importFileDocument = vscode.workspace.textDocuments.find(
(doc) => doc.uri.fsPath === importFileUri.fsPath
);
if (importFileDocument) {
for (let j = 0; j < importFileDocument.lineCount; j++) {
const line = importFileDocument.lineAt(j);
const match = regex.exec(line.text);
if (match) {
const start = new vscode.Position(j, match.index);
const end = new vscode.Position(j, match.index + match[0].length);
const range = new vscode.Range(start, end);
edits.replace(importFileUri, range, newName);
}
}
}
}
}
}

private updateChildren(document: vscode.TextDocument, regex: RegExp, edits: vscode.WorkspaceEdit, newName: string) {
const importRegex = new RegExp(`import\\s+"${path.basename(document.uri.fsPath)}"`);
const files = fg.sync("**/*.proto", {
cwd: path.dirname(document.uri.fsPath),
});
for (const file of files) {
if (file === path.basename(document.uri.fsPath)) {
continue;
}

const fileUri = vscode.Uri.file(path.join(path.dirname(document.uri.fsPath), file));
const fileDocument = vscode.workspace.textDocuments.find((doc) => doc.uri.fsPath === fileUri.fsPath);
if (fileDocument) {
let startLineIdx = 0;
for (let i = 0; i < fileDocument.lineCount; i++) {
const line = fileDocument.lineAt(i);
const match = importRegex.exec(line.text);
if (match) {
startLineIdx = i;
}
}

if (startLineIdx > 0) {
for (let i = startLineIdx; i < fileDocument.lineCount; i++) {
const line = fileDocument.lineAt(i);
const match = regex.exec(line.text);
if (match) {
const start = new vscode.Position(i, match.index);
const end = new vscode.Position(i, match.index + match[0].length);
const range = new vscode.Range(start, end);
edits.replace(fileUri, range, newName);
}
}
}
}
}
}
}

0 comments on commit 445cf36

Please sign in to comment.