-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterface.go
More file actions
101 lines (91 loc) · 2.82 KB
/
Copy pathinterface.go
File metadata and controls
101 lines (91 loc) · 2.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package analysis
import (
"github.com/ProCode-Software/klar/internal/ast"
"github.com/ProCode-Software/klar/internal/klarerrs"
)
type Interface struct {
// Doesn't guarantee compatibility because items can be overidden.
// Guaranteed compatibility for tag keys.
Inherited map[Type]struct{}
ItemAttrs map[string]*Attributes // Attributes for each field/method
DeclaredFields map[string]Type // Explicitly declared, not inherited
DeclaredMethods map[string]*Function // Methods from the interface declaration
order []string // Field and method order, as declared in the source
fmset *FieldMethodSet // Lazy-computed
MethodSet // Extension methods
}
func (*Interface) Kind() Kind { return KindInterface }
func (*Interface) String() string { return "<interface>" }
func (c *Checker) checkInterfaceDecl(o *Object, decl *ast.InterfaceDeclaration) {
fctx := o.LookupContext()
intf := &Interface{
Inherited: c.checkInheritedTypes(decl.InheritedTypes, KindInterface, fctx),
order: make([]string, 0, len(decl.Items)),
DeclaredFields: make(map[string]Type),
DeclaredMethods: make(map[string]*Function),
}
for _, entry := range decl.Items {
// Attributes
attrs := c.parseAttributes(
entry.Attributes, attrTargetKindOf(entry, true),
entry.Range, o.File,
)
if attrs != nil && intf.ItemAttrs == nil {
intf.ItemAttrs = make(map[string]*Attributes)
}
// Method. Redeclared items are checked by the parser
if meth, ok := entry.Value.(*ast.MethodType); ok {
name := entry.Keys[0].Name // Only 1 key, validated by parser
intf.order = append(intf.order, name)
ov := c.checkIntfMethod(entry.Keys[0], meth, fctx)
if par, ok := intf.DeclaredMethods[name]; ok {
par.Overloads = append(par.Overloads, ov) // Another overload
} else {
// First overload
intf.DeclaredMethods[name] = &Function{Overloads: []*Overload{ov}}
}
if attrs != nil {
intf.ItemAttrs[name] = attrs
}
continue
}
// Field
typ := c.parseType(entry.Value, fctx)
for _, key := range entry.Keys {
name := key.Name
intf.order = append(intf.order, name)
intf.DeclaredFields[name] = typ
if attrs != nil {
intf.ItemAttrs[name] = attrs
}
}
}
o.TypeName().Type = intf
}
func (c *Checker) checkIntfMethod(
ident ast.Identifier, meth *ast.MethodType, fctx *Context,
) *Overload {
return nil
}
func (i *Interface) Index(field string, t *Expr) *klarerrs.Error {
if i.DeclaredFields != nil {
if typ, ok := i.DeclaredFields[field]; ok {
t.Type = typ
return nil
}
}
if i.DeclaredMethods != nil {
if meth, ok := i.DeclaredMethods[field]; ok {
t.Type = meth
return nil
}
}
// Extension method
if i.methodMap != nil {
if meth, ok := i.methodMap[field]; ok {
t.Type = meth
return nil
}
}
return fieldNotFound(field)
}