@@ -348,143 +348,160 @@ func (x *extracter) visitArgs(fd *callData, v ssa.Value) {
348
348
}
349
349
}
350
350
351
- func (x * extracter ) extractMessages () {
352
- // print returns Go syntax for the specified node.
353
- print := func (n ast.Node ) string {
354
- var buf bytes.Buffer
355
- format .Node (& buf , x .conf .Fset , n )
356
- return buf .String ()
351
+ // print returns Go syntax for the specified node.
352
+ func (x * extracter ) print (n ast.Node ) string {
353
+ var buf bytes.Buffer
354
+ format .Node (& buf , x .conf .Fset , n )
355
+ return buf .String ()
356
+ }
357
+
358
+ type packageExtracter struct {
359
+ x * extracter
360
+ info * loader.PackageInfo
361
+ cmap ast.CommentMap
362
+ }
363
+
364
+ func (px packageExtracter ) getComment (n ast.Node ) string {
365
+ cs := px .cmap .Filter (n ).Comments ()
366
+ if len (cs ) > 0 {
367
+ return strings .TrimSpace (cs [0 ].Text ())
357
368
}
369
+ return ""
370
+ }
371
+
372
+ func (x * extracter ) extractMessages () {
358
373
prog := x .iprog
359
374
for _ , info := range x .iprog .AllPackages {
360
375
for _ , f := range info .Files {
361
376
// Associate comments with nodes.
362
- cmap := ast .NewCommentMap (prog .Fset , f , f .Comments )
363
- getComment := func (n ast.Node ) string {
364
- cs := cmap .Filter (n ).Comments ()
365
- if len (cs ) > 0 {
366
- return strings .TrimSpace (cs [0 ].Text ())
367
- }
368
- return ""
377
+ px := packageExtracter {
378
+ x , info ,
379
+ ast .NewCommentMap (prog .Fset , f , f .Comments ),
369
380
}
370
381
371
382
// Find function calls.
372
383
ast .Inspect (f , func (n ast.Node ) bool {
373
- call , ok := n .(* ast.CallExpr )
374
- if ! ok {
375
- return true
376
- }
377
- data := x .funcs [call .Lparen ]
378
- if data == nil || len (data .formats ) == 0 {
379
- return true
384
+ switch v := n .(type ) {
385
+ case * ast.CallExpr :
386
+ return px .handleCall (v )
380
387
}
381
- x .debug (data .call , "INSERT" , data .formats )
388
+ return true
389
+ })
390
+ }
391
+ }
392
+ }
382
393
383
- argn := data .callFormatPos ()
384
- if argn >= len (call .Args ) {
385
- return true
386
- }
387
- format := call .Args [argn ]
388
-
389
- comment := ""
390
- key := []string {}
391
- if ident , ok := format .(* ast.Ident ); ok {
392
- key = append (key , ident .Name )
393
- if v , ok := ident .Obj .Decl .(* ast.ValueSpec ); ok && v .Comment != nil {
394
- // TODO: get comment above ValueSpec as well
395
- comment = v .Comment .Text ()
396
- }
397
- }
394
+ func (px packageExtracter ) handleCall (call * ast.CallExpr ) bool {
395
+ x := px .x
396
+ info := px .info
397
+ data := x .funcs [call .Lparen ]
398
+ if data == nil || len (data .formats ) == 0 {
399
+ return true
400
+ }
401
+ x .debug (data .call , "INSERT" , data .formats )
398
402
399
- arguments := []argument {}
400
- simArgs := []interface {}{}
401
- if data .callArgsStart () >= 0 {
402
- args := call .Args [data .callArgsStart ():]
403
- simArgs = make ([]interface {}, len (args ))
404
- for i , arg := range args {
405
- expr := print (arg )
406
- val := ""
407
- if v := info .Types [arg ].Value ; v != nil {
408
- val = v .ExactString ()
409
- simArgs [i ] = val
410
- switch arg .(type ) {
411
- case * ast.BinaryExpr , * ast.UnaryExpr :
412
- expr = val
413
- }
414
- }
415
- arguments = append (arguments , argument {
416
- ArgNum : i + 1 ,
417
- Type : info .Types [arg ].Type .String (),
418
- UnderlyingType : info .Types [arg ].Type .Underlying ().String (),
419
- Expr : expr ,
420
- Value : val ,
421
- Comment : getComment (arg ),
422
- Position : posString (& x .conf , info .Pkg , arg .Pos ()),
423
- // TODO report whether it implements
424
- // interfaces plural.Interface,
425
- // gender.Interface.
426
- })
427
- }
403
+ argn := data .callFormatPos ()
404
+ if argn >= len (call .Args ) {
405
+ return true
406
+ }
407
+ format := call .Args [argn ]
408
+
409
+ comment := ""
410
+ key := []string {}
411
+ if ident , ok := format .(* ast.Ident ); ok {
412
+ key = append (key , ident .Name )
413
+ if v , ok := ident .Obj .Decl .(* ast.ValueSpec ); ok && v .Comment != nil {
414
+ // TODO: get comment above ValueSpec as well
415
+ comment = v .Comment .Text ()
416
+ }
417
+ }
418
+
419
+ arguments := []argument {}
420
+ simArgs := []interface {}{}
421
+ if data .callArgsStart () >= 0 {
422
+ args := call .Args [data .callArgsStart ():]
423
+ simArgs = make ([]interface {}, len (args ))
424
+ for i , arg := range args {
425
+ expr := x .print (arg )
426
+ val := ""
427
+ if v := info .Types [arg ].Value ; v != nil {
428
+ val = v .ExactString ()
429
+ simArgs [i ] = val
430
+ switch arg .(type ) {
431
+ case * ast.BinaryExpr , * ast.UnaryExpr :
432
+ expr = val
428
433
}
434
+ }
435
+ arguments = append (arguments , argument {
436
+ ArgNum : i + 1 ,
437
+ Type : info .Types [arg ].Type .String (),
438
+ UnderlyingType : info .Types [arg ].Type .Underlying ().String (),
439
+ Expr : expr ,
440
+ Value : val ,
441
+ Comment : px .getComment (arg ),
442
+ Position : posString (& x .conf , info .Pkg , arg .Pos ()),
443
+ // TODO report whether it implements
444
+ // interfaces plural.Interface,
445
+ // gender.Interface.
446
+ })
447
+ }
448
+ }
429
449
430
- formats := data .formats
431
- for _ , c := range formats {
432
- key := append ([]string {}, key ... )
433
- fmtMsg := constant .StringVal (c )
434
- msg := ""
435
-
436
- ph := placeholders {index : map [string ]string {}}
437
-
438
- trimmed , _ , _ := trimWS (fmtMsg )
439
-
440
- p := fmtparser.Parser {}
441
- p .Reset (simArgs )
442
- for p .SetFormat (trimmed ); p .Scan (); {
443
- switch p .Status {
444
- case fmtparser .StatusText :
445
- msg += p .Text ()
446
- case fmtparser .StatusSubstitution ,
447
- fmtparser .StatusBadWidthSubstitution ,
448
- fmtparser .StatusBadPrecSubstitution :
449
- arguments [p .ArgNum - 1 ].used = true
450
- arg := arguments [p .ArgNum - 1 ]
451
- sub := p .Text ()
452
- if ! p .HasIndex {
453
- r , sz := utf8 .DecodeLastRuneInString (sub )
454
- sub = fmt .Sprintf ("%s[%d]%c" , sub [:len (sub )- sz ], p .ArgNum , r )
455
- }
456
- msg += fmt .Sprintf ("{%s}" , ph .addArg (& arg , sub ))
457
- }
458
- }
459
- key = append (key , msg )
460
-
461
- // Add additional Placeholders that can be used in translations
462
- // that are not present in the string.
463
- for _ , arg := range arguments {
464
- if arg .used {
465
- continue
466
- }
467
- ph .addArg (& arg , fmt .Sprintf ("%%[%d]v" , arg .ArgNum ))
468
- }
450
+ formats := data .formats
451
+ for _ , c := range formats {
452
+ key := append ([]string {}, key ... )
453
+ fmtMsg := constant .StringVal (c )
454
+ msg := ""
455
+
456
+ ph := placeholders {index : map [string ]string {}}
457
+
458
+ trimmed , _ , _ := trimWS (fmtMsg )
459
+
460
+ p := fmtparser.Parser {}
461
+ p .Reset (simArgs )
462
+ for p .SetFormat (trimmed ); p .Scan (); {
463
+ switch p .Status {
464
+ case fmtparser .StatusText :
465
+ msg += p .Text ()
466
+ case fmtparser .StatusSubstitution ,
467
+ fmtparser .StatusBadWidthSubstitution ,
468
+ fmtparser .StatusBadPrecSubstitution :
469
+ arguments [p .ArgNum - 1 ].used = true
470
+ arg := arguments [p .ArgNum - 1 ]
471
+ sub := p .Text ()
472
+ if ! p .HasIndex {
473
+ r , sz := utf8 .DecodeLastRuneInString (sub )
474
+ sub = fmt .Sprintf ("%s[%d]%c" , sub [:len (sub )- sz ], p .ArgNum , r )
475
+ }
476
+ msg += fmt .Sprintf ("{%s}" , ph .addArg (& arg , sub ))
477
+ }
478
+ }
479
+ key = append (key , msg )
469
480
470
- if c := getComment (call .Args [0 ]); c != "" {
471
- comment = c
472
- }
481
+ // Add additional Placeholders that can be used in translations
482
+ // that are not present in the string.
483
+ for _ , arg := range arguments {
484
+ if arg .used {
485
+ continue
486
+ }
487
+ ph .addArg (& arg , fmt .Sprintf ("%%[%d]v" , arg .ArgNum ))
488
+ }
473
489
474
- x .messages = append (x .messages , Message {
475
- ID : key ,
476
- Key : fmtMsg ,
477
- Message : Text {Msg : msg },
478
- // TODO(fix): this doesn't get the before comment.
479
- Comment : comment ,
480
- Placeholders : ph .slice ,
481
- Position : posString (& x .conf , info .Pkg , call .Lparen ),
482
- })
483
- }
484
- return true
485
- })
490
+ if c := px .getComment (call .Args [0 ]); c != "" {
491
+ comment = c
486
492
}
493
+
494
+ x .messages = append (x .messages , Message {
495
+ ID : key ,
496
+ Key : fmtMsg ,
497
+ Message : Text {Msg : msg },
498
+ // TODO(fix): this doesn't get the before comment.
499
+ Comment : comment ,
500
+ Placeholders : ph .slice ,
501
+ Position : posString (& x .conf , info .Pkg , call .Lparen ),
502
+ })
487
503
}
504
+ return true
488
505
}
489
506
490
507
func posString (conf * loader.Config , pkg * types.Package , pos token.Pos ) string {
0 commit comments