Skip to content

Commit e60eaad

Browse files
authored
Merge pull request #55 from NathanBaulch/stringslice
Special capacity handling for slice type conversions
2 parents 0f4dc97 + 11918fd commit e60eaad

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

pkg/prealloc.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,12 @@ func isCreateArray(expr ast.Expr) ast.Expr {
336336
}
337337

338338
func appendEllipsisCount(expr ast.Expr) ast.Expr {
339+
if call, ok := expr.(*ast.CallExpr); ok && len(call.Args) == 1 {
340+
if _, ok := call.Fun.(*ast.ArrayType); ok {
341+
expr = call.Args[0]
342+
}
343+
}
344+
339345
if hasCall(expr) {
340346
return nil
341347
}
@@ -372,7 +378,14 @@ func appendEllipsisCount(expr ast.Expr) ast.Expr {
372378
}
373379

374380
func rangeLoopCount(stmt *ast.RangeStmt) (ast.Expr, bool) {
375-
xType := inferExprType(stmt.X)
381+
x := stmt.X
382+
if call, ok := x.(*ast.CallExpr); ok && len(call.Args) == 1 {
383+
if _, ok := call.Fun.(*ast.ArrayType); ok {
384+
x = call.Args[0]
385+
}
386+
}
387+
388+
xType := inferExprType(x)
376389

377390
switch xType := xType.(type) {
378391
case *ast.ChanType, *ast.FuncType:
@@ -385,20 +398,20 @@ func rangeLoopCount(stmt *ast.RangeStmt) (ast.Expr, bool) {
385398
return intExpr(len(lit.Elts)), true
386399
}
387400
case *ast.MapType:
388-
if lit, ok := stmt.X.(*ast.CompositeLit); ok {
401+
if lit, ok := x.(*ast.CompositeLit); ok {
389402
return intExpr(len(lit.Elts)), true
390403
}
391404
case *ast.StarExpr:
392405
if xType, ok := xType.X.(*ast.ArrayType); !ok || xType.Len == nil {
393406
return nil, true
394-
} else if unary, ok := stmt.X.(*ast.UnaryExpr); ok && unary.Op == token.AND {
407+
} else if unary, ok := x.(*ast.UnaryExpr); ok && unary.Op == token.AND {
395408
if _, ok := unary.X.(*ast.CompositeLit); ok {
396409
return xType.Len, true
397410
}
398411
}
399412
case *ast.Ident:
400413
if xType.Name == "string" {
401-
if lit, ok := stmt.X.(*ast.BasicLit); ok && lit.Kind == token.STRING {
414+
if lit, ok := x.(*ast.BasicLit); ok && lit.Kind == token.STRING {
402415
if str, err := strconv.Unquote(lit.Value); err == nil {
403416
return intExpr(len(str)), true
404417
}
@@ -408,22 +421,22 @@ func rangeLoopCount(stmt *ast.RangeStmt) (ast.Expr, bool) {
408421
return nil, true
409422
}
410423

411-
if hasCall(stmt.X) {
424+
if hasCall(x) {
412425
return nil, true
413426
}
414427

415428
if ident, ok := xType.(*ast.Ident); ok {
416429
switch ident.Name {
417430
case "byte", "rune", "int", "int8", "int16", "int32", "int64",
418431
"uint", "uint8", "uint16", "uint32", "uint64", "uintptr":
419-
return stmt.X, true
432+
return x, true
420433
case "string":
421434
default:
422435
return nil, true
423436
}
424437
}
425438

426-
if slice, ok := stmt.X.(*ast.SliceExpr); ok {
439+
if slice, ok := x.(*ast.SliceExpr); ok {
427440
high := slice.High
428441
if high == nil {
429442
high = &ast.CallExpr{Fun: ast.NewIdent("len"), Args: []ast.Expr{slice.X}}
@@ -434,7 +447,7 @@ func rangeLoopCount(stmt *ast.RangeStmt) (ast.Expr, bool) {
434447
return high, true
435448
}
436449

437-
return &ast.CallExpr{Fun: ast.NewIdent("len"), Args: []ast.Expr{stmt.X}}, true
450+
return &ast.CallExpr{Fun: ast.NewIdent("len"), Args: []ast.Expr{x}}, true
438451
}
439452

440453
func forLoopCount(stmt *ast.ForStmt) (ast.Expr, bool) {

testdata/append.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ func appendEllipsisFunc() {
7979
}
8080
}
8181

82+
func appendEllipsisTypeConvert() {
83+
var x []byte // want "Consider preallocating x with capacity 25$"
84+
for range 5 {
85+
x = append(x, []byte("Hello")...)
86+
}
87+
}
88+
8289
func appendMultipleCalls() {
8390
var x []int // want "Consider preallocating x with capacity 10$"
8491
for i := range 5 {

testdata/range.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ func rangeSliceLit() {
9191
}
9292
}
9393

94+
func rangeSliceTypeConvert() {
95+
var x []int // want "Consider preallocating x with capacity 5$"
96+
for i := range []byte("Hello") {
97+
x = append(x, i)
98+
}
99+
}
100+
94101
func rangeArrayVar() {
95102
var a [5]int
96103
var x []int // want "Consider preallocating x with capacity len\\(a\\)$"

0 commit comments

Comments
 (0)