Disambiguate all class and instance method names.

This commit is contained in:
Greg 2019-05-28 13:03:23 -04:00
parent d086c0fdfe
commit 154a2fac14
3 changed files with 159 additions and 138 deletions

View File

@ -23,13 +23,12 @@ func didFinishLaunching(n ns.NSNotification) {
fmt.Println("Go: did finish launching") fmt.Println("Go: did finish launching")
fmt.Printf("Notification: %s\n",n.Name().UTF8String()) fmt.Printf("Notification: %s\n",n.Name().UTF8String())
//Set up an NSWindow //Set up an NSWindow
win = ns.NSWindowAlloc().InitWithContentRect( win = ns.NSWindowAlloc().InitWithContentRectStyleMask(
ns.NSMakeRect(200,200,600,600), ns.NSMakeRect(200,200,600,600),
ns.NSWindowStyleMaskTitled | ns.NSWindowStyleMaskClosable | ns.NSWindowStyleMaskTitled | ns.NSWindowStyleMaskClosable |
ns.NSWindowStyleMaskResizable, ns.NSWindowStyleMaskResizable,
ns.NSBackingStoreBuffered, ns.NSBackingStoreBuffered,
0, 0,
ns.NSScreen{},
) )
// retain win since we called Alloc and did not add it to a collection // retain win since we called Alloc and did not add it to a collection
win.Retain() win.Retain()
@ -83,10 +82,10 @@ func didFinishLaunching(n ns.NSNotification) {
cv := win.ContentView() cv := win.ContentView()
cv.AddSubview(b1.NSView,ns.NSWindowAbove,ns.NSView{}) cv.AddSubview(b1.NSView)
cv.AddSubview(b2.NSView,ns.NSWindowAbove,ns.NSView{}) cv.AddSubview(b2.NSView)
viewmap := ns.NSDictionaryWithObjects( viewmap := ns.NSDictionaryWithObjectsForKeys(
ns.NSArrayWithObjects(b1,b2), ns.NSArrayWithObjects(b1,b2),
ns.NSArrayWithObjects(nst("b1"),nst("b2"))) ns.NSArrayWithObjects(nst("b1"),nst("b2")))

View File

@ -120,7 +120,7 @@ func main() {
hrm_uuid = ns.CBUUIDWithGoString("180D") hrm_uuid = ns.CBUUIDWithGoString("180D")
hrv_uuid = ns.CBUUIDWithGoString("2A37") hrv_uuid = ns.CBUUIDWithGoString("2A37")
cm = ns.CBCentralManagerAlloc().InitWithDelegate(cd,queue,ns.NSDictionary{}) cm = ns.CBCentralManagerAlloc().InitWithDelegateQueue(cd,queue)
select { } select { }
} }

View File

@ -5,6 +5,7 @@ import (
"os" "os"
"path" "path"
"regexp" "regexp"
"sort"
"strconv" "strconv"
"strings" "strings"
@ -145,12 +146,21 @@ type Parameter struct {
} }
type Method struct { type Method struct {
Name, Class, GoClass string Name, GoName, Class, GoClass string
Type *types.Type Type *types.Type
ClassMethod bool ClassMethod bool
Parameters []*Parameter Parameters []*Parameter
} }
//Fully disambiguated method name (m.GoName + all parameter names)
func (m *Method) LongName() string {
ret := m.GoName
for _,p := range m.Parameters {
ret = ret + p.Pname
}
return ret
}
type Enum struct { type Enum struct {
Name string Name string
Type *types.Type Type *types.Type
@ -158,29 +168,64 @@ type Enum struct {
} }
type Protocol struct { type Protocol struct {
Name, GoName string InstanceMethods, ClassMethods *MethodCollection
ClassMethods map[string]*Method
InstanceMethods map[string]*Method
CPolymorphic map[string]int // polymorphic class methods
IPolymorphic map[string]int // polymorphic instance methods
} }
func (p Protocol) name() string { return p.Name } type MethodCollection struct {
func (p Protocol) goName() string { return p.GoName } Class string
func (p Protocol) classMethods() map[string]*Method { return p.ClassMethods } Methods []*Method
func (p Protocol) instanceMethods() map[string]*Method { return p.InstanceMethods } Polymorphic map[string]int
func (p Protocol) cPolymorphic() map[string]int { return p.CPolymorphic }
func (p Protocol) iPolymorphic() map[string]int { return p.IPolymorphic }
type methodCollection interface {
name() string
goName() string
classMethods() map[string]*Method
instanceMethods() map[string]*Method
cPolymorphic() map[string]int
iPolymorphic() map[string]int
} }
func NewMethodCollection(class string) *MethodCollection {
ret := &MethodCollection{
Class: class,
Methods: []*Method{},
Polymorphic: map[string]int{},
}
return ret
}
type ByParams []*Method
func (a ByParams) Len() int { return len(a) }
func (a ByParams) Swap(i,j int) { a[i], a[j] = a[j], a[i] }
func (a ByParams) Less(i, j int) bool { return len(a[i].Parameters) < len(a[j].Parameters) }
//Disambiguate polyorphic method names
func Disambiguate(mc *MethodCollection) {
lst := map[string][]*Method{}
for _,m := range mc.Methods {
lst2 := lst[m.Name]
if lst2 == nil {
lst2 = []*Method{m}
} else {
lst2 = append(lst2,m)
}
lst[m.Name] = lst2
}
mc.Methods = []*Method{}
used := map[string]bool{}
for _,v := range lst {
sort.Sort(ByParams(v))
for _,m := range v {
if len(v) < 2 || len(m.Parameters) < 2 {
mc.Methods = append(mc.Methods,m)
continue
}
i := 2
pname := m.Name + strings.Title(m.Parameters[1].Pname)
for ; used[pname] && i < len(m.Parameters); i++ {
pname = pname + strings.Title(m.Parameters[i].Pname)
}
used[pname] = true
m.GoName = strings.Title(pname)
mc.Methods = append(mc.Methods,m)
}
}
}
//isVoid() returns true if the method has no return value. //isVoid() returns true if the method has no return value.
func (m Method) isVoid() bool { func (m Method) isVoid() bool {
return m.Type.CType() == "void" return m.Type.CType() == "void"
@ -287,22 +332,12 @@ func (w *Wrapper) gpntp(m *Method) ([]string,[]*types.Type,string) {
type Interface struct { type Interface struct {
Name, GoName string Name, GoName string
InstanceMethods, ClassMethods *MethodCollection
Properties map[string]*Property Properties map[string]*Property
ClassMethods map[string]*Method
InstanceMethods map[string]*Method
CPolymorphic map[string]int // polymorphic class methods
IPolymorphic map[string]int // polymorphic instance methods
Protocols []string // Protocols impelemented by this Interface Protocols []string // Protocols impelemented by this Interface
ProcessedInstanceMethods map[string]bool ProcessedInstanceMethods map[string]bool
} }
func (p Interface) name() string { return p.Name }
func (p Interface) goName() string { return p.GoName }
func (p Interface) classMethods() map[string]*Method { return p.ClassMethods }
func (p Interface) instanceMethods() map[string]*Method { return p.InstanceMethods }
func (p Interface) cPolymorphic() map[string]int { return p.CPolymorphic }
func (p Interface) iPolymorphic() map[string]int { return p.IPolymorphic }
func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) { func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
//fmt.Printf("ast.ObjCInterfaceDecl: %s\n",n.Name) //fmt.Printf("ast.ObjCInterfaceDecl: %s\n",n.Name)
w.add(n.Name, n.Children()) w.add(n.Name, n.Children())
@ -325,6 +360,7 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
tp := types.NewTypeFromString(n.Type,"") tp := types.NewTypeFromString(n.Type,"")
m := &Method{ m := &Method{
Name: n.Name, Name: n.Name,
GoName: strings.Title(n.Name),
Type: tp.ReturnType(), Type: tp.ReturnType(),
Class: "", Class: "",
ClassMethod: true, ClassMethod: true,
@ -362,65 +398,46 @@ func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
p := w.Protocols[n.Name] p := w.Protocols[n.Name]
if p == nil { if p == nil {
//fmt.Printf("Adding protocol %s\n",n.Name) //fmt.Printf("Adding protocol %s\n",n.Name)
p = &Protocol{ p = &Protocol{ }
Name: n.Name, //p.GoName = types.NewTypeFromString(n.Name,n.Name).GoType()
GoName: types.NewTypeFromString(n.Name,n.Name).GoType(), p.ClassMethods = NewMethodCollection(n.Name)
ClassMethods: map[string]*Method{}, p.InstanceMethods = NewMethodCollection(n.Name)
InstanceMethods: map[string]*Method{}, p.ClassMethods.Polymorphic = map[string]int{}
CPolymorphic: map[string]int{}, p.InstanceMethods.Polymorphic = map[string]int{}
IPolymorphic: map[string]int{},
}
} }
//fmt.Printf("Protocol %s\n",p.Name) //fmt.Printf("Protocol %s\n",p.Name)
for _,c := range n.Children() { for _,c := range n.Children() {
switch x := c.(type) { switch x := c.(type) {
case *ast.ObjCMethodDecl: case *ast.ObjCMethodDecl:
w.AddMethod(p,x) if x.ClassMethod {
w.AddMethod(p.ClassMethods,x)
} else {
w.AddMethod(p.InstanceMethods,x)
} }
} }
}
Disambiguate(p.InstanceMethods)
Disambiguate(p.ClassMethods)
w.Protocols[n.Name] = p w.Protocols[n.Name] = p
} }
func (w *Wrapper) AddMethod(p methodCollection, x *ast.ObjCMethodDecl) { func (w *Wrapper) AddMethod(p *MethodCollection, x *ast.ObjCMethodDecl) {
m := &Method{ m := &Method{
Name: x.Name, Name: x.Name,
Type: types.NewTypeFromString(x.Type,p.name()), GoName: strings.Title(x.Name),
Class: p.name(), Type: types.NewTypeFromString(x.Type,p.Class),
GoClass: p.goName(), Class: p.Class,
GoClass: strings.Title(p.Class),
ClassMethod: x.ClassMethod, ClassMethod: x.ClassMethod,
} }
//fmt.Printf(" -- Method %s\n",m.Name) //fmt.Printf(" -- Method %s\n",m.Name)
var avail bool var avail bool
m.Parameters, avail = w.GetParms(x,p.name()) m.Parameters, avail = w.GetParms(x,p.Class)
if avail { if avail {
var mth map[string]*Method //fmt.Printf("%s: Adding %s (%d)\n",p.Class,m.Name,len(m.Parameters))
var poly map[string]int p.Polymorphic[m.Name] = p.Polymorphic[m.Name] + 1
if m.ClassMethod { //fmt.Printf("--Method name is %s\n",m.Name)
mth = p.classMethods() p.Methods = append(p.Methods,m)
poly = p.cPolymorphic()
} else {
mth = p.instanceMethods()
poly = p.iPolymorphic()
}
pname := strings.Title(m.Name)
fmt.Printf("%s: Adding %s (%d)\n",p.name(),m.Name,len(m.Parameters))
if x := poly[m.Name]; x != 0 && len(m.Parameters) > 1 {
poly[m.Name] = x + 1
fmt.Printf(" polymorphic detected (%d)\n",poly[m.Name])
pname = pname + strings.Title(m.Parameters[1].Pname)
m.Name = pname
//if m2 := mth[pname]; m2 != nil {
if m2 := mth[m.Name]; m2 != nil {
pname2 := pname + strings.Title(m2.Parameters[1].Pname)
m2.Name = pname2
mth[pname2] = m2
delete(mth,m.Name)
}
} else {
poly[m.Name] = 1
}
fmt.Printf("--Method name is %s\n",m.Name)
mth[pname] = m
} }
} }
@ -474,32 +491,31 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl,rs []string) {
} }
} }
//Add an Interface //Add an Interface or add a Category to an Interface
func (w *Wrapper) add(name string, ns []ast.Node) { func (w *Wrapper) add(name string, ns []ast.Node) {
var i *Interface var i *Interface
var ok bool var ok bool
goname := strings.Title(types.NewTypeFromString(name,name).GoType()) goname := strings.Title(types.NewTypeFromString(name,name).GoType())
types.Wrap(goname) types.Wrap(goname)
if i,ok = w.Interfaces[name]; !ok { if i,ok = w.Interfaces[name]; !ok {
i = &Interface{ i = &Interface{ }
Name: name, i.Name = name
GoName: goname, i.GoName = goname
Properties: map[string]*Property{}, i.Properties = map[string]*Property{}
InstanceMethods: map[string]*Method{}, i.InstanceMethods = NewMethodCollection(name)
CPolymorphic: map[string]int{}, i.ClassMethods = NewMethodCollection(name)
IPolymorphic: map[string]int{}, i.Protocols = []string{}
Protocols: []string{}, i.ProcessedInstanceMethods = map[string]bool{}
ProcessedInstanceMethods: map[string]bool{},
}
m := &Method{ m := &Method{
Name: "class", Name: "class",
GoName: "Class",
Class: i.Name, Class: i.Name,
GoClass: i.Name, GoClass: i.Name,
Type: types.NewTypeFromString("Class",i.Name), Type: types.NewTypeFromString("Class",i.Name),
ClassMethod: true, ClassMethod: true,
Parameters: []*Parameter{}, Parameters: []*Parameter{},
} }
i.ClassMethods = map[string]*Method{"class": m} i.ClassMethods.Methods = []*Method{m}
} }
//var avail bool //var avail bool
for _,c := range ns { for _,c := range ns {
@ -516,27 +532,14 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
//} //}
case *ast.ObjCMethodDecl: case *ast.ObjCMethodDecl:
//fmt.Printf("ObjCMethodDecl: %s (%s) %s\n",x.Type,name,x.Name) //fmt.Printf("ObjCMethodDecl: %s (%s) %s\n",x.Type,name,x.Name)
/*
if name == "NSObject" && x.Name == "initialize" { if name == "NSObject" && x.Name == "initialize" {
continue continue
} }
m := &Method{ if x.ClassMethod {
Name: x.Name, w.AddMethod(i.ClassMethods,x)
Type: types.NewTypeFromString(x.Type,name),
Class: name,
GoClass: goname,
ClassMethod: x.ClassMethod,
}
//fmt.Println(m.Type.Node.String())
m.Parameters, avail = w.GetParms(x,name)
if avail {
if m.ClassMethod {
i.ClassMethods[strings.Title(m.Name)] = m
} else { } else {
i.InstanceMethods[strings.Title(m.Name)] = m w.AddMethod(i.InstanceMethods,x)
} }
}*/
w.AddMethod(i,x)
case *ast.ObjCProtocol: case *ast.ObjCProtocol:
//fmt.Printf("ast.ObjCProtocol: %s\n",x.Name) //fmt.Printf("ast.ObjCProtocol: %s\n",x.Name)
i.Protocols = append(i.Protocols,x.Name) i.Protocols = append(i.Protocols,x.Name)
@ -560,9 +563,12 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
if sup,ok := w.Interfaces[s]; !ok { if sup,ok := w.Interfaces[s]; !ok {
return return
} else { } else {
for _,m := range sup.ClassMethods { //depth first
supmethods(i,types.Super(s))
for _,m := range sup.ClassMethods.Methods {
m2 := &Method{ m2 := &Method{
Name: m.Name, Name: m.Name,
GoName: m.GoName,
Class: i.Name, Class: i.Name,
GoClass: i.GoName, GoClass: i.GoName,
Type: m.Type.CloneToClass(i.Name), Type: m.Type.CloneToClass(i.Name),
@ -577,13 +583,24 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
} }
m2.Parameters = append(m2.Parameters,p2) m2.Parameters = append(m2.Parameters,p2)
} }
i.ClassMethods[strings.Title(m.Name)] = m2 found := false
longname := m2.LongName()
for n,x := range i.ClassMethods.Methods {
if x.LongName() == longname {
i.ClassMethods.Methods[n] = m2
found = true
}
}
if !found {
i.ClassMethods.Methods = append(i.ClassMethods.Methods,m2)
}
} }
} }
supmethods(i,types.Super(s))
} }
supmethods(i,types.Super(i.Name)) supmethods(i,types.Super(i.Name))
//fmt.Println("Add interface ",i.Name) //fmt.Println("Add interface ",i.Name)
Disambiguate(i.ClassMethods)
Disambiguate(i.InstanceMethods)
w.Interfaces[i.Name] = i w.Interfaces[i.Name] = i
} }
@ -802,7 +819,7 @@ func (w *Wrapper) ProcessMethod(m *Method) {
func (w *Wrapper) ProcessMethodForClass(m *Method, class string) { func (w *Wrapper) ProcessMethodForClass(m *Method, class string) {
goclass := strings.Title(types.NewTypeFromString(class,class).GoType()) goclass := strings.Title(types.NewTypeFromString(class,class).GoType())
m2 := &Method{ m2 := &Method{
Name: m.Name, Class: class, GoClass: goclass, Name: m.Name, GoName: m.GoName, Class: class, GoClass: goclass,
Type: m.Type.CloneToClass(class), Type: m.Type.CloneToClass(class),
ClassMethod: m.ClassMethod, ClassMethod: m.ClassMethod,
Parameters: make([]*Parameter,len(m.Parameters)), Parameters: make([]*Parameter,len(m.Parameters)),
@ -832,12 +849,17 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
return return
} }
w.processType(m.Type) w.processType(m.Type)
gname := m.Name gname := m.GoName
gname = strings.ReplaceAll(gname,"_"," ") gname = strings.ReplaceAll(gname,"_"," ")
gname = strings.Title(gname) gname = strings.Title(gname)
gname = strings.ReplaceAll(gname," ","") gname = strings.ReplaceAll(gname," ","")
receiver := "" receiver := ""
cname := m.Name var cname string
if fun {
cname = m.Name
} else {
cname = gname
}
//fmt.Printf("Method %s (GoClass %s)\n",cname,m.GoClass) //fmt.Printf("Method %s (GoClass %s)\n",cname,m.GoClass)
switch { switch {
case !m.ClassMethod: case !m.ClassMethod:
@ -1044,6 +1066,7 @@ func (w *Wrapper) MethodFromSig(sig,class string) *Method {
ret.Type = tp ret.Type = tp
case "Identifier": case "Identifier":
ret.Name = c.Content ret.Name = c.Content
ret.GoName = strings.Title(c.Content)
case "MethodParameter": case "MethodParameter":
p := &Parameter{} p := &Parameter{}
for _,d := range c.Children { for _,d := range c.Children {
@ -1108,7 +1131,7 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
for pname,pats := range ps { for pname,pats := range ps {
pnames[i] = pname pnames[i] = pname
i++ i++
var ms map[string]*Method var ms []*Method
if sub { if sub {
interf := w.Interfaces[pname] interf := w.Interfaces[pname]
supr = interf.GoName supr = interf.GoName
@ -1121,15 +1144,15 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
os.Exit(-1) os.Exit(-1)
} }
//fmt.Printf(" subclass for %s\n",pname) //fmt.Printf(" subclass for %s\n",pname)
ms = map[string]*Method{} ms = []*Method{}
var addmeths func(s string) var addmeths func(s string)
addmeths = func(s string) { addmeths = func(s string) {
if sup := types.Super(s); w.Interfaces[sup] != nil { if sup := types.Super(s); w.Interfaces[sup] != nil {
addmeths(sup) addmeths(sup)
} }
//fmt.Printf("Adding methods for %s\n",s) //fmt.Printf("Adding methods for %s\n",s)
for k,v := range w.Interfaces[s].InstanceMethods { for _,m := range w.Interfaces[s].InstanceMethods.Methods {
ms[k] = v ms = append(ms,m)
} }
} }
//for subclasses, add all superclass methods, depth first //for subclasses, add all superclass methods, depth first
@ -1141,21 +1164,21 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
os.Exit(-1) os.Exit(-1)
} }
//fmt.Printf(" proto %s\n",pname) //fmt.Printf(" proto %s\n",pname)
ms = proto.InstanceMethods ms = proto.InstanceMethods.Methods
fmt.Printf("Protocol %s\n",pname)
types.SetSuper(dname,"Id") types.SetSuper(dname,"Id")
supr = "Id" supr = "Id"
} }
for gname,m := range ms { for _,m := range ms {
//note:we may have capitalized the first character to make a goname, //note:we may have capitalized the first character to make a GoName...
//but m.Name is not disambiguated for polymorphics... if !matches(string(m.Name[0])+m.GoName[1:],pats) {
if !matches(string(m.Name[0])+gname[1:],pats) {
continue continue
} }
if m.Type.IsFunction() || m.Type.IsFunctionPtr() || m.hasFunctionParam() { if m.Type.IsFunction() || m.Type.IsFunctionPtr() || m.hasFunctionParam() {
continue continue
} }
methods = append(methods,m) methods = append(methods,m)
gnames = append(gnames,gname) gnames = append(gnames,m.GoName)
if sub { sms = len(methods) } if sub { sms = len(methods) }
} }
} }
@ -1557,7 +1580,7 @@ func (w *Wrapper) Wrap(toproc []string) {
gname = "Id" gname = "Id"
} }
fmt.Printf("Interface %s: %d properties, %d class methods, %d instance methods\n", fmt.Printf("Interface %s: %d properties, %d class methods, %d instance methods\n",
i.Name, len(i.Properties), len(i.ClassMethods), len(i.InstanceMethods)) i.Name, len(i.Properties), len(i.ClassMethods.Methods), len(i.InstanceMethods.Methods))
w.goCode.WriteString(fmt.Sprintf(` w.goCode.WriteString(fmt.Sprintf(`
func %sAlloc() %s { func %sAlloc() %s {
@ -1590,11 +1613,10 @@ void*
fmt.Printf(" property: %s (%s)\n", p.Name, p.Type.CType()) fmt.Printf(" property: %s (%s)\n", p.Name, p.Type.CType())
} }
} }
//FIXME: sort methods for _,m := range i.ClassMethods.Methods {
for _,m := range i.ClassMethods {
w.ProcessMethod(m) w.ProcessMethod(m)
} }
for _,m := range i.InstanceMethods { for _,m := range i.InstanceMethods.Methods {
w.ProcessMethod(m) w.ProcessMethod(m)
} }
// add methods for Protocols that this interface implements // add methods for Protocols that this interface implements
@ -1604,10 +1626,10 @@ void*
fmt.Printf("Failed to find protocol %s for interface %s\n",p,i.Name) fmt.Printf("Failed to find protocol %s for interface %s\n",p,i.Name)
os.Exit(-1) os.Exit(-1)
} }
for _,m := range prot.ClassMethods { for _,m := range prot.ClassMethods.Methods {
w.ProcessMethodForClass(m,i.Name) w.ProcessMethodForClass(m,i.Name)
} }
for _,m := range prot.InstanceMethods { for _,m := range prot.InstanceMethods.Methods {
w.ProcessMethodForClass(m,i.Name) w.ProcessMethodForClass(m,i.Name)
} }
} }