genbindings: add namespaces support

This commit is contained in:
mappu 2024-08-27 19:12:08 +12:00
parent a5104aa614
commit 164ef8cb6c
3 changed files with 42 additions and 11 deletions

View File

@ -7,7 +7,7 @@ import (
"strings" "strings"
) )
func parseHeader(topLevel []interface{}) (*CppParsedHeader, error) { func parseHeader(topLevel []interface{}, addNamePrefix string) (*CppParsedHeader, error) {
var ret CppParsedHeader var ret CppParsedHeader
@ -28,7 +28,7 @@ func parseHeader(topLevel []interface{}) (*CppParsedHeader, error) {
case "CXXRecordDecl": case "CXXRecordDecl":
// Process the inner class definition // Process the inner class definition
obj, err := processClassType(node, "") obj, err := processClassType(node, addNamePrefix)
if err != nil { if err != nil {
if errors.Is(err, ErrNoContent) { if errors.Is(err, ErrNoContent) {
log.Printf("-> Skipping (%v)\n", err) log.Printf("-> Skipping (%v)\n", err)
@ -59,7 +59,30 @@ func parseHeader(topLevel []interface{}) (*CppParsedHeader, error) {
// ignore // ignore
case "NamespaceDecl": case "NamespaceDecl":
// ignore // Parse everything inside the namespace with prefix, as if it is
// a whole separate file
// Then copy the parsed elements back into our own file
namespace, ok := node["name"].(string)
if !ok {
panic("NamespaceDecl missing name")
}
namespaceInner, ok := node["inner"].([]interface{})
if !ok {
// A namespace declaration with no inner content means that, for
// the rest of this whole file, we are in this namespace
// Update our own `addNamePrefix` accordingly
addNamePrefix += namespace + "::"
} else {
contents, err := parseHeader(namespaceInner, namespace+"::")
if err != nil {
panic(err)
}
ret.AddContentFrom(contents)
}
case "FunctionDecl": case "FunctionDecl":
// TODO // TODO
@ -84,16 +107,15 @@ func parseHeader(topLevel []interface{}) (*CppParsedHeader, error) {
// TODO e.g. qfuturewatcher.h // TODO e.g. qfuturewatcher.h
// Probably can't be supported in the Go binding // Probably can't be supported in the Go binding
case "TypeAliasDecl": case "TypeAliasDecl", // qglobal.h
// TODO e.g. qglobal.h "UsingDirectiveDecl", // qtextstream.h
// Should be treated like a typedef "UsingDecl", // qglobal.h
"UsingShadowDecl": // global.h
case "UsingDirectiveDecl": // TODO e.g.
// TODO e.g. qtextstream.h
// Should be treated like a typedef // Should be treated like a typedef
case "TypedefDecl": case "TypedefDecl":
td, err := processTypedef(node, "") td, err := processTypedef(node, addNamePrefix)
if err != nil { if err != nil {
return nil, fmt.Errorf("processTypedef: %w", err) return nil, fmt.Errorf("processTypedef: %w", err)
} }
@ -103,6 +125,9 @@ func parseHeader(topLevel []interface{}) (*CppParsedHeader, error) {
// A C++ class method implementation directly in the header // A C++ class method implementation directly in the header
// Skip over these // Skip over these
case "FullComment":
// Safe to skip
default: default:
return nil, fmt.Errorf("missing handling for clang ast node type %q", kind) return nil, fmt.Errorf("missing handling for clang ast node type %q", kind)
} }

View File

@ -273,3 +273,9 @@ func (c CppParsedHeader) Empty() bool {
return len(c.Typedefs) == 0 && return len(c.Typedefs) == 0 &&
len(c.Classes) == 0 len(c.Classes) == 0
} }
func (c *CppParsedHeader) AddContentFrom(other *CppParsedHeader) {
c.Classes = append(c.Classes, other.Classes...)
c.Enums = append(c.Enums, other.Enums...)
c.Typedefs = append(c.Typedefs, other.Typedefs...)
}

View File

@ -124,7 +124,7 @@ func main() {
} }
// Convert it to our intermediate format // Convert it to our intermediate format
parsed, err := parseHeader(astInner) parsed, err := parseHeader(astInner, "")
if err != nil { if err != nil {
panic(err) panic(err)
} }