Skip to content

Commit 03644a0

Browse files
committed
Reimplement type aliases. Add a few type alias tests.
1 parent 005e880 commit 03644a0

13 files changed

+106
-33
lines changed

_testing/DESC

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,5 @@ test.0050 - anonymous struct pointer type as a function argument
5151
test.0051 - go parser stops parsing after 10 errors without AllErrors flag
5252
test.0052 - implicit type of a struct within slice/array literal
5353
test.0053 - type redefinition should not inherit method sets
54+
test.0054 - type alias dealiasing
55+
test.0055 - type alias inference

_testing/test.0054/cursor.168

Whitespace-only changes.

_testing/test.0054/out.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Found 4 candidates:
2+
func Foobarer() string
3+
var A int
4+
var B int
5+
var C float64

_testing/test.0054/test.go.in

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package main
2+
3+
type FooBar struct {
4+
A int
5+
B int
6+
C float64
7+
}
8+
9+
func (b *FooBar) Foobarer() string { return "foobarer" }
10+
11+
type Bar = FooBar
12+
13+
func main() {
14+
var b Bar
15+
b.
16+
}

_testing/test.0055/cursor.229

Whitespace-only changes.

_testing/test.0055/out.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Found 3 candidates:
2+
var Jim string
3+
var John string
4+
var Kim string

_testing/test.0055/test.go.in

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package main
2+
3+
type Baz struct {
4+
Jim string
5+
John string
6+
Kim string
7+
}
8+
9+
type FooBar struct {
10+
A int
11+
B int
12+
C float64
13+
}
14+
15+
func (b *FooBar) Foobarer() Baz { return Baz{} }
16+
17+
func main() {
18+
type Bar = FooBar
19+
var b Bar
20+
b.Foobarer().
21+
}

autocompletecontext.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,28 @@ func (c *auto_complete_context) get_candidates_from_set(set map[string]*decl, pa
201201
}
202202
}
203203

