package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
type Spec struct {
|
|
Arguments []Argument `json:"arguments"`
|
|
ExtraAttributes ExtraAttributes `json:"extAttrs"`
|
|
IDLType IDLType `json:"idlType"`
|
|
Includes []Includes `json:"includes"`
|
|
Inheritance Inheritance `json:"inheritance"`
|
|
RawMembers []Member `json:"members"`
|
|
Name string `json:"name"`
|
|
Partials []Spec `json:"partials"`
|
|
Trivia interface{} `json:"trivia"`
|
|
Type string `json:"type"`
|
|
Values []Value `json:"values"`
|
|
}
|
|
type SpecMap map[string]Spec
|
|
|
|
func LoadSpecs(f string) (specs SpecMap, err error) {
|
|
fp, err := os.Open(f)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
|
|
bytes, err := ioutil.ReadAll(fp)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = json.Unmarshal(bytes, &specs)
|
|
return
|
|
}
|
|
|
|
func (s Spec) Shortname() string {
|
|
return string(strings.ToLower(s.Name)[0])
|
|
}
|
|
|
|
func (s Spec) Receiver() string {
|
|
return fmt.Sprintf("(%s %s)", s.Shortname(), s.Name)
|
|
}
|
|
|
|
func (s Spec) Filename() string {
|
|
return strings.ToLower(s.Name) + ".go"
|
|
}
|
|
|
|
func (s Spec) ResolveInheritance(specs SpecMap) (inheritance []Spec, err error) {
|
|
i := s.Inheritance
|
|
for i.Name != "" {
|
|
// This wasn't defined in any of our sources :(
|
|
if i.Name == "MouseEvent" {
|
|
return
|
|
}
|
|
spec, ok := specs[i.Name]
|
|
if !ok {
|
|
err = fmt.Errorf("Could not find spec for inheritance %q", i.Name)
|
|
return
|
|
}
|
|
inheritance = append(inheritance, spec)
|
|
i = spec.Inheritance
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s Spec) Members() (mems []Member) {
|
|
memMap := make(map[string][]Member)
|
|
for _, m := range s.RawMembers {
|
|
if m.Title() == "" {
|
|
continue
|
|
}
|
|
memMap[m.Title()] = append(memMap[m.Title()], m)
|
|
}
|
|
|
|
for _, members := range memMap {
|
|
if len(members) == 1 {
|
|
// Do nothing
|
|
} else if len(members) == 2 {
|
|
if len(members[1].Body.Arguments) > len(members[0].Body.Arguments) {
|
|
members[1].Body.Name.Value = fmt.Sprintf("%sWithArgs", members[1].Body.Name.Value)
|
|
members[1].Body.Name.Escaped = fmt.Sprintf("%sWithArgs", members[1].Body.Name.Escaped)
|
|
} else if len(members[0].Body.Arguments) > len(members[1].Body.Arguments) {
|
|
members[0].Body.Name.Value = fmt.Sprintf("%sWithArgs", members[0].Body.Name.Value)
|
|
members[0].Body.Name.Escaped = fmt.Sprintf("%sWithArgs", members[0].Body.Name.Escaped)
|
|
}
|
|
} else if s.Name == "WebSocket" && members[0].Title() == "Send" {
|
|
for i, m := range members {
|
|
members[i].Body.Name.Value = fmt.Sprintf("%sWith%s", m.Body.Name.Value, m.Body.Arguments[0].IDLType.IDLType)
|
|
members[i].Body.Name.Escaped = fmt.Sprintf("%sWith%s", m.Body.Name.Escaped, m.Body.Arguments[0].IDLType.IDLType)
|
|
}
|
|
}
|
|
mems = append(mems, members...)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s Spec) ResolveMembers(specs SpecMap, includeParents bool) (mems []Member, err error) {
|
|
parents, err := s.ResolveInheritance(specs)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
memMap := make(map[string]Member)
|
|
|
|
if includeParents {
|
|
for _, p := range parents {
|
|
for _, m := range p.Members() {
|
|
memMap[m.Title()] = m
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, i := range s.Includes {
|
|
p, ok := specs[i.Includes]
|
|
if !ok {
|
|
err = fmt.Errorf("Cannot include unknown type %q", i.Includes)
|
|
return
|
|
}
|
|
|
|
for _, m := range p.Members() {
|
|
memMap[m.Title()] = m
|
|
}
|
|
}
|
|
|
|
for _, p := range s.Partials {
|
|
for _, m := range p.Members() {
|
|
memMap[m.Title()] = m
|
|
}
|
|
}
|
|
|
|
for _, m := range s.Members() {
|
|
memMap[m.Title()] = m
|
|
}
|
|
|
|
for _, m := range memMap {
|
|
mems = append(mems, m)
|
|
}
|
|
|
|
sort.Slice(mems, func(i, j int) bool { return mems[i].Title() < mems[j].Title() })
|
|
return
|
|
}
|