Repository: TabbyML/tabby
File: clients/vscode/src/Commands.ts (TypeScript)

Code before:
      chatPanelViewProvider.resolveWebviewView(panel);
    },
    "chat.edit.start": async (userCommand?: string, range?: Range) => {
      const editor = window.activeTextEditor;
      if (!editor) {
        return;
      }

      let editLocation = {
        uri: editor.document.uri.toString(),
        range: {
          start: { line: editor.selection.start.line, character: 0 },
          end: {
            line: editor.selection.end.character === 0 ? editor.selection.end.line : editor.selection.end.line + 1,
            character: 0,
          },
        },
      };
      if (range) {
        editLocation = {
          uri: editor.document.uri.toString(),
          range: {
            start: { line: range.start.line, character: 0 },
            end: {
              line: range.end.line === 0 ? range.end.line : range.end.line + 1,
              character: range.end.line === 0 ? Number.MAX_SAFE_INTEGER : 0,
            },
          },
        };
      }

      const inlineEditController = new InlineEditController(
        this.client,
        this.config,
        this.contextVariables,
        editor,
        editLocation,
        userCommand,
      );
      inlineEditController.start();
    },
    "chat.edit.stop": async () => {
      this.chatEditCancellationTokenSource?.cancel();
    },
    "chat.edit.accept": async () => {
      const editor = window.activeTextEditor;
      if (!editor) {
        return;
      }
      const location = {
        uri: editor.document.uri.toString(),

Review comment (refactor):
I believe the range process should aim to ensure that the range always covers full lines. However, the check here is `range.end.line` instead of `range.end.character`, which may be a mistake.

Additionally, this process should be same with Line 305-313, where can you extract `editor.selection` to `editRange` and use `const editRange = range ? editor.selection` in order to reuse this process.

Code after:
      chatPanelViewProvider.resolveWebviewView(panel);
    },
    "chat.edit.start": async (userCommand?: string, range?: Range) => {
      const editor = window.activeTextEditor;
      if (!editor) {
        return;
      }

      const editRange = range || editor.selection;

      const editLocation = {
        uri: editor.document.uri.toString(),
        range: {
          start: { line: editRange.start.line, character: 0 },
          end: {
            line: editRange.end.character === 0 ? editRange.end.line : editRange.end.line + 1,
            character: 0,
          },
        },
      };

      const inlineEditController = new InlineEditController(
        this.client,
        this.config,
        this.contextVariables,
        editor,
        editLocation,
        userCommand,
      );
      inlineEditController.start();
    },
    "chat.edit.stop": async () => {
      this.chatEditCancellationTokenSource?.cancel();
    },
    "chat.edit.accept": async () => {
      const editor = window.activeTextEditor;
      if (!editor) {
        return;
      }
      const location = {
        uri: editor.document.uri.toString(),
        range: {
          start: { line: editor.selection.start.line, character: 0 },
          end: { line: editor.selection.end.line + 1, character: 0 },
        },
      };
      await this.client.chat.resolveEdit({ location, action: "accept" });
    },
    "chat.edit.discard": async () => {
      const editor = window.activeTextEditor;
      if (!editor) {