470 lines
10 KiB
Go
470 lines
10 KiB
Go
package manifest
|
|
|
|
import (
|
|
"errors"
|
|
ststrings "strings"
|
|
|
|
"aego/schema"
|
|
"aego/script/abi"
|
|
"aego/script/bind"
|
|
"aego/script/runtime"
|
|
)
|
|
|
|
const Version uint32 = 6
|
|
|
|
type Manifest struct {
|
|
Version uint32
|
|
ABIHash [32]byte
|
|
Modules []Module
|
|
Components []Component
|
|
Enums []Enum
|
|
Structs []Struct
|
|
Events []Event
|
|
Methods []Method
|
|
CompMethods []CompMethod
|
|
Handles []HandleType
|
|
HandleMethods []HandleMethod
|
|
CompSignals []CompSignal
|
|
HandleSignals []HandleSignal
|
|
Keywords map[string]string
|
|
}
|
|
|
|
type HandleType struct {
|
|
Name string
|
|
Await bool
|
|
Doc string
|
|
}
|
|
|
|
type HandleMethod struct {
|
|
Handle string
|
|
Name string
|
|
Sig abi.Signature
|
|
Params []string
|
|
Example string
|
|
Doc string
|
|
Loc string
|
|
}
|
|
|
|
type CompSignal struct {
|
|
Comp string
|
|
Name string
|
|
Params []abi.TypeRef
|
|
Names []string
|
|
Doc string
|
|
}
|
|
|
|
type HandleSignal struct {
|
|
Handle string
|
|
Name string
|
|
Params []abi.TypeRef
|
|
Names []string
|
|
Doc string
|
|
}
|
|
|
|
func (m *Manifest) collectSignals(r *bind.Registry, sr *schema.Registry) {
|
|
t := r.Table()
|
|
for _, c := range t.AllComponents() {
|
|
var td *schema.TypeDescriptor
|
|
if sr != nil {
|
|
td, _ = sr.ByName(c.Name)
|
|
}
|
|
for i, s := range c.Signals {
|
|
cs := CompSignal{Comp: c.Name, Name: s.Name, Params: s.Params}
|
|
if td != nil && i < len(td.Signals) {
|
|
cs.Names, cs.Doc = td.Signals[i].Names, td.Signals[i].Doc
|
|
}
|
|
m.CompSignals = append(m.CompSignals, cs)
|
|
}
|
|
}
|
|
for _, hs := range t.HandleSignalList() {
|
|
info := r.Info("#"+hs.Handle, hs.Def.Name)
|
|
m.HandleSignals = append(m.HandleSignals, HandleSignal{
|
|
Handle: hs.Handle, Name: hs.Def.Name, Params: hs.Def.Params, Names: info.Params, Doc: info.Doc,
|
|
})
|
|
}
|
|
}
|
|
|
|
type CompMethod struct {
|
|
Comp string
|
|
Name string
|
|
Sig abi.Signature
|
|
Params []string
|
|
Example string
|
|
Doc string
|
|
Loc string
|
|
}
|
|
|
|
func (m *Manifest) CompMethodDoc(comp, name string) (CompMethod, bool) {
|
|
if m == nil {
|
|
return CompMethod{}, false
|
|
}
|
|
for _, cm := range m.CompMethods {
|
|
if cm.Comp == comp && cm.Name == name {
|
|
return cm, true
|
|
}
|
|
}
|
|
return CompMethod{}, false
|
|
}
|
|
|
|
func (m *Manifest) HandleMethodDoc(handle, name string) (HandleMethod, bool) {
|
|
if m == nil {
|
|
return HandleMethod{}, false
|
|
}
|
|
for _, hm := range m.HandleMethods {
|
|
if hm.Handle == handle && hm.Name == name {
|
|
return hm, true
|
|
}
|
|
}
|
|
return HandleMethod{}, false
|
|
}
|
|
|
|
func splitHandle(q string) (string, string) {
|
|
i := ststrings.LastIndexByte(q, '.')
|
|
if i < 0 {
|
|
return "", q
|
|
}
|
|
return q[:i], q[i+1:]
|
|
}
|
|
|
|
func (m *Manifest) Keyword(key string) string {
|
|
if m == nil {
|
|
return ""
|
|
}
|
|
return m.Keywords[key]
|
|
}
|
|
|
|
type Module struct {
|
|
Path string
|
|
Funcs []Func
|
|
Consts []Const
|
|
}
|
|
|
|
type Func struct {
|
|
Name string
|
|
Sig abi.Signature
|
|
Params []string
|
|
Example string
|
|
Doc string
|
|
Loc string
|
|
}
|
|
|
|
type Const struct {
|
|
Name string
|
|
Val abi.Const
|
|
Doc string
|
|
}
|
|
|
|
type Component struct {
|
|
Name string
|
|
Short string
|
|
Category string
|
|
Doc string
|
|
Fields []Field
|
|
}
|
|
|
|
type Field struct {
|
|
Name string
|
|
Type abi.TypeRef
|
|
ReadOnly bool
|
|
Doc string
|
|
}
|
|
|
|
type Enum struct {
|
|
Module string
|
|
Name string
|
|
Doc string
|
|
Members []abi.EnumMember
|
|
}
|
|
|
|
type Struct struct {
|
|
Module string
|
|
Name string
|
|
Doc string
|
|
Slots int
|
|
Fields []abi.StructField
|
|
}
|
|
|
|
type Event struct {
|
|
Name string
|
|
Doc string
|
|
Params []abi.TypeRef
|
|
Names []string
|
|
}
|
|
|
|
type Method struct {
|
|
Recv abi.Kind
|
|
Name string
|
|
Sig abi.Signature
|
|
Params []string
|
|
Example string
|
|
Doc string
|
|
Loc string
|
|
}
|
|
|
|
func FromRegistry(r *bind.Registry, sr *schema.Registry) (*Manifest, error) {
|
|
if sr != nil && !sr.Frozen() {
|
|
if err := sr.Freeze(); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if !r.Frozen() {
|
|
if sr != nil {
|
|
runtime.BindComponents(r, sr)
|
|
}
|
|
if err := r.Freeze(); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
t := r.Table()
|
|
m := &Manifest{Version: Version, ABIHash: t.Hash()}
|
|
index := map[string]int{}
|
|
for _, p := range t.ModuleList() {
|
|
index[p] = len(m.Modules)
|
|
m.Modules = append(m.Modules, Module{Path: p})
|
|
}
|
|
for _, f := range t.FuncList() {
|
|
info := r.Info(f.Module, f.Name)
|
|
mod := &m.Modules[index[f.Module]]
|
|
mod.Funcs = append(mod.Funcs, Func{Name: f.Name, Sig: f.Sig, Params: info.Params, Example: info.Example, Doc: info.Doc, Loc: info.Loc})
|
|
}
|
|
for _, c := range t.ConstList() {
|
|
mod := &m.Modules[index[c.Module]]
|
|
mod.Consts = append(mod.Consts, Const{Name: c.Name, Val: c.Val, Doc: r.Info(c.Module, c.Name).Doc})
|
|
}
|
|
for _, e := range t.EnumList() {
|
|
m.Enums = append(m.Enums, Enum{
|
|
Module: e.Module,
|
|
Name: e.Name,
|
|
Doc: r.Info(e.Module, e.Name).Doc,
|
|
Members: append([]abi.EnumMember(nil), e.Members...),
|
|
})
|
|
}
|
|
for _, s := range t.StructList() {
|
|
m.Structs = append(m.Structs, Struct{
|
|
Module: s.Module,
|
|
Name: s.Name,
|
|
Doc: r.Info(s.Module, s.Name).Doc,
|
|
Slots: s.Slots,
|
|
Fields: append([]abi.StructField(nil), s.Fields...),
|
|
})
|
|
}
|
|
for _, h := range t.HandleList() {
|
|
mod, name := splitHandle(h.Name)
|
|
m.Handles = append(m.Handles, HandleType{Name: h.Name, Await: h.Await, Doc: r.Info(mod, name).Doc})
|
|
}
|
|
for _, e := range t.EventList() {
|
|
info := r.Info(bind.EventModule, e.Name)
|
|
m.Events = append(m.Events, Event{Name: e.Name, Doc: info.Doc, Params: append([]abi.TypeRef(nil), e.Params...), Names: info.Params})
|
|
}
|
|
for _, me := range t.MethodList() {
|
|
info := r.Info("#"+me.Recv.String(), me.Name)
|
|
m.Methods = append(m.Methods, Method{Recv: me.Recv, Name: me.Name, Sig: me.Sig, Params: info.Params, Example: info.Example, Doc: info.Doc, Loc: info.Loc})
|
|
}
|
|
for _, cm := range t.ComponentMethodList() {
|
|
info := r.Info("#"+cm.Comp, cm.Name)
|
|
m.CompMethods = append(m.CompMethods, CompMethod{Comp: cm.Comp, Name: cm.Name, Sig: cm.Sig, Params: info.Params, Example: info.Example, Doc: info.Doc, Loc: info.Loc})
|
|
}
|
|
for _, hm := range t.HandleMethodList() {
|
|
info := r.Info("#"+hm.Handle, hm.Name)
|
|
m.HandleMethods = append(m.HandleMethods, HandleMethod{Handle: hm.Handle, Name: hm.Name, Sig: hm.Sig, Params: info.Params, Example: info.Example, Doc: info.Doc, Loc: info.Loc})
|
|
}
|
|
for _, c := range t.AllComponents() {
|
|
m.Components = append(m.Components, component(c, sr))
|
|
}
|
|
m.collectSignals(r, sr)
|
|
return m, nil
|
|
}
|
|
|
|
func component(c *abi.Component, sr *schema.Registry) Component {
|
|
out := Component{Name: c.Name, Short: c.Short}
|
|
out.Category, _, _ = ststrings.Cut(c.Name, ".")
|
|
var fds []*schema.FieldDescriptor
|
|
if sr != nil {
|
|
if td, ok := sr.ByName(c.Name); ok {
|
|
out.Doc = td.Doc
|
|
fds = runtime.ComponentFields(td)
|
|
}
|
|
}
|
|
for i, f := range c.Fields {
|
|
fl := Field{Name: f.Name, Type: f.Type, ReadOnly: f.ReadOnly}
|
|
if i < len(fds) {
|
|
fl.Doc = fds[i].Doc
|
|
}
|
|
out.Fields = append(out.Fields, fl)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (m *Manifest) Table() (*abi.Table, error) {
|
|
t := abi.NewTable()
|
|
for _, mod := range m.Modules {
|
|
if err := t.AddModule(mod.Path); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, e := range m.Enums {
|
|
def := &abi.EnumDef{Module: e.Module, Name: e.Name, Members: append([]abi.EnumMember(nil), e.Members...)}
|
|
if err := t.AddEnum(def); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, s := range m.Structs {
|
|
def := &abi.StructDef{Module: s.Module, Name: s.Name, Slots: s.Slots, Fields: append([]abi.StructField(nil), s.Fields...)}
|
|
if err := t.AddStruct(def); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, h := range m.Handles {
|
|
if err := t.AddHandle(abi.HandleDef{Name: h.Name, Await: h.Await}); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, mod := range m.Modules {
|
|
for _, f := range mod.Funcs {
|
|
if err := t.AddFunc(mod.Path, f.Name, f.Sig); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, c := range mod.Consts {
|
|
if err := t.AddConst(mod.Path, c.Name, c.Val); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
for _, me := range m.Methods {
|
|
if err := t.AddMethod(me.Recv, me.Name, me.Sig); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, cm := range m.CompMethods {
|
|
if err := t.AddComponentMethod(cm.Comp, cm.Name, cm.Sig); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, hm := range m.HandleMethods {
|
|
if err := t.AddHandleMethod(hm.Handle, hm.Name, hm.Sig); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, hs := range m.HandleSignals {
|
|
if err := t.AddHandleSignal(hs.Handle, abi.SignalDef{Name: hs.Name, Params: hs.Params}); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, e := range m.Events {
|
|
if err := t.AddEvent(abi.EventDef{Name: e.Name, Params: e.Params}); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
for _, c := range m.Components {
|
|
ac := &abi.Component{Name: c.Name, Short: c.Short}
|
|
for _, f := range c.Fields {
|
|
ac.Fields = append(ac.Fields, abi.Field{Name: f.Name, Type: f.Type, ReadOnly: f.ReadOnly})
|
|
}
|
|
for _, cs := range m.CompSignals {
|
|
if cs.Comp == c.Name {
|
|
ac.Signals = append(ac.Signals, abi.SignalDef{Name: cs.Name, Params: cs.Params})
|
|
}
|
|
}
|
|
if err := t.AddComponent(ac); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
t.Freeze()
|
|
if m.ABIHash != ([32]byte{}) && t.Hash() != m.ABIHash {
|
|
return nil, errors.New("manifest: abi hash does not match its contents")
|
|
}
|
|
return t, nil
|
|
}
|
|
|
|
func (m *Manifest) FuncDoc(module, name string) (Func, bool) {
|
|
if m == nil {
|
|
return Func{}, false
|
|
}
|
|
for i := range m.Modules {
|
|
if m.Modules[i].Path != module {
|
|
continue
|
|
}
|
|
for _, f := range m.Modules[i].Funcs {
|
|
if f.Name == name {
|
|
return f, true
|
|
}
|
|
}
|
|
}
|
|
return Func{}, false
|
|
}
|
|
|
|
func (m *Manifest) ConstDoc(module, name string) (Const, bool) {
|
|
if m == nil {
|
|
return Const{}, false
|
|
}
|
|
for i := range m.Modules {
|
|
if m.Modules[i].Path != module {
|
|
continue
|
|
}
|
|
for _, c := range m.Modules[i].Consts {
|
|
if c.Name == name {
|
|
return c, true
|
|
}
|
|
}
|
|
}
|
|
return Const{}, false
|
|
}
|
|
|
|
func (m *Manifest) MethodDoc(recv abi.Kind, name string) (Method, bool) {
|
|
if m == nil {
|
|
return Method{}, false
|
|
}
|
|
for _, me := range m.Methods {
|
|
if me.Recv == recv && me.Name == name {
|
|
return me, true
|
|
}
|
|
}
|
|
return Method{}, false
|
|
}
|
|
|
|
func (m *Manifest) Component(name string) (*Component, bool) {
|
|
if m == nil {
|
|
return nil, false
|
|
}
|
|
for i := range m.Components {
|
|
if m.Components[i].Name == name {
|
|
return &m.Components[i], true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
func (c *Component) Field(name string) (Field, bool) {
|
|
for _, f := range c.Fields {
|
|
if f.Name == name {
|
|
return f, true
|
|
}
|
|
}
|
|
return Field{}, false
|
|
}
|
|
|
|
func (m *Manifest) StructDoc(module, name string) (Struct, bool) {
|
|
if m == nil {
|
|
return Struct{}, false
|
|
}
|
|
for _, s := range m.Structs {
|
|
if s.Module == module && s.Name == name {
|
|
return s, true
|
|
}
|
|
}
|
|
return Struct{}, false
|
|
}
|
|
|
|
func (m *Manifest) EventDoc(name string) (Event, bool) {
|
|
if m == nil {
|
|
return Event{}, false
|
|
}
|
|
for _, e := range m.Events {
|
|
if e.Name == name {
|
|
return e, true
|
|
}
|
|
}
|
|
return Event{}, false
|
|
}
|