Update to Big Sur 15.5.2 / Clang 12.0.5. Improved handing of avaiability

attributes and boolean values.
This commit is contained in:
Greg Pomerantz 2021-11-16 16:01:03 -05:00
parent f4a9dae250
commit e4f7e32887
21 changed files with 482 additions and 9157 deletions

5
.gitignore vendored
View File

@ -15,6 +15,9 @@ examples/gc/gc
examples/gc/ns
examples/functions/functions
examples/functions/ns
ns-old
examples/subclass/ns
examples/subclass/subclass
examples/strings/strings
examples/strings/ns
ns-old
outputclang.txt

View File

@ -89,6 +89,8 @@ func Parse(fullline string) Node {
return parseBlockPointerType(line)
case "BreakStmt":
return parseBreakStmt(line)
case "BuiltinAttr":
return parseBuiltinAttr(line)
case "BuiltinType":
return parseBuiltinType(line)
case "CallExpr":

58
ast/builtin_attr.go Normal file
View File

@ -0,0 +1,58 @@
package ast
// BuiltinAttr is a type of attribute that is optionally attached to a variable
// or struct field definition.
type BuiltinAttr struct {
Addr Address
Pos Position
ChildNodes []Node
Implicit bool
Inherited bool
Value string
}
func parseBuiltinAttr(line string) Node {
groups := groupsFromRegex(
`<(?P<position>.*)>
(?P<inherited> Inherited)?
(?P<implicit> Implicit)?
(?P<value> \d+)?
`,
line,
)
if groups == nil {
return &Unknown{}
}
return &BuiltinAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
Inherited: len(groups["inherited"]) > 0,
Implicit: len(groups["implicit"]) > 0,
Value: groups["value"],
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *BuiltinAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *BuiltinAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *BuiltinAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *BuiltinAttr) Position() Position {
return n.Pos
}

56
ast/builtin_attr_test.go Normal file
View File

@ -0,0 +1,56 @@
package ast
import (
"testing"
)
func TestBuiltinAttr(t *testing.T) {
nodes := map[string]testNode{
`0x7fa1488273a0 <line:7:4, line:11:4>`: testNode{&BuiltinAttr{
Addr: 0x7fa1488273a0,
Pos: NewPositionFromString("line:7:4, line:11:4"),
ChildNodes: []Node{},
Inherited: false,
Implicit: false,
},
0x7fa1488273a0,
NewPositionFromString("line:7:4, line:11:4"),
[]Node{},
},
`0x5605ceaf4b88 <col:12> Implicit`: testNode{&BuiltinAttr{
Addr: 0x5605ceaf4b88,
Pos: NewPositionFromString("col:12"),
ChildNodes: []Node{},
Inherited: false,
Implicit: true,
},
0x5605ceaf4b88,
NewPositionFromString("col:12"),
[]Node{},
},
`0x4153c50 </usr/include/unistd.h:779:46> Inherited`: testNode{&BuiltinAttr{
Addr: 0x4153c50,
Pos: NewPositionFromString("/usr/include/unistd.h:779:46"),
ChildNodes: []Node{},
Inherited: true,
Implicit: false,
},
0x4153c50,
NewPositionFromString("/usr/include/unistd.h:779:46"),
[]Node{},
},
`0x1038b8828 <col:20> Inherited Implicit`: testNode{&BuiltinAttr{
Addr: 0x1038b8828,
Pos: NewPositionFromString("col:20"),
ChildNodes: []Node{},
Inherited: true,
Implicit: true,
},
0x1038b8828,
NewPositionFromString("col:20"),
[]Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -18,8 +18,8 @@ type ObjCInterfaceDecl struct {
func parseObjCInterfaceDecl(line string) Node {
groups := groupsFromRegex(
`(?:prev (?P<prev>0x[0-9a-f]+) )?
<(?P<position><invalid sloc>|.*)>
(?P<position2> <invalid sloc>| col:\d+| line:\d+:\d+)
<(?P<position><invalid sloc>|[^>]*)>
(?P<position2>( <invalid sloc>| col:\d+| line:\d+:\d+| <scratch space>:\d+:\d+))
(?P<implicit> implicit)?
(?P<name> \w+)?`,
line,

View File

@ -15,7 +15,7 @@ type ObjCMethodDecl struct {
Parameters []string
Type string
Type2 string
Attr string
Attr []string
ChildNodes []Node
}
@ -27,7 +27,7 @@ func parseObjCMethodDecl(line string) Node {
(?P<implicit> implicit)?
(?P<methodtype> \+| \-)
(?P<names>.*?)
'(?P<type>[^']*?)'
'(?P<type>.*?)'
(:'(?P<type2>.*?)')?
(?P<attr> .*)?`,
line,
@ -43,6 +43,8 @@ func parseObjCMethodDecl(line string) Node {
params = parts[:len(parts)-1]
}
attrs := strings.Split(strings.TrimSpace(groups["attr"]), " ")
return &ObjCMethodDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
@ -53,7 +55,7 @@ func parseObjCMethodDecl(line string) Node {
Parameters: params,
Type: strings.TrimSpace(groups["type"]),
//Type2: strings.TrimSpace(groups["type2"]),
Attr: strings.TrimSpace(groups["attr"]),
Attr: attrs,
ChildNodes: []Node{},
}
}

View File

@ -16,6 +16,7 @@ func TestObjCMethodDecl(t *testing.T) {
ClassMethod: false,
Parameters: []string{"isEqual"},
Implicit: false,
Attr: []string{""},
ChildNodes: []Node{},
},
0x7f92a58a7570,
@ -32,6 +33,7 @@ func TestObjCMethodDecl(t *testing.T) {
ClassMethod: false,
Parameters: []string{},
Implicit: false,
Attr: []string{""},
ChildNodes: []Node{},
},
0x7f92a58a7978,
@ -48,6 +50,7 @@ func TestObjCMethodDecl(t *testing.T) {
ClassMethod: false,
Parameters: []string{"respondsToSelector"},
Implicit: false,
Attr: []string{""},
ChildNodes: []Node{},
},
0x7f92a58a82b0,
@ -64,6 +67,7 @@ func TestObjCMethodDecl(t *testing.T) {
ClassMethod: true,
Parameters: []string{"instancesRespondToSelector"},
Implicit: false,
Attr: []string{""},
ChildNodes: []Node{},
},
0x7f92a58a82b0,
@ -80,6 +84,7 @@ func TestObjCMethodDecl(t *testing.T) {
ClassMethod: false,
Parameters: []string{"performSelector", "withObject", "withObject"},
Implicit: false,
Attr: []string{""},
ChildNodes: []Node{},
},
0x7f92a58a7cd8,
@ -96,6 +101,7 @@ func TestObjCMethodDecl(t *testing.T) {
ClassMethod: false,
Parameters: []string{},
Implicit: true,
Attr: []string{""},
ChildNodes: []Node{},
},
0x7f92a4459318,

View File

@ -34,7 +34,7 @@ func didFinishLaunching(self ns.AppDelegate, n *ns.NSNotification) {
ns.NSWindowStyleMask(ns.NSWindowStyleMaskTitled|ns.NSWindowStyleMaskClosable|
ns.NSWindowStyleMaskResizable),
ns.NSBackingStoreType(ns.NSBackingStoreBuffered),
0,
false,
)
// We do not need to retain this because we are in garbage collection mode
// and have assigned it to a global variable.
@ -86,8 +86,8 @@ func didFinishLaunching(self ns.AppDelegate, n *ns.NSNotification) {
//add some layout constraints
b1.SetTranslatesAutoresizingMaskIntoConstraints(0)
b2.SetTranslatesAutoresizingMaskIntoConstraints(0)
b1.SetTranslatesAutoresizingMaskIntoConstraints(false)
b2.SetTranslatesAutoresizingMaskIntoConstraints(false)
cv := win.ContentView()
@ -105,12 +105,12 @@ func didFinishLaunching(self ns.AppDelegate, n *ns.NSNotification) {
cv.AddConstraints(ns.NSLayoutConstraintsWithVisualFormat(
nst("H:[b1]-[b2]"), ns.NSLayoutFormatOptions(ns.NSLayoutFormatAlignAllBaseline), nil, viewmap))
a.ActivateIgnoringOtherApps(1)
a.ActivateIgnoringOtherApps(true)
}
func shouldTerminateAfterLastWindowClosed(self ns.AppDelegate, s *ns.NSApplication) ns.BOOL {
fmt.Println("Go: should terminate after last window closed")
return 1
return true
}
func willTerminate(self ns.AppDelegate, n *ns.NSNotification) {

View File

@ -10,7 +10,7 @@ import (
"time"
)
func updateState(self ns.CBDelegate, c *ns.CBCentralManager, b bool) {
func updateState(self ns.CBDelegate, c *ns.CBCentralManager) {
fmt.Printf("Go: did update state\n")
switch ns.NSInteger(cm.CBManager.State()) {
case ns.CBManagerStateUnknown:
@ -107,7 +107,7 @@ func discoverCharacteristics(self ns.CBDelegate, p *ns.CBPeripheral, s *ns.CBSer
chuuid := chr.UUID()
fmt.Printf("------%s\n", chuuid.UUIDString())
if chuuid.IsEqualTo(hrv_uuid) {
p.SetNotifyValue(1, chr)
p.SetNotifyValue((ns.BOOL)(true), chr)
v := chr.Value()
fmt.Println(hr(v))
}

View File

@ -110,7 +110,7 @@ func main() {
fmt.Printf("Length of oarr is %d\n", len(oarr))
karr := make([]*ns.Id, 0, 5)
fmt.Printf("\nGetObjectsAndKeysCount()\n")
d.GetObjectsAndKeysCount(&oarr, &karr, 4)
d.GetObjectsAndKeys(&oarr, &karr, 4)
fmt.Printf("Length of oarr is now %d\n", len(oarr))
for i, k := range karr {
fmt.Printf("-- %s -> %s\n", k.NSString(), oarr[i].NSString())
@ -150,7 +150,7 @@ func main() {
ost := make([]*ns.NSString, 0, 1)
oar := make([]*ns.NSArray, 0, 1)
fmt.Printf("\nCompletePathIntoString()\n")
i := path.CompletePathIntoString(&ost, 0, &oar, filter)
i := path.CompletePathIntoString(&ost, false, &oar, filter)
fmt.Printf("%d matches\n", i)
if i > 0 {
fmt.Printf("ost = %s\n", ost[0])

View File

@ -1,58 +0,0 @@
package ns
/*
#cgo CFLAGS: -x objective-c -fno-objc-arc
#cgo LDFLAGS: -framework Foundation
#pragma clang diagnostic ignored "-Wformat-security"
#import <Foundation/Foundation.h>
*/
import "C"
import (
"unsafe"
)
//export C1Dealloc
func C1Dealloc(o unsafe.Pointer) {
C1Mux.RLock()
cb := C1Lookup[o].Dealloc
C1Mux.RUnlock()
if cb == nil { return }
self := C1{}
self.ptr = o
super := C1Supermethods{
self.SuperDealloc,
self.SuperRelease,
}
cb(self, super)
}
//export C1Release
func C1Release(o unsafe.Pointer) {
C1Mux.RLock()
cb := C1Lookup[o].Release
C1Mux.RUnlock()
if cb == nil { return }
self := C1{}
self.ptr = o
super := C1Supermethods{
self.SuperDealloc,
self.SuperRelease,
}
cb(self, super)
}
//export C2MyMethod
func C2MyMethod(o unsafe.Pointer) {
C2Mux.RLock()
cb := C2Lookup[o].MyMethod
C2Mux.RUnlock()
if cb == nil { return }
self := C2{}
self.ptr = o
cb(self)
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

8
go.mod Normal file
View File

@ -0,0 +1,8 @@
module git.wow.st/gmp/nswrap
go 1.16
require (
github.com/a8m/envsubst v1.2.0
gopkg.in/yaml.v2 v2.4.0
)

5
go.sum Normal file
View File

@ -0,0 +1,5 @@
github.com/a8m/envsubst v1.2.0 h1:yvzAhJD2QKdo35Ut03wIfXQmg+ta3wC/1bskfZynz+Q=
github.com/a8m/envsubst v1.2.0/go.mod h1:PpvLvNWa+Rvu/10qXmFbFiGICIU5hZvFJNPCCkUaObg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

View File

@ -453,7 +453,7 @@ func GoToC(sname, name string, pnames, snames []string, rtype *Type, ptypes []*T
ret.ptr = unsafe.Pointer(`, rtgt[1:]))
default:
if rtgt == "BOOL" {
ret.WriteString("ret := (")
ret.WriteString("ret := (bool)(")
rtgt = "bool"
} else {
ret.WriteString("ret := (" + rtgt + ")(")
@ -501,9 +501,6 @@ func GoToC(sname, name string, pnames, snames []string, rtype *Type, ptypes []*T
if isptr {
ret.WriteString(")")
}
if rt == "BOOL" {
ret.WriteString(" != 0")
}
for i, sname := range snames {
if sname == "" {
continue

View File

@ -286,7 +286,7 @@ func (o *Id) NSString() *NSString {
rtype = bl
chk_gotoc(
`ret := (C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))) != 0
`ret := (bool)(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4)))
runtime.KeepAlive(o)
return ret`)

View File

@ -37,6 +37,7 @@ func MethodSignature(s string, n *Node) (string, *Node) {
Parenthesized(TypeName),
Identifier,
Opt(MethodParameterList),
Opt(Word("NS_RETURNS_INNER_POINTER")),
))(s, n)
}
@ -66,6 +67,16 @@ func MethodParameter(s string, n *Node) (string, *Node) {
func _TypeName(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("TypeName"), Seq(
Opt(APIAvailable),
Opt(APIUnavailable),
Opt(SwiftUnavailable),
Opt(APIDeprecated),
Opt(APIDeprecatedWithReplacement),
Opt(NSAvailable),
Opt(NSAvailableMac),
Opt(NSDeprecated),
Opt(DispatchReturns),
Opt(ReturnsInnerPointer),
SpecifierQualifierList,
Opt(AbstractDeclarator),
))(s, n)
@ -256,6 +267,80 @@ func TypeQualifier(s string, n *Node) (string, *Node) {
))(s, n)
}
func APIAvailable(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("APIAvailable"), Seq(
Word("API_AVAILABLE"),
Parenthesized(NodeNamed("Version",Regexp(`\w+\(\d+(\.\d+(\.\d+)?)?\)`))),
))(s, n)
}
func APIUnavailable(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("APIUnavailable"), Seq(
Word("API_UNAVAILABLE"),
Parenthesized(NodeNamed("Version",Regexp(`[^)]*`))),
))(s, n)
}
func APIDeprecated(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("APIDeprecated"), Seq(
NodeNamed("APIDeprecated",Regexp(`API_DEPRECATED`)),
Parenthesized(Seq(
NodeNamed("Message",Regexp(`"[^"]*"`)),
Lit(","),
NodeNamed("Version",Regexp(`\w+\(\d+(\.\d+)?,\s*((\d+(\.\d+)?)|(API_TO_BE_DEPRECATED))\)`)),
)),
))(s, n)
}
func APIDeprecatedWithReplacement(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("APIDeprecated"), Seq(
NodeNamed("APIDeprecated",Regexp(`API_DEPRECATED_WITH_REPLACEMENT`)),
Parenthesized(Seq(
NodeNamed("Message",Regexp(`"[^"]*"`)),
Lit(","),
NodeNamed("Version",Regexp(`\w+\(\d+(\.\d+)?,\s*((\d+(\.\d+)?)|(API_TO_BE_DEPRECATED))\)`)),
)),
))(s, n)
}
func SwiftUnavailable(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("SwiftUnavailable"), Seq(
Word("NS_SWIFT_UNAVAILABLE"),
Parenthesized(NodeNamed("Message",Regexp(`[^)]*`))),
))(s, n)
}
func NSAvailable(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("NSAvailable"), Seq(
Word("NS_AVAILABLE"),
Parenthesized(NodeNamed("Versions",Regexp(`\d+_\d+(,\s*\d+_\d+)?`))),
))(s, n)
}
func NSAvailableMac(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("NSAvailableMac"), Seq(
Word("NS_AVAILABLE_MAC"),
Parenthesized(NodeNamed("Versions",Regexp(`\d+_\d+(,\s*\d+_\d+)?`))),
))(s, n)
}
func NSDeprecated(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("NSDeprecated"), Seq(
Word("NS_DEPRECATED"),
Parenthesized(NodeNamed("Versions",Regexp(`\d+_\d+(,\s*\d+_\d+(,\s*\d+_\d+(,\s*\d+_\d+)?)?)?`))),
))(s, n)
}
func DispatchReturns(s string, n *Node) (string, *Node) {
return NodeNamed("DispatchReturns",Regexp("DISPATCH_[A-Z_]+"))(s, n)
}
func ReturnsInnerPointer(s string, n *Node) (string, *Node) {
return ChildOf(NewNode("ReturnsInnerPointer"),
Word("NS_RETURNS_INNER_POINTER"),
)(s, n)
}
func StructOrUnionSpecifier(s string, n *Node) (string, *Node) {
return OneOf(
// Seq(StructOrUnion,Opt(Identifier),StructDeclarationList),

View File

@ -117,13 +117,22 @@ func (n *Node) IsArray() bool {
return n.ArrayOf() != nil
}
func isQualifier(s string) bool {
return (s == "KindQualifier" ||
s == "APIAvailable" ||
s == "APIUnavailable" ||
s == "APIDeprecated" ||
s == "SwiftUnavailable" ||
s == "NSAvailable" ||
s == "NSAvailableMac")
}
func (n *Node) IsStruct() bool {
if n == nil || len(n.Children) < 1 {
return false
}
i := 0
for ; i < len(n.Children) &&
n.Children[i].Kind == "KindQualifier"; i++ {
for ; i < len(n.Children) && isQualifier(n.Children[i].Kind); i++ {
}
return n.Children[i].Kind == "Struct"
}
@ -152,8 +161,7 @@ func (n *Node) IsId() bool {
return false
}
i := 0
for ; i < len(n.Children) &&
n.Children[i].Kind == "KindQualifier"; i++ {
for ; i < len(n.Children) && isQualifier(n.Children[i].Kind); i++ {
}
return !n.IsFunction() &&
n.Children[i].Kind == "TypedefName" &&
@ -165,8 +173,7 @@ func (n *Node) IsInstancetype() bool {
return false
}
i := 0
for ; i < len(n.Children) &&
n.Children[i].Kind == "KindQualifier"; i++ {
for ; i < len(n.Children) && isQualifier(n.Children[i].Kind); i++ {
}
return n.Children[i].Kind == "TypedefName" &&
n.Children[i].Content == "instancetype"

View File

@ -127,6 +127,16 @@ func (n *Node) _CType(ignore map[string]bool) string {
return ret
}
switch n.Kind {
case "APIAvailable":
case "DispatchReturns":
case "APIUnavailable":
case "APIDeprecated":
case "APIDeprecatedWithReplacement":
case "NSAvailable":
case "NSAvailableMac":
case "NSDeprecated":
case "SwiftUnavailable":
case "ReturnsInnerPointer":
case "Parenthesized":
ret.WriteString("(" + strings.Join(childStrings(n), " ") + ")")
case "Function":

View File

@ -20,6 +20,7 @@ var (
Arc = false
Autorelease = false
Gogc = false
dbclass = ""
)
type Wrapper struct {
@ -237,6 +238,7 @@ type Protocol struct {
type MethodCollection struct {
Class, GoClass string
Methods []*Method
Unavailable map[string]bool
}
func NewMethodCollection(class string) *MethodCollection {
@ -244,6 +246,7 @@ func NewMethodCollection(class string) *MethodCollection {
Class: class,
GoClass: strings.Title(class),
Methods: []*Method{},
Unavailable: make(map[string]bool),
}
return ret
}
@ -256,6 +259,11 @@ func (a ByParams) Less(i, j int) bool { return len(a[i].Parameters) < len(a[j].P
//Disambiguate overloaded method names
func Disambiguate(mc *MethodCollection) {
prt := false
if mc.Class == dbclass {
prt = true
fmt.Printf("Disambiguate(%s)\n", mc.Class)
}
lst := map[string][]*Method{}
for _, m := range mc.Methods {
lst2 := lst[m.Name]
@ -285,6 +293,9 @@ func Disambiguate(mc *MethodCollection) {
}
used[pname] = true
m.GoName = strings.Title(pname)
if prt {
fmt.Printf(" -> %s(%s)\n", m.Name, pname)
}
mc.Methods = append(mc.Methods, m)
}
}
@ -471,6 +482,7 @@ func (w *Wrapper) AddCategory(n *ast.ObjCCategoryDecl) {
}
func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
prt := false
//treat functions as class methods with no class
tp := types.NewTypeFromString(n.Type, "")
m := &Method{
@ -517,7 +529,7 @@ func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
m.Parameters = append(m.Parameters, p)
i++
case *ast.AvailabilityAttr, *ast.UnavailableAttr, *ast.DeprecatedAttr:
a.Add(x)
a.Add(x, prt)
}
}
if a.Available() {
@ -561,6 +573,16 @@ func (w *Wrapper) AddProtocol(n *ast.ObjCProtocolDecl) {
}
func (w *Wrapper) AddMethod(p *MethodCollection, x *ast.ObjCMethodDecl) {
prt := false
if p.Class == dbclass {
prt = true
fmt.Printf("%s -> adding %s\n", dbclass, x.Name)
}
tp := types.NewTypeFromString(x.Type, p.Class)
if tp.String() == "" {
fmt.Printf("AddMethod(%s): type is empty.\n", x.Name)
fmt.Printf("x.Type = %s\n", x.Type)
}
m := &Method{
Name: x.Name,
GoName: strings.Title(x.Name),
@ -571,20 +593,32 @@ func (w *Wrapper) AddMethod(p *MethodCollection, x *ast.ObjCMethodDecl) {
Unavailable: false,
}
if Debug {
fmt.Printf(" -- Method %s\n", m.Name)
fmt.Printf(" -- Method %s type %s\n", m.Name, m.Type.CType())
}
var avail bool
m.Parameters, avail, m.Unavailable = w.GetParms(x, p.Class)
m.Parameters, avail, m.Unavailable = w.GetParms(x, p.Class, prt)
if avail {
if Debug {
fmt.Printf("%s: Adding %s (%d)\n", p.Class, m.Name, len(m.Parameters))
if Debug || prt {
fmt.Printf("%s: Adding %s (%d) type %s\n", p.Class, m.Name, len(m.Parameters), m.Type.GoType())
}
p.Methods = append(p.Methods, m)
// p.Methods = append(p.Methods, m)
} else {
if Debug {
m.Unavailable = true
p.Unavailable[m.LongName()] = true
if m.Name == "init" {
y := w.Interfaces[p.Class]
if y != nil {
if prt {
fmt.Printf(" Marking new method as unavailable for %s\n", p.Class)
}
y.ClassMethods.Unavailable["New"] = true
}
}
if Debug || prt {
fmt.Printf("--Method %s is not available\n", m.Name)
}
}
p.Methods = append(p.Methods, m)
}
//FIXME: copied from nswrap/main.go, should put this in a utils package
@ -598,6 +632,7 @@ func matches(x string, rs []string) bool {
}
func (w *Wrapper) AddEnum(n *ast.EnumDecl, rs []string) {
prt := false
if n.Name != "" && !matches(n.Name, rs) {
return
}
@ -622,7 +657,7 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl, rs []string) {
for _, c := range n.Children() {
switch x := c.(type) {
case *ast.AvailabilityAttr, *ast.UnavailableAttr, *ast.DeprecatedAttr:
a.Add(x)
a.Add(x, prt)
case *ast.EnumConstantDecl:
if Debug {
fmt.Printf("*ast.EnumConstantDecl: (%s) '%s': %s\n", n.Type, n.Name, x.Name)
@ -649,6 +684,13 @@ func (w *Wrapper) AddEnum(n *ast.EnumDecl, rs []string) {
//Add an Interface or add a Category to an Interface
func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
prt := false
if name == dbclass {
prt = true
}
if Debug || prt {
fmt.Printf("addIntCat(%s)\n", name)
}
var i *Interface
var ok bool
goname := strings.Title(name)
@ -662,6 +704,7 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
i.Properties = map[string]*Property{}
i.Protocols = []string{}
i.ProcessedInstanceMethods = map[string]bool{}
w.Interfaces[name] = i
}
avail := (*Avail)(&[]AvailAttr{})
mcc := NewMethodCollection(name)
@ -670,18 +713,19 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
for _, c := range ns {
switch x := c.(type) {
case *ast.ObjCPropertyDecl:
if Debug {
fmt.Printf("ObjCPropertyDecl: %s\n", x.Name)
}
p := &Property{
Name: x.Name,
Type: types.NewTypeFromString(x.Type, name),
Attr: x.Attr,
}
if Debug {
fmt.Printf("ObjCPropertyDecl: %s %s (%s)\n", x.Type, x.Name, p.Type.GoType())
}
i.Properties[x.Name] = p
case *ast.ObjCMethodDecl:
if Debug {
if Debug || prt {
fmt.Printf("ObjCMethodDecl: %s (%s) %s\n", x.Type, name, x.Name)
fmt.Printf(" type = %s\n", x.Type)
}
if name == "NSObject" && x.Name == "initialize" {
continue
@ -709,14 +753,15 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
}
types.SetTypeParam(name, x.Name, x.Type)
case *ast.AvailabilityAttr, *ast.UnavailableAttr, *ast.DeprecatedAttr:
avail.Add(x)
avail.Add(x, prt)
case *ast.Unknown:
if Debug {
fmt.Printf("(*ast.Unkonwn %s: %s)\n", x.Name, x.Content)
}
case *ast.ObjCRootClassAttr, *ast.VisibilityAttr,
*ast.ObjCIvarDecl, *ast.ArcWeakrefUnavailableAttr,
*ast.ObjCExceptionAttr, *ast.SwiftNameAttr:
*ast.ObjCExceptionAttr, *ast.SwiftNameAttr,
*ast.FullComment:
default:
fmt.Printf("AST parse error: node type is %s\n", reflect.TypeOf(x).String())
}
@ -728,7 +773,25 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
return
}
i.ClassMethods.Methods = append(i.ClassMethods.Methods, mcc.Methods...)
for k,v := range mcc.Unavailable {
if prt {
fmt.Printf(" class method %s: %t\n", k, v)
}
i.ClassMethods.Unavailable[k] = v
}
i.InstanceMethods.Methods = append(i.InstanceMethods.Methods, mci.Methods...)
for k,v := range mci.Unavailable {
if prt {
fmt.Printf(" instance method %s: %t\n", k, v)
}
i.InstanceMethods.Unavailable[k] = v
if k == "init" {
if prt {
fmt.Printf(" Marking new method as unavailable for %s\n", i.Name)
}
i.ClassMethods.Unavailable["New"] = true
}
}
i.Protocols = append(i.Protocols, prots...)
if Debug {
@ -748,11 +811,11 @@ type AvailAttr struct {
type Avail []AvailAttr
func (a *Avail) Add(n ast.Node) {
func (a *Avail) Add(n ast.Node, prt bool) {
switch x := n.(type) {
case *ast.AvailabilityAttr:
if Debug {
fmt.Printf(" AvailabilityAttr: OS: %s, Version: %s, Deprecated: %t\n", x.OS, x.Version, (x.Unknown1 != "0") || x.IsUnavailable)
if Debug || prt {
fmt.Printf(" AvailabilityAttr: OS: %s, Version: %s, Deprecated: %t\n", x.OS, x.Version, x.OS == "macos" && ((x.Unknown1 != "0") || x.IsUnavailable))
}
if x.OS != "macos" {
return
@ -763,7 +826,7 @@ func (a *Avail) Add(n ast.Node) {
Deprecated: (x.Unknown1 != "0") || x.IsUnavailable,
})
case *ast.UnavailableAttr, *ast.DeprecatedAttr:
if Debug {
if Debug || prt {
fmt.Printf(" DeprecatedAttr\n")
}
*a = append(*a, AvailAttr{
@ -786,14 +849,20 @@ func (a *Avail) Available() bool {
//GetParms returns the parameters of a method declaration and a bool
//indicating whether the given method is available on MacOS and not
//deprecated.
func (w *Wrapper) GetParms(n ast.Node, class string) ([]*Parameter, bool, bool) {
func (w *Wrapper) GetParms(n ast.Node, class string, prt bool) ([]*Parameter, bool, bool) {
ret := make([]*Parameter, 0)
unavail := false
variadic := false
avail := (*Avail)(&[]AvailAttr{})
var parms []string
switch x := n.(type) {
case *ast.ObjCMethodDecl:
parms = x.Parameters
for _,z := range x.Attr {
if z == "variadic" {
variadic = true
}
}
case *ast.FunctionDecl:
default:
panic("GetParms called with wrong node type")
@ -812,26 +881,35 @@ func (w *Wrapper) GetParms(n ast.Node, class string) ([]*Parameter, bool, bool)
ret = append(ret, p)
j++
case *ast.Variadic:
//ret[j-1].Type.Variadic = true
p := &Parameter{
Vname: "object",
Type: types.NewTypeFromString("NSObject*", ""),
}
p.Type.Variadic = true
ret = append(ret, p)
variadic = true
j++
case *ast.UnavailableAttr:
if prt {
fmt.Printf(" UnavailableAttr\n")
}
unavail = true
case *ast.AvailabilityAttr, *ast.DeprecatedAttr:
avail.Add(x)
avail.Add(x, prt)
case *ast.Unknown:
if Debug {
fmt.Printf("GetParms(): ast.Unknown: %s\n", x.Name)
}
}
}
if variadic {
p := &Parameter{
Vname: "object",
Type: types.NewTypeFromString("NSObject*", ""),
}
p.Type.Variadic = true
ret = append(ret, p)
}
// check that the method is available for this OS and not deprecated
if !avail.Available() {
if unavail || !avail.Available() {
if prt {
fmt.Printf(" it's unavailable\n")
}
return nil, false, unavail
}
return ret, true, unavail
@ -1027,15 +1105,61 @@ func (w *Wrapper) ProcessFunction(m *Method) {
}
func (w *Wrapper) _processMethod(m *Method, fun bool) {
prt := false
if m.Class == dbclass && m.Name == "new" {
prt = true
}
if Debug {
fmt.Printf(" method: %s (%s)\n", m.Name, m.Type)
fmt.Printf(" (%s) method: %s (%s)\n", m.Class, m.Name, m.Type)
}
if m.HasUnsupportedType() {
return
}
if m.Unavailable {
if prt {
fmt.Printf(" %s unavailable\n")
}
return
}
if x := w.Interfaces[m.Class]; x != nil {
if prt {
fmt.Printf("processMethod (%s) %s\n", m.Class, m.Name)
}
if m.ClassMethod {
if prt {
fmt.Printf(" %s class method", m.Name)
}
y := x.ClassMethods
if y != nil {
if y.Unavailable[m.LongName()] {
if prt {
fmt.Printf(" marked unavailable\n")
}
return
} else {
if prt {
fmt.Printf("\n")
}
}
}
} else {
if prt {
fmt.Printf(" %s instance method", m.Name)
}
y := x.InstanceMethods
if y != nil {
if y.Unavailable[m.LongName()] {
if prt {
fmt.Printf(" marked unavailable")
}
return
}
}
}
if prt {
fmt.Printf("\n")
}
}
w.processType(m.Type)
gname := m.GoName
gname = strings.ReplaceAll(gname, "_", " ")
@ -1186,6 +1310,10 @@ func %s%s(%s) %s {
if fun {
// return
}
if cmtype == "" {
fmt.Printf("Method: %s type: '%s'\n", cname, cmtype)
fmt.Printf("Node: %s\n", m.Type.Node)
}
if !fun || len(tps) > 0 && tps[lparm].Variadic {
w.cCode.WriteString(fmt.Sprintf(`
%s
@ -1541,8 +1669,8 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
if m.Unavailable {
continue
}
if Debug {
fmt.Printf(" -> %s\n", m.Name)
if x := w.Interfaces[dname]; x != nil && x.InstanceMethods != nil && x.InstanceMethods.Unavailable[m.LongName()] {
continue
}
if matches(string(m.Name[0])+m.GoName[1:], pats) {
mc.Methods = append(mc.Methods, m)
@ -1556,6 +1684,9 @@ func (w *Wrapper) _ProcessDelSub(dname string, ps map[string][]string, nms []*Me
if m.Unavailable {
continue
}
if x := w.Interfaces[dname]; x != nil && x.InstanceMethods != nil && x.InstanceMethods.Unavailable[m.LongName()] {
continue
}
if Debug {
fmt.Printf(" -> %s\n", m.Name)
}
@ -2109,9 +2240,37 @@ func (o *%s) Super%s(%s) %s {
//Add class and instance methods from super class
func (w *Wrapper) AddSupermethods(i *Interface) {
prt := false
if i.Name == dbclass {
prt = true
fmt.Printf("%s\n", dbclass)
}
var supmethods func(string)
procsups := func(mc, smc *MethodCollection) {
for _, m := range smc.Methods {
if mc.Unavailable[m.LongName()] {
if prt {
fmt.Printf(" %s (from %s): previously marked unavailable\n", m.Name, smc.Class)
}
continue
}
if m.Unavailable {
if prt {
fmt.Printf(" %s (from %s): marked unavailable\n", m.Name, smc.Class)
}
mc.Unavailable[m.LongName()] = true
if m.Name == "init" {
if prt {
fmt.Printf(" Marking new method unavailable in %s\n", mc.Class)
}
w.Interfaces[mc.Class].ClassMethods.Unavailable["New"] = true
}
continue
}
if prt {
fmt.Printf(" %s (from %s): available\n", m.Name, smc.Class)
}
m2 := &Method{
Name: m.Name,
GoName: m.GoName,
@ -2130,6 +2289,9 @@ func (w *Wrapper) AddSupermethods(i *Interface) {
}
m2.Parameters = append(m2.Parameters, p2)
}
if prt {
fmt.Printf(" -> adding method %s\n", m.Name)
}
mc.Methods = append(mc.Methods, m2)
}
}
@ -2148,8 +2310,29 @@ func (w *Wrapper) AddSupermethods(i *Interface) {
//Add methods from a Protocol
func (w *Wrapper) AddProtocolMethods(i *Interface, p *Protocol) {
prt := false
if i.Name == dbclass {
prt = true
fmt.Printf("%s\n",dbclass)
}
procmeths := func(mc, pmc *MethodCollection) {
for _, m := range pmc.Methods {
if mc.Unavailable[m.LongName()] {
if prt {
fmt.Printf(" %s: previously marked unavailable\n", m.Name)
}
continue
}
if m.Unavailable {
if prt {
fmt.Printf(" %s: marked unavailable\n", m.Name)
}
mc.Unavailable[m.LongName()] = true
continue
}
if prt {
fmt.Printf(" %s: available\n", m.Name)
}
m2 := &Method{
Name: m.Name,
GoName: m.GoName,
@ -2168,6 +2351,9 @@ func (w *Wrapper) AddProtocolMethods(i *Interface, p *Protocol) {
}
m2.Parameters = append(m2.Parameters, p2)
}
if prt {
fmt.Printf(" -> adding method %s\n", m.Name)
}
mc.Methods = append(mc.Methods, m2)
}
}