@@ -180,8 +180,12 @@ func parseAndAugment(xctx XContext, pkg *PackageData, isTest bool, fileSet *toke
180
180
181
181
for _ , file := range originalFiles {
182
182
augmentOriginalImports (pkg .ImportPath , file )
183
- augmentOriginalFile (file , overrides )
184
- pruneImports (file )
183
+ }
184
+
185
+ if len (overrides ) > 0 {
186
+ for _ , file := range originalFiles {
187
+ augmentOriginalFile (file , overrides )
188
+ }
185
189
}
186
190
187
191
return append (overlayFiles , originalFiles ... ), jsFiles , nil
@@ -275,6 +279,7 @@ func parserOriginalFiles(pkg *PackageData, fileSet *token.FileSet) ([]*ast.File,
275
279
// an overlay file AST to collect information such as compiler directives
276
280
// and perform any initial augmentation needed to the overlay.
277
281
func augmentOverlayFile (file * ast.File , overrides map [string ]overrideInfo ) {
282
+ anyChange := false
278
283
for i , decl := range file .Decls {
279
284
purgeDecl := astutil .Purge (decl )
280
285
switch d := decl .(type ) {
@@ -302,15 +307,20 @@ func augmentOverlayFile(file *ast.File, overrides map[string]overrideInfo) {
302
307
}
303
308
}
304
309
if purgeSpec {
310
+ anyChange = true
305
311
d .Specs [j ] = nil
306
312
}
307
313
}
308
314
}
309
315
if purgeDecl {
316
+ anyChange = true
310
317
file .Decls [i ] = nil
311
318
}
312
319
}
313
- finalizeRemovals (file )
320
+ if anyChange {
321
+ finalizeRemovals (file )
322
+ pruneImports (file )
323
+ }
314
324
}
315
325
316
326
// augmentOriginalImports is the part of parseAndAugment that processes
@@ -334,10 +344,12 @@ func augmentOriginalImports(importPath string, file *ast.File) {
334
344
// original file AST to augment the source code using the overrides from
335
345
// the overlay files.
336
346
func augmentOriginalFile (file * ast.File , overrides map [string ]overrideInfo ) {
347
+ anyChange := false
337
348
for i , decl := range file .Decls {
338
349
switch d := decl .(type ) {
339
350
case * ast.FuncDecl :
340
351
if info , ok := overrides [astutil .FuncKey (d )]; ok {
352
+ anyChange = true
341
353
removeFunc := true
342
354
if info .keepOriginal {
343
355
// Allow overridden function calls
@@ -358,6 +370,7 @@ func augmentOriginalFile(file *ast.File, overrides map[string]overrideInfo) {
358
370
} else if recvKey := astutil .FuncReceiverKey (d ); len (recvKey ) > 0 {
359
371
// check if the receiver has been purged, if so, remove the method too.
360
372
if info , ok := overrides [recvKey ]; ok && info .purgeMethods {
373
+ anyChange = true
361
374
file .Decls [i ] = nil
362
375
}
363
376
}
@@ -366,6 +379,7 @@ func augmentOriginalFile(file *ast.File, overrides map[string]overrideInfo) {
366
379
switch s := spec .(type ) {
367
380
case * ast.TypeSpec :
368
381
if _ , ok := overrides [s .Name .Name ]; ok {
382
+ anyChange = true
369
383
d .Specs [j ] = nil
370
384
}
371
385
case * ast.ValueSpec :
@@ -378,6 +392,7 @@ func augmentOriginalFile(file *ast.File, overrides map[string]overrideInfo) {
378
392
// to be run, add the call into the overlay.
379
393
for k , name := range s .Names {
380
394
if _ , ok := overrides [name .Name ]; ok {
395
+ anyChange = true
381
396
s .Names [k ] = nil
382
397
s .Values [k ] = nil
383
398
}
@@ -405,6 +420,7 @@ func augmentOriginalFile(file *ast.File, overrides map[string]overrideInfo) {
405
420
}
406
421
}
407
422
if removeSpec {
423
+ anyChange = true
408
424
d .Specs [j ] = nil
409
425
}
410
426
}
@@ -413,7 +429,10 @@ func augmentOriginalFile(file *ast.File, overrides map[string]overrideInfo) {
413
429
}
414
430
}
415
431
}
416
- finalizeRemovals (file )
432
+ if anyChange {
433
+ finalizeRemovals (file )
434
+ pruneImports (file )
435
+ }
417
436
}
418
437
419
438
// isOnlyImports determines if this file is empty except for imports.
@@ -437,6 +456,14 @@ func isOnlyImports(file *ast.File) bool {
437
456
// If the removal of code causes an import to be removed, the init's from that
438
457
// import may not be run anymore. If we still need to run an init for an import
439
458
// which is no longer used, add it to the overlay as a blank (`_`) import.
459
+ //
460
+ // This uses the given name or guesses at the name using the import path,
461
+ // meaning this doesn't work for packages which have a different package name
462
+ // from the path, including those paths which are versioned
463
+ // (e.g. `github.com/foo/bar/v2` where the package name is `bar`)
464
+ // or if the import is defined using a relative path (e.g. `./..`).
465
+ // Those cases don't exist in the native for Go, so we should only run
466
+ // this pruning when we have native overlays, but not for unknown packages.
440
467
func pruneImports (file * ast.File ) {
441
468
if isOnlyImports (file ) && ! astutil .HasDirectivePrefix (file , `//go:linkname ` ) {
442
469
// The file is empty, remove all imports including any `.` or `_` imports.
@@ -478,12 +505,11 @@ func pruneImports(file *ast.File) {
478
505
// since the import is otherwise unused set the name to blank.
479
506
in .Name = ast .NewIdent (`_` )
480
507
delete (unused , name )
481
- if len (unused ) == 0 {
482
- return
483
- }
484
- break
485
508
}
486
509
}
510
+ if len (unused ) == 0 {
511
+ return
512
+ }
487
513
488
514
// Remove all unused import specifications
489
515
isUnusedSpec := map [* ast.ImportSpec ]bool {}
0 commit comments