@@ -370,31 +370,14 @@ type candidate struct {
370
370
// expanded calls for function invocations.
371
371
names []string
372
372
373
- // expandFuncCall is true if obj should be invoked in the completion.
374
- // For example, expandFuncCall=true yields "foo()", expandFuncCall=false yields "foo".
375
- expandFuncCall bool
376
-
377
- // takeAddress is true if the completion should take a pointer to obj.
378
- // For example, takeAddress=true yields "&foo", takeAddress=false yields "foo".
379
- takeAddress bool
373
+ // mods contains modifications that should be applied to the
374
+ // candidate when inserted. For example, "foo" may be insterted as
375
+ // "*foo" or "foo()".
376
+ mods []typeModKind
380
377
381
378
// addressable is true if a pointer can be taken to the candidate.
382
379
addressable bool
383
380
384
- // makePointer is true if the candidate type name T should be made into *T.
385
- makePointer bool
386
-
387
- // dereference is a count of how many times to dereference the candidate obj.
388
- // For example, dereference=2 turns "foo" into "**foo" when formatting.
389
- dereference int
390
-
391
- // takeSlice is true if obj is an array that should be converted to a slice.
392
- takeSlice bool
393
-
394
- // variadic is true if this candidate fills a variadic param and
395
- // needs "..." appended.
396
- variadic bool
397
-
398
381
// convertTo is a type that this candidate should be cast to. For
399
382
// example, if convertTo is float64, "foo" should be formatted as
400
383
// "float64(foo)".
@@ -405,6 +388,15 @@ type candidate struct {
405
388
imp * importInfo
406
389
}
407
390
391
+ func (c candidate ) hasMod (mod typeModKind ) bool {
392
+ for _ , m := range c .mods {
393
+ if m == mod {
394
+ return true
395
+ }
396
+ }
397
+ return false
398
+ }
399
+
408
400
// ErrIsDefinition is an error that informs the user they got no
409
401
// completions because they tried to complete the name of a new object
410
402
// being defined.
@@ -1768,20 +1760,23 @@ func (c *completer) expectedCompositeLiteralType() types.Type {
1768
1760
return nil
1769
1761
}
1770
1762
1771
- // typeModifier represents an operator that changes the expected type.
1772
- type typeModifier struct {
1773
- mod typeMod
1763
+ // typeMod represents an operator that changes the expected type.
1764
+ type typeMod struct {
1765
+ mod typeModKind
1774
1766
arrayLen int64
1775
1767
}
1776
1768
1777
- type typeMod int
1769
+ type typeModKind int
1778
1770
1779
1771
const (
1780
- dereference typeMod = iota // pointer indirection: "*"
1781
- reference // adds level of pointer: "&" for values, "*" for type names
1782
- chanRead // channel read operator ("<-")
1783
- slice // make a slice type ("[]" in "[]int")
1784
- array // make an array type ("[2]" in "[2]int")
1772
+ dereference typeModKind = iota // pointer indirection: "*"
1773
+ reference // adds level of pointer: "&" for values, "*" for type names
1774
+ chanRead // channel read operator: "<-"
1775
+ sliceType // make a slice type: "[]" in "[]int"
1776
+ arrayType // make an array type: "[2]" in "[2]int"
1777
+ invoke // make a function call: "()" in "foo()"
1778
+ takeSlice // take slice of array: "[:]" in "foo[:]"
1779
+ takeDotDotDot // turn slice into variadic args: "..." in "foo..."
1785
1780
)
1786
1781
1787
1782
type objKind int
@@ -1832,7 +1827,7 @@ type candidateInference struct {
1832
1827
1833
1828
// modifiers are prefixes such as "*", "&" or "<-" that influence how
1834
1829
// a candidate type relates to the expected type.
1835
- modifiers []typeModifier
1830
+ modifiers []typeMod
1836
1831
1837
1832
// convertibleTo is a type our candidate type must be convertible to.
1838
1833
convertibleTo types.Type
@@ -1882,7 +1877,7 @@ type typeNameInference struct {
1882
1877
1883
1878
// modifiers are prefixes such as "*", "&" or "<-" that influence how
1884
1879
// a candidate type relates to the expected type.
1885
- modifiers []typeModifier
1880
+ modifiers []typeMod
1886
1881
1887
1882
// assertableFrom is a type that must be assertable to our candidate type.
1888
1883
assertableFrom types.Type
@@ -2108,13 +2103,13 @@ Nodes:
2108
2103
}
2109
2104
return inf
2110
2105
case * ast.StarExpr :
2111
- inf .modifiers = append (inf .modifiers , typeModifier {mod : dereference })
2106
+ inf .modifiers = append (inf .modifiers , typeMod {mod : dereference })
2112
2107
case * ast.UnaryExpr :
2113
2108
switch node .Op {
2114
2109
case token .AND :
2115
- inf .modifiers = append (inf .modifiers , typeModifier {mod : reference })
2110
+ inf .modifiers = append (inf .modifiers , typeMod {mod : reference })
2116
2111
case token .ARROW :
2117
- inf .modifiers = append (inf .modifiers , typeModifier {mod : chanRead })
2112
+ inf .modifiers = append (inf .modifiers , typeMod {mod : chanRead })
2118
2113
}
2119
2114
case * ast.DeferStmt , * ast.GoStmt :
2120
2115
inf .objKind |= kindFunc
@@ -2209,9 +2204,9 @@ func (ci candidateInference) applyTypeNameModifiers(typ types.Type) types.Type {
2209
2204
switch mod .mod {
2210
2205
case reference :
2211
2206
typ = types .NewPointer (typ )
2212
- case array :
2207
+ case arrayType :
2213
2208
typ = types .NewArray (typ , mod .arrayLen )
2214
- case slice :
2209
+ case sliceType :
2215
2210
typ = types .NewSlice (typ )
2216
2211
}
2217
2212
}
@@ -2325,7 +2320,7 @@ Nodes:
2325
2320
}
2326
2321
return typeNameInference {}
2327
2322
case * ast.StarExpr :
2328
- inf .modifiers = append (inf .modifiers , typeModifier {mod : reference })
2323
+ inf .modifiers = append (inf .modifiers , typeMod {mod : reference })
2329
2324
case * ast.CompositeLit :
2330
2325
// We want a type name if position is in the "Type" part of a
2331
2326
// composite literal (e.g. "Foo<>{}").
@@ -2338,7 +2333,7 @@ Nodes:
2338
2333
// the composite literal and not the type name, but if
2339
2334
// affects our type completion nonetheless.
2340
2335
if u , ok := c .path [i + 1 ].(* ast.UnaryExpr ); ok && u .Op == token .AND {
2341
- inf .modifiers = append (inf .modifiers , typeModifier {mod : reference })
2336
+ inf .modifiers = append (inf .modifiers , typeMod {mod : reference })
2342
2337
}
2343
2338
}
2344
2339
}
@@ -2349,13 +2344,13 @@ Nodes:
2349
2344
inf .wantTypeName = true
2350
2345
if n .Len == nil {
2351
2346
// No "Len" expression means a slice type.
2352
- inf .modifiers = append (inf .modifiers , typeModifier {mod : slice })
2347
+ inf .modifiers = append (inf .modifiers , typeMod {mod : sliceType })
2353
2348
} else {
2354
2349
// Try to get the array type using the constant value of "Len".
2355
2350
tv , ok := c .pkg .GetTypesInfo ().Types [n .Len ]
2356
2351
if ok && tv .Value != nil && tv .Value .Kind () == constant .Int {
2357
2352
if arrayLen , ok := constant .Int64Val (tv .Value ); ok {
2358
- inf .modifiers = append (inf .modifiers , typeModifier {mod : array , arrayLen : arrayLen })
2353
+ inf .modifiers = append (inf .modifiers , typeMod {mod : arrayType , arrayLen : arrayLen })
2359
2354
}
2360
2355
}
2361
2356
}
@@ -2417,7 +2412,7 @@ func (c *candidate) anyCandType(f func(t types.Type, addressable bool) bool) boo
2417
2412
if sig , ok := objType .Underlying ().(* types.Signature ); ok {
2418
2413
if sig .Results ().Len () == 1 && f (sig .Results ().At (0 ).Type (), false ) {
2419
2414
// Mark the candidate so we know to append "()" when formatting.
2420
- c .expandFuncCall = true
2415
+ c .mods = append ( c . mods , invoke )
2421
2416
return true
2422
2417
}
2423
2418
}
@@ -2454,8 +2449,10 @@ func (c *candidate) anyCandType(f func(t types.Type, addressable bool) bool) boo
2454
2449
}
2455
2450
2456
2451
if f (ptr .Elem (), false ) {
2457
- // Mark the candidate so we know to prepend "*" when formatting.
2458
- c .dereference = ptrDepth
2452
+ for i := 0 ; i < ptrDepth ; i ++ {
2453
+ // Mark the candidate so we know to prepend "*" when formatting.
2454
+ c .mods = append (c .mods , dereference )
2455
+ }
2459
2456
return true
2460
2457
}
2461
2458
@@ -2465,13 +2462,13 @@ func (c *candidate) anyCandType(f func(t types.Type, addressable bool) bool) boo
2465
2462
// Check if c is addressable and a pointer to c matches our type inference.
2466
2463
if c .addressable && f (types .NewPointer (objType ), false ) {
2467
2464
// Mark the candidate so we know to prepend "&" when formatting.
2468
- c .takeAddress = true
2465
+ c .mods = append ( c . mods , reference )
2469
2466
return true
2470
2467
}
2471
2468
2472
2469
if array , ok := objType .Underlying ().(* types.Array ); ok {
2473
2470
if f (types .NewSlice (array .Elem ()), false ) {
2474
- c .takeSlice = true
2471
+ c .mods = append ( c . mods , takeSlice )
2475
2472
return true
2476
2473
}
2477
2474
}
@@ -2510,15 +2507,17 @@ func (c *completer) matchingCandidate(cand *candidate) bool {
2510
2507
if sig , ok := candType .Underlying ().(* types.Signature ); ok {
2511
2508
if c .inference .assigneesMatch (cand , sig ) {
2512
2509
// Invoke the candidate if its results are multi-assignable.
2513
- cand .expandFuncCall = true
2510
+ cand .mods = append ( cand . mods , invoke )
2514
2511
return true
2515
2512
}
2516
2513
}
2517
2514
2518
2515
// Default to invoking *types.Func candidates. This is so function
2519
2516
// completions in an empty statement (or other cases with no expected type)
2520
2517
// are invoked by default.
2521
- cand .expandFuncCall = isFunc (cand .obj )
2518
+ if isFunc (cand .obj ) {
2519
+ cand .mods = append (cand .mods , invoke )
2520
+ }
2522
2521
2523
2522
return false
2524
2523
}
@@ -2572,7 +2571,7 @@ func (ci *candidateInference) candTypeMatches(cand *candidate) bool {
2572
2571
}
2573
2572
2574
2573
if expType == variadicType {
2575
- cand .variadic = true
2574
+ cand .mods = append ( cand . mods , takeDotDotDot )
2576
2575
}
2577
2576
2578
2577
// Lower candidate score for untyped conversions. This avoids
@@ -2611,7 +2610,7 @@ func (ci *candidateInference) candTypeMatches(cand *candidate) bool {
2611
2610
// matches.
2612
2611
if ci .kindMatches (candType ) {
2613
2612
if ci .objKind == kindFunc {
2614
- cand .expandFuncCall = true
2613
+ cand .mods = append ( cand . mods , invoke )
2615
2614
}
2616
2615
return true
2617
2616
}
@@ -2814,11 +2813,11 @@ func (c *completer) matchingTypeName(cand *candidate) bool {
2814
2813
if c .inference .typeName .compLitType {
2815
2814
// If we are completing a composite literal type as in
2816
2815
// "foo<>{}", to make a pointer we must prepend "&".
2817
- cand .takeAddress = true
2816
+ cand .mods = append ( cand . mods , reference )
2818
2817
} else {
2819
2818
// If we are completing a normal type name such as "foo<>", to
2820
2819
// make a pointer we must prepend "*".
2821
- cand .makePointer = true
2820
+ cand .mods = append ( cand . mods , dereference )
2822
2821
}
2823
2822
return true
2824
2823
}
0 commit comments