@@ -2,16 +2,64 @@ import * as vscode from "vscode";
22import { logger } from "../utils" ;
33import { 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 */
822export 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