genbindings: support protected methods

This commit is contained in:
mappu 2024-11-11 18:27:15 +13:00
parent 47d4581628
commit 9b37750d64

View File

@ -185,6 +185,14 @@ func processTypedef(node map[string]interface{}, addNamePrefix string) (CppTyped
return CppTypedef{}, errors.New("processTypedef: ???") return CppTypedef{}, errors.New("processTypedef: ???")
} }
type visibilityState int
const (
VsPublic visibilityState = 1
VsProtected = 2
VsPrivate = 3
)
// processClassType parses a single C++ class definition into our intermediate format. // processClassType parses a single C++ class definition into our intermediate format.
func processClassType(node map[string]interface{}, addNamePrefix string) (CppClass, error) { func processClassType(node map[string]interface{}, addNamePrefix string) (CppClass, error) {
var ret CppClass var ret CppClass
@ -229,10 +237,10 @@ func processClassType(node map[string]interface{}, addNamePrefix string) (CppCla
} }
} }
// Check if this was 'struct' (default visible) or 'class' (default invisible) // Check if this was 'struct' (default public) or 'class' (default private)
visibility := true visibility := VsPublic
if tagUsed, ok := node["tagUsed"].(string); ok && tagUsed == "class" { if tagUsed, ok := node["tagUsed"].(string); ok && tagUsed == "class" {
visibility = false visibility = VsPrivate
} }
// Check if this is an abstract class // Check if this is an abstract class
@ -289,9 +297,11 @@ nextMethod:
switch access { switch access {
case "public": case "public":
visibility = true visibility = VsPublic
case "private", "protected": case "protected":
visibility = false visibility = VsProtected
case "private":
visibility = VsPrivate
default: default:
panic("unexpected access visibility '" + access + "'") panic("unexpected access visibility '" + access + "'")
} }
@ -315,7 +325,7 @@ nextMethod:
// Child class type definition e.g. QAbstractEventDispatcher::TimerInfo // Child class type definition e.g. QAbstractEventDispatcher::TimerInfo
// Parse as a whole child class // Parse as a whole child class
if !visibility { if visibility != VsPublic {
continue // Skip private/protected continue // Skip private/protected
} }
@ -341,7 +351,7 @@ nextMethod:
case "EnumDecl": case "EnumDecl":
// Child class enum // Child class enum
if !visibility { if visibility != VsPublic {
continue // Skip private/protected continue // Skip private/protected
} }
@ -359,7 +369,7 @@ nextMethod:
// This is an implicit ctor. Therefore the class is constructable // This is an implicit ctor. Therefore the class is constructable
// even if we're currently in a `private:` block. // even if we're currently in a `private:` block.
} else if !visibility { } else if visibility != VsPublic {
continue // Skip private/protected continue // Skip private/protected
} }
@ -403,7 +413,8 @@ nextMethod:
continue continue
} }
if !visibility { if visibility != VsPublic {
// TODO Is there any use case for allowing MIQT to overload a virtual destructor?
ret.CanDelete = false ret.CanDelete = false
continue continue
} }
@ -415,8 +426,12 @@ nextMethod:
} }
case "CXXMethodDecl": case "CXXMethodDecl":
if !visibility {
continue // Skip private/protected // If this is a virtual method, we want to allow overriding it even
// if it is protected
// But we can only call it if it is public
if visibility == VsPrivate {
continue // Skip private, ALLOW protected
} }
// Check if this is `= delete` // Check if this is `= delete`
@ -648,6 +663,10 @@ func parseMethod(node map[string]interface{}, mm *CppMethod) error {
mm.IsStatic = true mm.IsStatic = true
} }
if virtual, ok := node["virtual"].(bool); ok && virtual {
mm.IsVirtual = true
}
if methodInner, ok := node["inner"].([]interface{}); ok { if methodInner, ok := node["inner"].([]interface{}); ok {
paramCounter := 0 paramCounter := 0
for _, methodObj := range methodInner { for _, methodObj := range methodInner {