@@ -1445,7 +1445,7 @@ func enclosingCompositeLiteral(path []ast.Node, pos token.Pos, info *types.Info)
1445
1445
1446
1446
return & clInfo
1447
1447
default :
1448
- if breaksExpectedTypeInference (n ) {
1448
+ if breaksExpectedTypeInference (n , pos ) {
1449
1449
return nil
1450
1450
}
1451
1451
}
@@ -1535,11 +1535,11 @@ type typeModifier struct {
1535
1535
type typeMod int
1536
1536
1537
1537
const (
1538
- star typeMod = iota // pointer indirection for expressions, pointer indicator for types
1539
- address // address operator ( "&")
1540
- chanRead // channel read operator ("<-")
1541
- slice // make a slice type ("[]" in "[]int")
1542
- array // make an array type ("[2]" in "[2]int")
1538
+ dereference typeMod = iota // pointer indirection: "*"
1539
+ reference // adds level of pointer: "&" for values, "*" for type names
1540
+ chanRead // channel read operator ("<-")
1541
+ slice // make a slice type ("[]" in "[]int")
1542
+ array // make an array type ("[2]" in "[2]int")
1543
1543
)
1544
1544
1545
1545
type objKind int
@@ -1651,6 +1651,10 @@ type typeNameInference struct {
1651
1651
// seenTypeSwitchCases tracks types that have already been used by
1652
1652
// the containing type switch.
1653
1653
seenTypeSwitchCases []types.Type
1654
+
1655
+ // compLitType is true if we are completing a composite literal type
1656
+ // name, e.g "foo<>{}".
1657
+ compLitType bool
1654
1658
}
1655
1659
1656
1660
// expectedCandidate returns information about the expected candidate
@@ -1862,19 +1866,19 @@ Nodes:
1862
1866
}
1863
1867
return inf
1864
1868
case * ast.StarExpr :
1865
- inf .modifiers = append (inf .modifiers , typeModifier {mod : star })
1869
+ inf .modifiers = append (inf .modifiers , typeModifier {mod : dereference })
1866
1870
case * ast.UnaryExpr :
1867
1871
switch node .Op {
1868
1872
case token .AND :
1869
- inf .modifiers = append (inf .modifiers , typeModifier {mod : address })
1873
+ inf .modifiers = append (inf .modifiers , typeModifier {mod : reference })
1870
1874
case token .ARROW :
1871
1875
inf .modifiers = append (inf .modifiers , typeModifier {mod : chanRead })
1872
1876
}
1873
1877
case * ast.DeferStmt , * ast.GoStmt :
1874
1878
inf .objKind |= kindFunc
1875
1879
return inf
1876
1880
default :
1877
- if breaksExpectedTypeInference (node ) {
1881
+ if breaksExpectedTypeInference (node , c . pos ) {
1878
1882
return inf
1879
1883
}
1880
1884
}
@@ -1928,15 +1932,15 @@ func objChain(info *types.Info, e ast.Expr) []types.Object {
1928
1932
func (ci candidateInference ) applyTypeModifiers (typ types.Type , addressable bool ) types.Type {
1929
1933
for _ , mod := range ci .modifiers {
1930
1934
switch mod .mod {
1931
- case star :
1935
+ case dereference :
1932
1936
// For every "*" indirection operator, remove a pointer layer
1933
1937
// from candidate type.
1934
1938
if ptr , ok := typ .Underlying ().(* types.Pointer ); ok {
1935
1939
typ = ptr .Elem ()
1936
1940
} else {
1937
1941
return nil
1938
1942
}
1939
- case address :
1943
+ case reference :
1940
1944
// For every "&" address operator, add another pointer layer to
1941
1945
// candidate type, if the candidate is addressable.
1942
1946
if addressable {
@@ -1961,8 +1965,7 @@ func (ci candidateInference) applyTypeModifiers(typ types.Type, addressable bool
1961
1965
func (ci candidateInference ) applyTypeNameModifiers (typ types.Type ) types.Type {
1962
1966
for _ , mod := range ci .typeName .modifiers {
1963
1967
switch mod .mod {
1964
- case star :
1965
- // For every "*" indicator, add a pointer layer to type name.
1968
+ case reference :
1966
1969
typ = types .NewPointer (typ )
1967
1970
case array :
1968
1971
typ = types .NewArray (typ , mod .arrayLen )
@@ -2006,9 +2009,17 @@ func findSwitchStmt(path []ast.Node, pos token.Pos, c *ast.CaseClause) ast.Stmt
2006
2009
// breaksExpectedTypeInference reports if an expression node's type is unrelated
2007
2010
// to its child expression node types. For example, "Foo{Bar: x.Baz(<>)}" should
2008
2011
// expect a function argument, not a composite literal value.
2009
- func breaksExpectedTypeInference (n ast.Node ) bool {
2010
- switch n .(type ) {
2011
- case * ast.FuncLit , * ast.CallExpr , * ast.IndexExpr , * ast.SliceExpr , * ast.CompositeLit :
2012
+ func breaksExpectedTypeInference (n ast.Node , pos token.Pos ) bool {
2013
+ switch n := n .(type ) {
2014
+ case * ast.CompositeLit :
2015
+ // Doesn't break inference if pos is in type name.
2016
+ // For example: "Foo<>{Bar: 123}"
2017
+ return ! nodeContains (n .Type , pos )
2018
+ case * ast.CallExpr :
2019
+ // Doesn't break inference if pos is in func name.
2020
+ // For example: "Foo<>(123)"
2021
+ return ! nodeContains (n .Fun , pos )
2022
+ case * ast.FuncLit , * ast.IndexExpr , * ast.SliceExpr :
2012
2023
return true
2013
2024
default :
2014
2025
return false
@@ -2017,13 +2028,7 @@ func breaksExpectedTypeInference(n ast.Node) bool {
2017
2028
2018
2029
// expectTypeName returns information about the expected type name at position.
2019
2030
func expectTypeName (c * completer ) typeNameInference {
2020
- var (
2021
- wantTypeName bool
2022
- wantComparable bool
2023
- modifiers []typeModifier
2024
- assertableFrom types.Type
2025
- seenTypeSwitchCases []types.Type
2026
- )
2031
+ var inf typeNameInference
2027
2032
2028
2033
Nodes:
2029
2034
for i , p := range c .path {
@@ -2034,20 +2039,20 @@ Nodes:
2034
2039
// InterfaceType. We don't need to worry about the field name
2035
2040
// because completion bails out early if pos is in an *ast.Ident
2036
2041
// that defines an object.
2037
- wantTypeName = true
2042
+ inf . wantTypeName = true
2038
2043
break Nodes
2039
2044
case * ast.CaseClause :
2040
2045
// Expect type names in type switch case clauses.
2041
2046
if swtch , ok := findSwitchStmt (c .path [i + 1 :], c .pos , n ).(* ast.TypeSwitchStmt ); ok {
2042
2047
// The case clause types must be assertable from the type switch parameter.
2043
2048
ast .Inspect (swtch .Assign , func (n ast.Node ) bool {
2044
2049
if ta , ok := n .(* ast.TypeAssertExpr ); ok {
2045
- assertableFrom = c .pkg .GetTypesInfo ().TypeOf (ta .X )
2050
+ inf . assertableFrom = c .pkg .GetTypesInfo ().TypeOf (ta .X )
2046
2051
return false
2047
2052
}
2048
2053
return true
2049
2054
})
2050
- wantTypeName = true
2055
+ inf . wantTypeName = true
2051
2056
2052
2057
// Track the types that have already been used in this
2053
2058
// switch's case statements so we don't recommend them.
@@ -2060,7 +2065,7 @@ Nodes:
2060
2065
}
2061
2066
2062
2067
if t := c .pkg .GetTypesInfo ().TypeOf (typeExpr ); t != nil {
2063
- seenTypeSwitchCases = append (seenTypeSwitchCases , t )
2068
+ inf . seenTypeSwitchCases = append (inf . seenTypeSwitchCases , t )
2064
2069
}
2065
2070
}
2066
2071
}
@@ -2072,33 +2077,43 @@ Nodes:
2072
2077
// Expect type names in type assert expressions.
2073
2078
if n .Lparen < c .pos && c .pos <= n .Rparen {
2074
2079
// The type in parens must be assertable from the expression type.
2075
- assertableFrom = c .pkg .GetTypesInfo ().TypeOf (n .X )
2076
- wantTypeName = true
2080
+ inf . assertableFrom = c .pkg .GetTypesInfo ().TypeOf (n .X )
2081
+ inf . wantTypeName = true
2077
2082
break Nodes
2078
2083
}
2079
2084
return typeNameInference {}
2080
2085
case * ast.StarExpr :
2081
- modifiers = append (modifiers , typeModifier {mod : star })
2086
+ inf . modifiers = append (inf . modifiers , typeModifier {mod : reference })
2082
2087
case * ast.CompositeLit :
2083
2088
// We want a type name if position is in the "Type" part of a
2084
2089
// composite literal (e.g. "Foo<>{}").
2085
2090
if n .Type != nil && n .Type .Pos () <= c .pos && c .pos <= n .Type .End () {
2086
- wantTypeName = true
2091
+ inf .wantTypeName = true
2092
+ inf .compLitType = true
2093
+
2094
+ if i < len (c .path )- 1 {
2095
+ // Track preceding "&" operator. Technically it applies to
2096
+ // the composite literal and not the type name, but if
2097
+ // affects our type completion nonetheless.
2098
+ if u , ok := c .path [i + 1 ].(* ast.UnaryExpr ); ok && u .Op == token .AND {
2099
+ inf .modifiers = append (inf .modifiers , typeModifier {mod : reference })
2100
+ }
2101
+ }
2087
2102
}
2088
2103
break Nodes
2089
2104
case * ast.ArrayType :
2090
2105
// If we are inside the "Elt" part of an array type, we want a type name.
2091
2106
if n .Elt .Pos () <= c .pos && c .pos <= n .Elt .End () {
2092
- wantTypeName = true
2107
+ inf . wantTypeName = true
2093
2108
if n .Len == nil {
2094
2109
// No "Len" expression means a slice type.
2095
- modifiers = append (modifiers , typeModifier {mod : slice })
2110
+ inf . modifiers = append (inf . modifiers , typeModifier {mod : slice })
2096
2111
} else {
2097
2112
// Try to get the array type using the constant value of "Len".
2098
2113
tv , ok := c .pkg .GetTypesInfo ().Types [n .Len ]
2099
2114
if ok && tv .Value != nil && tv .Value .Kind () == constant .Int {
2100
2115
if arrayLen , ok := constant .Int64Val (tv .Value ); ok {
2101
- modifiers = append (modifiers , typeModifier {mod : array , arrayLen : arrayLen })
2116
+ inf . modifiers = append (inf . modifiers , typeModifier {mod : array , arrayLen : arrayLen })
2102
2117
}
2103
2118
}
2104
2119
}
@@ -2114,34 +2129,28 @@ Nodes:
2114
2129
break Nodes
2115
2130
}
2116
2131
case * ast.MapType :
2117
- wantTypeName = true
2132
+ inf . wantTypeName = true
2118
2133
if n .Key != nil {
2119
- wantComparable = nodeContains (n .Key , c .pos )
2134
+ inf . wantComparable = nodeContains (n .Key , c .pos )
2120
2135
} else {
2121
2136
// If the key is empty, assume we are completing the key if
2122
2137
// pos is directly after the "map[".
2123
- wantComparable = c .pos == n .Pos ()+ token .Pos (len ("map[" ))
2138
+ inf . wantComparable = c .pos == n .Pos ()+ token .Pos (len ("map[" ))
2124
2139
}
2125
2140
break Nodes
2126
2141
case * ast.ValueSpec :
2127
- wantTypeName = nodeContains (n .Type , c .pos )
2142
+ inf . wantTypeName = nodeContains (n .Type , c .pos )
2128
2143
break Nodes
2129
2144
case * ast.TypeSpec :
2130
- wantTypeName = nodeContains (n .Type , c .pos )
2145
+ inf . wantTypeName = nodeContains (n .Type , c .pos )
2131
2146
default :
2132
- if breaksExpectedTypeInference (p ) {
2147
+ if breaksExpectedTypeInference (p , c . pos ) {
2133
2148
return typeNameInference {}
2134
2149
}
2135
2150
}
2136
2151
}
2137
2152
2138
- return typeNameInference {
2139
- wantTypeName : wantTypeName ,
2140
- wantComparable : wantComparable ,
2141
- modifiers : modifiers ,
2142
- assertableFrom : assertableFrom ,
2143
- seenTypeSwitchCases : seenTypeSwitchCases ,
2144
- }
2153
+ return inf
2145
2154
}
2146
2155
2147
2156
func (c * completer ) fakeObj (T types.Type ) * types.Var {
@@ -2519,7 +2528,15 @@ func (c *completer) matchingTypeName(cand *candidate) bool {
2519
2528
}
2520
2529
2521
2530
if ! isInterface (t ) && typeMatches (types .NewPointer (t )) {
2522
- cand .makePointer = true
2531
+ if c .inference .typeName .compLitType {
2532
+ // If we are completing a composite literal type as in
2533
+ // "foo<>{}", to make a pointer we must prepend "&".
2534
+ cand .takeAddress = true
2535
+ } else {
2536
+ // If we are completing a normal type name such as "foo<>", to
2537
+ // make a pointer we must prepend "*".
2538
+ cand .makePointer = true
2539
+ }
2523
2540
return true
2524
2541
}
2525
2542
0 commit comments