Skip to content

Commit 76f5165

Browse files
committed
merge: integrate refactor/consolidate-commands-and-cleanup into develop
Resolves conflicts: - .gitignore: combine develop's comprehensive entries with *.patch - extension.ts: take refactored CommandsHandler structure, port isModuleImport hotfix into simplified hover provider
2 parents fec6c31 + 3b2a001 commit 76f5165

14 files changed

Lines changed: 978 additions & 756 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,6 @@ Thumbs.db
3939
.claude
4040
.codex
4141
.gemini
42+
43+
# Patch files
44+
*.patch

src/commands/CommandsHandler.ts

Lines changed: 391 additions & 56 deletions
Large diffs are not rendered by default.

src/commands/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { CommandsHandler } from "./CommandsHandler";
1+
export { CommandsHandler, CommandsDependencies } from "./CommandsHandler";

src/extension.ts

Lines changed: 58 additions & 268 deletions
Large diffs are not rendered by default.

src/imports/ImportCodeLensProvider.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@ import { logger } from "../utils";
33
import { ImportFormatter } from "./ImportFormatter";
44
import { ImportPathConverter } from "./ImportPathConverter";
55

6+
/** Tracks hover state for a document's imports. */
7+
interface HoverState {
8+
lineNumber: number;
9+
timeout: NodeJS.Timeout | null;
10+
}
11+
612
export class ImportCodeLensProvider implements vscode.CodeLensProvider {
7-
private _onDidChangeCodeLenses: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
13+
private readonly _onDidChangeCodeLenses = new vscode.EventEmitter<void>();
814
public readonly onDidChangeCodeLenses: vscode.Event<void> = this._onDidChangeCodeLenses.event;
915

10-
private importPathConverter: ImportPathConverter;
11-
private hoverState = new Map<string, { lineNumber: number; timeout: NodeJS.Timeout | null }>();
12-
private isHoveringImport = new Map<string, boolean>();
16+
private readonly importPathConverter: ImportPathConverter;
17+
private readonly hoverState = new Map<string, HoverState>();
18+
private readonly isHoveringImport = new Map<string, boolean>();
1319
private refreshTimeout: NodeJS.Timeout | null = null;
1420

1521
constructor(private outputChannel: vscode.OutputChannel) {

src/imports/ImportDocumentEditor.ts

Lines changed: 68 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,64 @@ import * as vscode from "vscode";
22
import { logger } from "../utils";
33
import { ImportFormatter } from "./ImportFormatter";
44

5+
/** Represents a contiguous block of import statements in the document. */
6+
interface ImportBlock {
7+
start: number;
8+
end: number;
9+
imports: string[];
10+
}
11+
12+
/** Represents a single line edit for syntax conversion. */
13+
interface LineEdit {
14+
line: number;
15+
oldText: string;
16+
newText: string;
17+
}
18+
519
/**
620
* Handles all document modifications for imports.
721
*/
822
export class ImportDocumentEditor {
9-
private formatter: ImportFormatter;
23+
private readonly formatter: ImportFormatter;
1024

1125
constructor(private outputChannel: vscode.OutputChannel, formatter: ImportFormatter) {
1226
this.formatter = formatter;
1327
}
1428

29+
/**
30+
* Creates an edit to replace an import block with combined and formatted imports.
31+
*/
32+
private createBlockReplacementEdit(
33+
edit: vscode.WorkspaceEdit,
34+
document: vscode.TextDocument,
35+
block: ImportBlock,
36+
newPaths: string[],
37+
preferDotSyntax: boolean,
38+
sortAlphabetically: boolean
39+
): void {
40+
// Get existing paths in this block for combined sorting
41+
const existingBlockPaths = block.imports
42+
.map((imp) => this.formatter.extractPathFromImport(imp))
43+
.filter((p): p is string => p !== null);
44+
45+
const combinedPaths = [...existingBlockPaths, ...newPaths];
46+
if (sortAlphabetically) {
47+
combinedPaths.sort((a, b) => a.localeCompare(b));
48+
}
49+
50+
// Format all imports for this block
51+
const formattedImports = combinedPaths.map((path) =>
52+
this.formatter.formatImportStatement(path, preferDotSyntax)
53+
);
54+
55+
// Replace the entire block
56+
edit.replace(
57+
document.uri,
58+
new vscode.Range(new vscode.Position(block.start, 0), new vscode.Position(block.end + 1, 0)),
59+
formattedImports.join("\n") + "\n"
60+
);
61+
}
62+
1563
/**
1664
* Extracts existing import statements from a document.
1765
*/
@@ -55,8 +103,8 @@ export class ImportDocumentEditor {
55103
const lines = text.split("\n");
56104
const existingImports = new Set<string>();
57105

58-
const importBlocks: { start: number; end: number; imports: string[] }[] = [];
59-
let currentBlock: { start: number; end: number; imports: string[] } | null = null;
106+
const importBlocks: ImportBlock[] = [];
107+
let currentBlock: ImportBlock | null = null;
60108

61109
for (let i = 0; i < lines.length; i++) {
62110
const line = lines[i].trim();
@@ -153,38 +201,26 @@ export class ImportDocumentEditor {
153201

154202
// Add digest imports to digest block
155203
if (newDigestPaths.length > 0 && digestBlockIndex >= 0) {
156-
const block = importBlocks[digestBlockIndex];
157-
// Get existing paths in this block for combined sorting
158-
const existingBlockPaths = block.imports.map((imp) => this.formatter.extractPathFromImport(imp)).filter((p) => p) as string[];
159-
160-
const combinedPaths = [...existingBlockPaths, ...newDigestPaths];
161-
if (sortAlphabetically) {
162-
combinedPaths.sort((a, b) => a.localeCompare(b));
163-
}
164-
165-
// Format all imports for this block
166-
const formattedImports = combinedPaths.map((path) => this.formatter.formatImportStatement(path, preferDotSyntax));
167-
168-
// Replace the entire block
169-
edit.replace(document.uri, new vscode.Range(new vscode.Position(block.start, 0), new vscode.Position(block.end + 1, 0)), formattedImports.join("\n") + "\n");
204+
this.createBlockReplacementEdit(
205+
edit,
206+
document,
207+
importBlocks[digestBlockIndex],
208+
newDigestPaths,
209+
preferDotSyntax,
210+
sortAlphabetically
211+
);
170212
}
171213

172214
// Add local imports to local block
173215
if (newLocalPaths.length > 0 && localBlockIndex >= 0) {
174-
const block = importBlocks[localBlockIndex];
175-
// Get existing paths in this block for combined sorting
176-
const existingBlockPaths = block.imports.map((imp) => this.formatter.extractPathFromImport(imp)).filter((p) => p) as string[];
177-
178-
const combinedPaths = [...existingBlockPaths, ...newLocalPaths];
179-
if (sortAlphabetically) {
180-
combinedPaths.sort((a, b) => a.localeCompare(b));
181-
}
182-
183-
// Format all imports for this block
184-
const formattedImports = combinedPaths.map((path) => this.formatter.formatImportStatement(path, preferDotSyntax));
185-
186-
// Replace the entire block
187-
edit.replace(document.uri, new vscode.Range(new vscode.Position(block.start, 0), new vscode.Position(block.end + 1, 0)), formattedImports.join("\n") + "\n");
216+
this.createBlockReplacementEdit(
217+
edit,
218+
document,
219+
importBlocks[localBlockIndex],
220+
newLocalPaths,
221+
preferDotSyntax,
222+
sortAlphabetically
223+
);
188224
}
189225

190226
// Handle imports that don't have a matching block
@@ -453,7 +489,7 @@ export class ImportDocumentEditor {
453489

454490
const text = document.getText();
455491
const lines = text.split("\n");
456-
const edits: { line: number; oldText: string; newText: string }[] = [];
492+
const edits: LineEdit[] = [];
457493

458494
for (let i = 0; i < lines.length; i++) {
459495
const line = lines[i];

0 commit comments

Comments
 (0)