204+
func (c *auto_complete_context) get_candidates_from_decl_alias(cc cursor_context, class decl_class, b *out_buffers) {
205+
if cc.decl.flags&decl_visited != 0 {
206+
return
207+
}
208+
209+
cc.decl = cc.decl.type_dealias()
210+
if cc.decl == nil {
211+
return
212+
}
213+
cc.decl.flags |= decl_visited
214+
defer cc.decl.clear_visited()
215+
216+
c.get_candidates_from_decl(cc, class, b)
217+
return
218+
}
219+
204220
func (c *auto_complete_context) get_candidates_from_decl(cc cursor_context, class decl_class, b *out_buffers) {
221+
if cc.decl.class == decl_type_alias {
222+
c.get_candidates_from_decl_alias(cc, class, b)
223+
return
224+
}
225+
205226
// propose all children of a subject declaration and
206227
for _, decl := range cc.decl.children {
207228
if cc.decl.class == decl_package && !ast.IsExported(decl.name) {
@@ -595,6 +616,7 @@ var g_decl_class_to_color = [...]string{
595616
decl_const: color_white_bold,
596617
decl_var: color_magenta,
597618
decl_type: color_cyan,
619+
decl_type_alias: color_cyan,
598620
decl_func: color_green,
599621
decl_package: color_red,
600622
decl_methods_stub: color_red,
@@ -604,6 +626,7 @@ var g_decl_class_to_string_status = [...]string{
604626
decl_const: " const",
605627
decl_var: " var",
606628
decl_type: " type",
629+
decl_type_alias: " type",
607630
decl_func: " func",
608631
decl_package: "package",
609632
decl_methods_stub: " stub",

autocompletefile.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ func (f *auto_complete_file) process_decl(decl ast.Decl) {
135135
prevscope := f.scope
136136
foreach_decl(decl, func(data *foreach_decl_struct) {
137137
class := ast_decl_class(data.decl)
138-
if class != decl_type {
138+
if class != decl_type && class != decl_type_alias {
139139
f.scope, prevscope = advance_scope(f.scope)
140140
}
141141
for i, name := range data.names {

decl.go

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const (
2323
decl_import
2424
decl_package
2525
decl_type
26+
decl_type_alias
2627
decl_var
2728

2829
// this one serves as a temporary type for those methods that were
@@ -44,6 +45,8 @@ func (this decl_class) String() string {
4445
return "package"
4546
case decl_type:
4647
return "type"
48+
case decl_type_alias:
49+
return "type"
4750
case decl_var:
4851
return "var"
4952
case decl_methods_stub:
@@ -127,7 +130,11 @@ func ast_decl_class(d ast.Decl) decl_class {
127130
case token.CONST:
128131
return decl_const
129132
case token.TYPE:
130-
return decl_type
133+
if t.Specs[0].(*ast.TypeSpec).Assign != 0 {
134+
return decl_type_alias
135+
} else {
136+
return decl_type
137+
}
131138
}
132139
case *ast.FuncDecl:
133140
return decl_func
@@ -726,7 +733,7 @@ func infer_type(v ast.Expr, scope *scope, index int) (ast.Expr, *scope, bool) {
726733
return ast.NewIdent(t.Name), scope, false
727734
}
728735
typ, scope := d.infer_type()
729-
return typ, scope, d.class == decl_type
736+
return typ, scope, d.class == decl_type || d.class == decl_type_alias
730737
}
731738
case *ast.UnaryExpr:
732739
switch t.Op {
@@ -878,7 +885,7 @@ func infer_type(v ast.Expr, scope *scope, index int) (ast.Expr, *scope, bool) {
878885
if d := type_to_decl(it, s); d != nil {
879886
c := d.find_child_and_in_embedded(t.Sel.Name)
880887
if c != nil {
881-
if c.class == decl_type {
888+
if c.class == decl_type || c.class == decl_type_alias {
882889
return t, scope, true
883890
} else {
884891
typ, s := c.infer_type()
@@ -927,7 +934,7 @@ func (d *decl) infer_type() (ast.Expr, *scope) {
927934
case decl_package:
928935
// package is handled specially in inferType
929936
return nil, nil
930-
case decl_type:
937+
case decl_type, decl_type_alias:
931938
return ast.NewIdent(d.name), d.scope
932939
}
933940

@@ -948,13 +955,31 @@ func (d *decl) infer_type() (ast.Expr, *scope) {
948955
return d.typ, scope
949956
}
950957

958+
func (d *decl) type_dealias() *decl {
959+
dd := type_to_decl(d.typ, d.scope)
960+
return dd
961+
}
962+
951963
func (d *decl) find_child(name string) *decl {
952964
if d.flags&decl_visited != 0 {
953965
return nil
954966
}
955967
d.flags |= decl_visited
956968
defer d.clear_visited()
957969

970+
// type aliases don't really have any children on their own, but they
971+
// point to a different type, let's try to find one
972+
if d.class == decl_type_alias {
973+
dd := d.type_dealias()
974+
if dd != nil {
975+
return dd.find_child(name)
976+
}
977+
978+
// note that type alias can also point to a type literal, something like
979+
// type A = struct { A int }
980+
// in this case we rely on "advance_to_struct_or_interface" below
981+
}
982+
958983
if d.children != nil {
959984
if c, ok := d.children[name]; ok {
960985
return c
@@ -1301,11 +1326,6 @@ func (f *decl_pack) value_index(i int) (v ast.Expr, vi int) {
13011326

13021327
func (f *decl_pack) type_value_index(i int) (ast.Expr, ast.Expr, int) {
13031328
if f.typ != nil {
1304-
// If there is a type and have f.values, it's type alias decl.
1305-
// Return the both of type and first value.
1306-
if len(f.values) == 1 {
1307-
return f.typ, f.values[0], -1
1308-
}
13091329
// If there is a type, we don't care about value, just return the type
13101330
// and zero value.
13111331
return f.typ, nil, -1

declcache.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,6 @@ func append_to_top_decls(decls map[string]*decl, decl ast.Decl, scope *scope) {
121121
for i, name := range data.names {
122122
typ, v, vi := data.type_value_index(i)
123123

124-
// If typ is *ast.Ident, it holds the underlying type of type alias.
125-
// Replace the typ to underlying types ast.Expr.
126-
if id, ok := typ.(*ast.Ident); ok && id.Obj != nil {
127-
if t, ok := id.Obj.Decl.(*ast.TypeSpec); ok {
128-
if d, ok := decls[t.Name.Name]; ok {
129-
scope.typealias[name.Name] = d
130-
}
131-
132-
typ = t.Type
133-
}
134-
}
135-
136124
d := new_decl_full(name.Name, class, 0, typ, v, vi, scope)
137125
if d == nil {
138126
return
@@ -142,11 +130,6 @@ func append_to_top_decls(decls map[string]*decl, decl ast.Decl, scope *scope) {
142130
if methodof != "" {
143131
decl, ok := decls[methodof]
144132
if ok {
145-
if d, ok := scope.typealias[methodof]; ok {
146-
for _, d := range d.children {
147-
decl.add_child(d)
148-
}
149-
}
150133
decl.add_child(d)
151134
} else {
152135
decl = new_decl(methodof, decl_methods_stub, scope)

package_bin.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,9 @@ func (p *gc_bin_parser) obj(tag int) {
216216
Tok: token.TYPE,
217217
Specs: []ast.Spec{
218218
&ast.TypeSpec{
219-
Name: ast.NewIdent(name),
220-
Type: typ,
219+
Name: ast.NewIdent(name),
220+
Assign: 1, // fake, but gocode only cares if it's there or not
221+
Type: typ,
221222
},
222223
},
223224
})

scope.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,14 @@ package main
55
//-------------------------------------------------------------------------
66

77
type scope struct {
8-
parent *scope // nil for universe scope
9-
entities map[string]*decl
10-
typealias map[string]*decl
8+
parent *scope // nil for universe scope
9+
entities map[string]*decl
1110
}
1211

1312
func new_scope(outer *scope) *scope {
1413
s := new(scope)
1514
s.parent = outer
1615
s.entities = make(map[string]*decl)
17-
s.typealias = make(map[string]*decl)
1816
return s
1917
}
2018

0 commit comments

Comments
 (0)