llcppsigfetch:refine log out
This commit is contained in:
@@ -48,6 +48,7 @@ type Converter struct {
|
|||||||
// Example:
|
// Example:
|
||||||
// typedef struct { int x; } MyStruct;
|
// typedef struct { int x; } MyStruct;
|
||||||
anonyTypeMap map[string]bool // cursorUsr
|
anonyTypeMap map[string]bool // cursorUsr
|
||||||
|
indent int // for verbose debug
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagMap = map[string]ast.Tag{
|
var tagMap = map[string]ast.Tag{
|
||||||
@@ -72,6 +73,7 @@ func NewConverter(config *clangutils.Config) (*Converter, error) {
|
|||||||
log.Println("config.IsCpp", config.IsCpp)
|
log.Println("config.IsCpp", config.IsCpp)
|
||||||
log.Println("config.Temp", config.Temp)
|
log.Println("config.Temp", config.Temp)
|
||||||
}
|
}
|
||||||
|
|
||||||
index, unit, err := clangutils.CreateTranslationUnit(config)
|
index, unit, err := clangutils.CreateTranslationUnit(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -87,13 +89,8 @@ func NewConverter(config *clangutils.Config) (*Converter, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) Dispose() {
|
func (ct *Converter) Dispose() {
|
||||||
if debugParse {
|
ct.logln("Dispose")
|
||||||
log.Println("Dispose: ct.index")
|
|
||||||
}
|
|
||||||
ct.index.Dispose()
|
ct.index.Dispose()
|
||||||
if debugParse {
|
|
||||||
log.Println("Dispose: ct.unit")
|
|
||||||
}
|
|
||||||
ct.unit.Dispose()
|
ct.unit.Dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,74 +115,87 @@ func (ct *Converter) GetTokens(cursor clang.Cursor) []*ast.Token {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) logBase() string {
|
||||||
|
return strings.Repeat(" ", ct.indent)
|
||||||
|
}
|
||||||
|
func (ct *Converter) incIndent() {
|
||||||
|
ct.indent++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) decIndent() {
|
||||||
|
if ct.indent > 0 {
|
||||||
|
ct.indent--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) logf(format string, args ...interface{}) {
|
||||||
|
if debugParse {
|
||||||
|
log.Printf(ct.logBase()+format, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (ct *Converter) logln(args ...interface{}) {
|
||||||
|
if debugParse {
|
||||||
|
if len(args) > 0 {
|
||||||
|
firstArg := fmt.Sprintf("%s%v", ct.logBase(), args[0])
|
||||||
|
log.Println(append([]interface{}{firstArg}, args[1:]...)...)
|
||||||
|
} else {
|
||||||
|
log.Println(ct.logBase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (ct *Converter) UpdateLoc(cursor clang.Cursor) {
|
func (ct *Converter) UpdateLoc(cursor clang.Cursor) {
|
||||||
loc := cursor.Location()
|
loc := cursor.Location()
|
||||||
var file clang.File
|
var file clang.File
|
||||||
loc.SpellingLocation(&file, nil, nil, nil)
|
loc.SpellingLocation(&file, nil, nil, nil)
|
||||||
filename := file.FileName()
|
|
||||||
defer filename.Dispose()
|
|
||||||
|
|
||||||
if filename.CStr() == nil {
|
filePath := toStr(file.FileName())
|
||||||
|
|
||||||
|
if filePath == "" {
|
||||||
//todo(zzy): For some built-in macros, there is no file.
|
//todo(zzy): For some built-in macros, there is no file.
|
||||||
ct.curLoc = ast.Location{File: ""}
|
ct.curLoc = ast.Location{File: ""}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath := c.GoString(filename.CStr())
|
|
||||||
ct.curLoc = ast.Location{File: filePath}
|
ct.curLoc = ast.Location{File: filePath}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) GetCurFile() *ast.File {
|
func (ct *Converter) GetCurFile() *ast.File {
|
||||||
if ct.curLoc.File == "" {
|
if ct.curLoc.File == "" {
|
||||||
if debugParse {
|
ct.logln("GetCurFile: NO FILE")
|
||||||
log.Println("GetCurFile: NO FILE")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// todo(zzy): more efficient
|
// todo(zzy): more efficient
|
||||||
for i, entry := range ct.Files {
|
for i, entry := range ct.Files {
|
||||||
if entry.Path == ct.curLoc.File {
|
if entry.Path == ct.curLoc.File {
|
||||||
if debugParse {
|
ct.logln("GetCurFile: found", ct.curLoc.File)
|
||||||
log.Println("GetCurFile: found", ct.curLoc.File)
|
|
||||||
}
|
|
||||||
return ct.Files[i].Doc
|
return ct.Files[i].Doc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if debugParse {
|
ct.logln("GetCurFile: Create New ast.File", ct.curLoc.File)
|
||||||
log.Println("GetCurFile: Create New ast.File", ct.curLoc.File)
|
|
||||||
}
|
|
||||||
newDoc := &ast.File{}
|
newDoc := &ast.File{}
|
||||||
ct.Files = append(ct.Files, &FileEntry{Path: ct.curLoc.File, Doc: newDoc})
|
ct.Files = append(ct.Files, &FileEntry{Path: ct.curLoc.File, Doc: newDoc})
|
||||||
return newDoc
|
return newDoc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) SetAnonyType(cursor clang.Cursor) {
|
func (ct *Converter) SetAnonyType(cursor clang.Cursor) {
|
||||||
usr := cursor.USR()
|
usr := toStr(cursor.USR())
|
||||||
usrStr := c.GoString(usr.CStr())
|
ct.anonyTypeMap[usr] = true
|
||||||
defer usr.Dispose()
|
|
||||||
ct.anonyTypeMap[usrStr] = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) GetAnonyType(cursor clang.Cursor) (bool, bool) {
|
func (ct *Converter) GetAnonyType(cursor clang.Cursor) (bool, bool) {
|
||||||
usr := cursor.USR()
|
usr := toStr(cursor.USR())
|
||||||
usrStr := c.GoString(usr.CStr())
|
isAnony, ok := ct.anonyTypeMap[usr]
|
||||||
defer usr.Dispose()
|
|
||||||
isAnony, ok := ct.anonyTypeMap[usrStr]
|
|
||||||
return isAnony, ok
|
return isAnony, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) SetTypeDecl(cursor clang.Cursor, decl ast.Decl) {
|
func (ct *Converter) SetTypeDecl(cursor clang.Cursor, decl ast.Decl) {
|
||||||
usr := cursor.USR()
|
usr := toStr(cursor.USR())
|
||||||
usrStr := c.GoString(usr.CStr())
|
ct.typeDecls[usr] = decl
|
||||||
ct.typeDecls[usrStr] = decl
|
|
||||||
usr.Dispose()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) GetTypeDecl(cursor clang.Cursor) (ast.Decl, bool) {
|
func (ct *Converter) GetTypeDecl(cursor clang.Cursor) (ast.Decl, bool) {
|
||||||
usr := cursor.USR()
|
usr := toStr(cursor.USR())
|
||||||
usrStr := c.GoString(usr.CStr())
|
decl, ok := ct.typeDecls[usr]
|
||||||
decl, ok := ct.typeDecls[usrStr]
|
|
||||||
usr.Dispose()
|
|
||||||
return decl, ok
|
return decl, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,14 +223,13 @@ func (ct *Converter) CreateDeclBase(cursor clang.Cursor) ast.DeclBase {
|
|||||||
// Note: In cases where both documentation comments and line comments conceptually exist,
|
// Note: In cases where both documentation comments and line comments conceptually exist,
|
||||||
// only the line comment will be preserved.
|
// only the line comment will be preserved.
|
||||||
func (ct *Converter) ParseCommentGroup(cursor clang.Cursor) (comentGroup *ast.CommentGroup, isDoc bool) {
|
func (ct *Converter) ParseCommentGroup(cursor clang.Cursor) (comentGroup *ast.CommentGroup, isDoc bool) {
|
||||||
rawComment := cursor.RawCommentText()
|
rawComment := toStr(cursor.RawCommentText())
|
||||||
defer rawComment.Dispose()
|
|
||||||
commentGroup := &ast.CommentGroup{}
|
commentGroup := &ast.CommentGroup{}
|
||||||
if rawComment.CStr() != nil {
|
if rawComment != "" {
|
||||||
commentRange := cursor.CommentRange()
|
commentRange := cursor.CommentRange()
|
||||||
cursorRange := cursor.Extent()
|
cursorRange := cursor.Extent()
|
||||||
isDoc := getOffset(commentRange.RangeStart()) < getOffset(cursorRange.RangeStart())
|
isDoc := getOffset(commentRange.RangeStart()) < getOffset(cursorRange.RangeStart())
|
||||||
commentGroup = ct.ParseComment(c.GoString(rawComment.CStr()))
|
commentGroup = ct.ParseComment(rawComment)
|
||||||
if len(commentGroup.List) > 0 {
|
if len(commentGroup.List) > 0 {
|
||||||
return commentGroup, isDoc
|
return commentGroup, isDoc
|
||||||
}
|
}
|
||||||
@@ -239,15 +248,15 @@ func (ct *Converter) ParseComment(rawComment string) *ast.CommentGroup {
|
|||||||
|
|
||||||
// visit top decls (struct,class,function,enum & macro,include)
|
// visit top decls (struct,class,function,enum & macro,include)
|
||||||
func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResult {
|
func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResult {
|
||||||
|
ct.incIndent()
|
||||||
|
defer ct.decIndent()
|
||||||
|
|
||||||
ct.UpdateLoc(cursor)
|
ct.UpdateLoc(cursor)
|
||||||
|
|
||||||
curFile := ct.GetCurFile()
|
curFile := ct.GetCurFile()
|
||||||
|
|
||||||
if debugParse {
|
name := toStr(cursor.String())
|
||||||
name := cursor.String()
|
ct.logf("visitTop: Cursor: %s\n", name)
|
||||||
defer name.Dispose()
|
|
||||||
log.Println("visitTop: Cursor:", c.GoString(name.CStr()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if curFile == nil {
|
if curFile == nil {
|
||||||
return clang.ChildVisit_Continue
|
return clang.ChildVisit_Continue
|
||||||
@@ -257,69 +266,57 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
|
|||||||
case clang.CursorInclusionDirective:
|
case clang.CursorInclusionDirective:
|
||||||
include := ct.ProcessInclude(cursor)
|
include := ct.ProcessInclude(cursor)
|
||||||
curFile.Includes = append(curFile.Includes, include)
|
curFile.Includes = append(curFile.Includes, include)
|
||||||
if debugParse {
|
ct.logln("visitTop: ProcessInclude END ", include.Path)
|
||||||
log.Println("visitTop: ProcessInclude END ", include.Path)
|
|
||||||
}
|
|
||||||
case clang.CursorMacroDefinition:
|
case clang.CursorMacroDefinition:
|
||||||
macro := ct.ProcessMacro(cursor)
|
macro := ct.ProcessMacro(cursor)
|
||||||
curFile.Macros = append(curFile.Macros, macro)
|
curFile.Macros = append(curFile.Macros, macro)
|
||||||
if debugParse {
|
ct.logln("visitTop: ProcessMacro END ", macro.Name, "Tokens Length:", len(macro.Tokens))
|
||||||
log.Println("visitTop: ProcessMacro END ", macro.Name, "Tokens Length:", len(macro.Tokens))
|
|
||||||
}
|
|
||||||
case clang.CursorEnumDecl:
|
case clang.CursorEnumDecl:
|
||||||
enum := ct.ProcessEnumDecl(cursor)
|
enum := ct.ProcessEnumDecl(cursor)
|
||||||
curFile.Decls = append(curFile.Decls, enum)
|
curFile.Decls = append(curFile.Decls, enum)
|
||||||
if debugParse {
|
|
||||||
name := "anonymous"
|
ct.logf("visitTop: ProcessEnumDecl END")
|
||||||
if enum.Name != nil {
|
if enum.Name != nil {
|
||||||
name = enum.Name.Name
|
ct.logln(enum.Name.Name)
|
||||||
}
|
} else {
|
||||||
log.Println("visitTop: ProcessEnumDecl END", name)
|
ct.logln("ANONY")
|
||||||
}
|
}
|
||||||
|
|
||||||
case clang.CursorClassDecl:
|
case clang.CursorClassDecl:
|
||||||
classDecl := ct.ProcessClassDecl(cursor)
|
classDecl := ct.ProcessClassDecl(cursor)
|
||||||
curFile.Decls = append(curFile.Decls, classDecl)
|
curFile.Decls = append(curFile.Decls, classDecl)
|
||||||
if debugParse {
|
// class havent anonymous situation
|
||||||
name := "anonymous"
|
ct.logln("visitTop: ProcessClassDecl END", classDecl.Name.Name)
|
||||||
if classDecl.Name != nil {
|
|
||||||
name = classDecl.Name.Name
|
|
||||||
}
|
|
||||||
log.Println("visitTop: ProcessClassDecl END", name)
|
|
||||||
}
|
|
||||||
case clang.CursorStructDecl:
|
case clang.CursorStructDecl:
|
||||||
structDecl := ct.ProcessStructDecl(cursor)
|
structDecl := ct.ProcessStructDecl(cursor)
|
||||||
curFile.Decls = append(curFile.Decls, structDecl)
|
curFile.Decls = append(curFile.Decls, structDecl)
|
||||||
if debugParse {
|
|
||||||
name := "anonymous"
|
ct.logf("visitTop: ProcessStructDecl END")
|
||||||
if structDecl.Name != nil {
|
if structDecl.Name != nil {
|
||||||
name = structDecl.Name.Name
|
ct.logln(structDecl.Name.Name)
|
||||||
}
|
} else {
|
||||||
log.Println("visitTop: ProcessStructDecl END", name)
|
ct.logln("ANONY")
|
||||||
}
|
}
|
||||||
case clang.CursorUnionDecl:
|
case clang.CursorUnionDecl:
|
||||||
unionDecl := ct.ProcessUnionDecl(cursor)
|
unionDecl := ct.ProcessUnionDecl(cursor)
|
||||||
curFile.Decls = append(curFile.Decls, unionDecl)
|
curFile.Decls = append(curFile.Decls, unionDecl)
|
||||||
if debugParse {
|
|
||||||
name := "anonymous"
|
ct.logf("visitTop: ProcessUnionDecl END")
|
||||||
if unionDecl.Name != nil {
|
if unionDecl.Name != nil {
|
||||||
name = unionDecl.Name.Name
|
ct.logln(unionDecl.Name.Name)
|
||||||
}
|
} else {
|
||||||
log.Println("visitTop: ProcessUnionDecl END", name)
|
ct.logln("ANONY")
|
||||||
}
|
}
|
||||||
case clang.CursorFunctionDecl, clang.CursorCXXMethod, clang.CursorConstructor, clang.CursorDestructor:
|
case clang.CursorFunctionDecl, clang.CursorCXXMethod, clang.CursorConstructor, clang.CursorDestructor:
|
||||||
// Handle functions and class methods (including out-of-class method)
|
// Handle functions and class methods (including out-of-class method)
|
||||||
// Example: void MyClass::myMethod() { ... } out-of-class method
|
// Example: void MyClass::myMethod() { ... } out-of-class method
|
||||||
funcDecl := ct.ProcessFuncDecl(cursor)
|
funcDecl := ct.ProcessFuncDecl(cursor)
|
||||||
curFile.Decls = append(curFile.Decls, funcDecl)
|
curFile.Decls = append(curFile.Decls, funcDecl)
|
||||||
if debugParse {
|
ct.logln("visitTop: ProcessFuncDecl END", funcDecl.Name.Name, funcDecl.MangledName, "isStatic:", funcDecl.IsStatic, "isInline:", funcDecl.IsInline)
|
||||||
log.Println("visitTop: ProcessFuncDecl END", funcDecl.Name.Name, funcDecl.MangledName, "isStatic:", funcDecl.IsStatic, "isInline:", funcDecl.IsInline)
|
|
||||||
}
|
|
||||||
case clang.CursorTypedefDecl:
|
case clang.CursorTypedefDecl:
|
||||||
typedefDecl := ct.ProcessTypeDefDecl(cursor)
|
typedefDecl := ct.ProcessTypeDefDecl(cursor)
|
||||||
curFile.Decls = append(curFile.Decls, typedefDecl)
|
curFile.Decls = append(curFile.Decls, typedefDecl)
|
||||||
if debugParse {
|
ct.logln("visitTop: ProcessTypeDefDecl END", typedefDecl.Name.Name)
|
||||||
log.Println("visitTop: ProcessTypeDefDecl END", typedefDecl.Name.Name)
|
|
||||||
}
|
|
||||||
case clang.CursorNamespace:
|
case clang.CursorNamespace:
|
||||||
VisitChildren(cursor, ct.visitTop)
|
VisitChildren(cursor, ct.visitTop)
|
||||||
}
|
}
|
||||||
@@ -343,6 +340,12 @@ func VisitChildren(cursor clang.Cursor, fn Visitor) c.Uint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) ProcessType(t clang.Type) ast.Expr {
|
func (ct *Converter) ProcessType(t clang.Type) ast.Expr {
|
||||||
|
ct.incIndent()
|
||||||
|
defer ct.decIndent()
|
||||||
|
|
||||||
|
typeName, typeKind := getTypeDesc(t)
|
||||||
|
ct.logln("ProcessType: TypeName:", typeName, "TypeKind:", typeKind)
|
||||||
|
|
||||||
if t.Kind >= clang.TypeFirstBuiltin && t.Kind <= clang.TypeLastBuiltin {
|
if t.Kind >= clang.TypeFirstBuiltin && t.Kind <= clang.TypeLastBuiltin {
|
||||||
return ct.ProcessBuiltinType(t)
|
return ct.ProcessBuiltinType(t)
|
||||||
}
|
}
|
||||||
@@ -354,14 +357,22 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr {
|
|||||||
var expr ast.Expr
|
var expr ast.Expr
|
||||||
switch t.Kind {
|
switch t.Kind {
|
||||||
case clang.TypePointer:
|
case clang.TypePointer:
|
||||||
|
name, kind := getTypeDesc(t.PointeeType())
|
||||||
|
ct.logln("ProcessType: PointerType Pointee TypeName:", name, "TypeKind:", kind)
|
||||||
expr = &ast.PointerType{X: ct.ProcessType(t.PointeeType())}
|
expr = &ast.PointerType{X: ct.ProcessType(t.PointeeType())}
|
||||||
case clang.TypeLValueReference:
|
case clang.TypeLValueReference:
|
||||||
|
name, kind := getTypeDesc(t.NonReferenceType())
|
||||||
|
ct.logln("ProcessType: LvalueRefType NonReference TypeName:", name, "TypeKind:", kind)
|
||||||
expr = &ast.LvalueRefType{X: ct.ProcessType(t.NonReferenceType())}
|
expr = &ast.LvalueRefType{X: ct.ProcessType(t.NonReferenceType())}
|
||||||
case clang.TypeRValueReference:
|
case clang.TypeRValueReference:
|
||||||
|
name, kind := getTypeDesc(t.NonReferenceType())
|
||||||
|
ct.logln("ProcessType: RvalueRefType NonReference TypeName:", name, "TypeKind:", kind)
|
||||||
expr = &ast.RvalueRefType{X: ct.ProcessType(t.NonReferenceType())}
|
expr = &ast.RvalueRefType{X: ct.ProcessType(t.NonReferenceType())}
|
||||||
case clang.TypeFunctionProto, clang.TypeFunctionNoProto:
|
case clang.TypeFunctionProto, clang.TypeFunctionNoProto:
|
||||||
// treating TypeFunctionNoProto as a general function without parameters
|
// treating TypeFunctionNoProto as a general function without parameters
|
||||||
// function type will only collect return type, params will be collected in ProcessFuncDecl
|
// function type will only collect return type, params will be collected in ProcessFuncDecl
|
||||||
|
name, kind := getTypeDesc(t)
|
||||||
|
ct.logln("ProcessType: FunctionType TypeName:", name, "TypeKind:", kind)
|
||||||
expr = ct.ProcessFunctionType(t)
|
expr = ct.ProcessFunctionType(t)
|
||||||
case clang.TypeConstantArray, clang.TypeIncompleteArray, clang.TypeVariableArray, clang.TypeDependentSizedArray:
|
case clang.TypeConstantArray, clang.TypeIncompleteArray, clang.TypeVariableArray, clang.TypeDependentSizedArray:
|
||||||
if t.Kind == clang.TypeConstantArray {
|
if t.Kind == clang.TypeConstantArray {
|
||||||
@@ -378,6 +389,9 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr {
|
|||||||
Elt: ct.ProcessType(t.ArrayElementType()),
|
Elt: ct.ProcessType(t.ArrayElementType()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
name, kind := getTypeDesc(t)
|
||||||
|
ct.logln("ProcessType: Unknown Type TypeName:", name, "TypeKind:", kind)
|
||||||
}
|
}
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
@@ -386,11 +400,19 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr {
|
|||||||
// This is because we cannot reverse-lookup the corresponding declaration node from a function type.
|
// This is because we cannot reverse-lookup the corresponding declaration node from a function type.
|
||||||
// Note: For function declarations, parameter names are collected in the ProcessFuncDecl method.
|
// Note: For function declarations, parameter names are collected in the ProcessFuncDecl method.
|
||||||
func (ct *Converter) ProcessFunctionType(t clang.Type) *ast.FuncType {
|
func (ct *Converter) ProcessFunctionType(t clang.Type) *ast.FuncType {
|
||||||
|
ct.incIndent()
|
||||||
|
defer ct.decIndent()
|
||||||
|
typeName, typeKind := getTypeDesc(t)
|
||||||
|
ct.logln("ProcessFunctionType: TypeName:", typeName, "TypeKind:", typeKind)
|
||||||
// Note: Attempting to get the type declaration for a function type will result in CursorNoDeclFound
|
// Note: Attempting to get the type declaration for a function type will result in CursorNoDeclFound
|
||||||
// cursor := t.TypeDeclaration()
|
// cursor := t.TypeDeclaration()
|
||||||
// This would return CursorNoDeclFound
|
// This would return CursorNoDeclFound
|
||||||
|
resType := t.ResultType()
|
||||||
|
|
||||||
ret := ct.ProcessType(t.ResultType())
|
name, kind := getTypeDesc(resType)
|
||||||
|
ct.logln("ProcessFunctionType: ResultType TypeName:", name, "TypeKind:", kind)
|
||||||
|
|
||||||
|
ret := ct.ProcessType(resType)
|
||||||
params := &ast.FieldList{}
|
params := &ast.FieldList{}
|
||||||
numArgs := t.NumArgTypes()
|
numArgs := t.NumArgTypes()
|
||||||
for i := 0; i < int(numArgs); i++ {
|
for i := 0; i < int(numArgs); i++ {
|
||||||
@@ -412,14 +434,16 @@ func (ct *Converter) ProcessFunctionType(t clang.Type) *ast.FuncType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) ProcessTypeDefDecl(cursor clang.Cursor) *ast.TypedefDecl {
|
func (ct *Converter) ProcessTypeDefDecl(cursor clang.Cursor) *ast.TypedefDecl {
|
||||||
name := cursor.String()
|
ct.incIndent()
|
||||||
defer name.Dispose()
|
defer ct.decIndent()
|
||||||
|
name, kind := getCursorDesc(cursor)
|
||||||
|
ct.logln("ProcessTypeDefDecl: CursorName:", name, "CursorKind:", kind)
|
||||||
|
|
||||||
typ := ct.ProcessUnderlyingType(cursor)
|
typ := ct.ProcessUnderlyingType(cursor)
|
||||||
|
|
||||||
decl := &ast.TypedefDecl{
|
decl := &ast.TypedefDecl{
|
||||||
DeclBase: ct.CreateDeclBase(cursor),
|
DeclBase: ct.CreateDeclBase(cursor),
|
||||||
Name: &ast.Ident{Name: c.GoString(name.CStr())},
|
Name: &ast.Ident{Name: name},
|
||||||
Type: typ,
|
Type: typ,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,9 +456,7 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr {
|
|||||||
underlyingTyp := cursor.TypedefDeclUnderlyingType()
|
underlyingTyp := cursor.TypedefDeclUnderlyingType()
|
||||||
|
|
||||||
if underlyingTyp.Kind != clang.TypeElaborated {
|
if underlyingTyp.Kind != clang.TypeElaborated {
|
||||||
if debugParse {
|
ct.logln("ProcessUnderlyingType: not elaborated")
|
||||||
log.Println("ProcessUnderlyingType: not elaborated")
|
|
||||||
}
|
|
||||||
return ct.ProcessType(underlyingTyp)
|
return ct.ProcessType(underlyingTyp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,9 +469,7 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr {
|
|||||||
// In this case, libclang incorrectly reports an anonymous struct as a named struct
|
// In this case, libclang incorrectly reports an anonymous struct as a named struct
|
||||||
sourceCode := ct.GetTokens(referTypeCursor)
|
sourceCode := ct.GetTokens(referTypeCursor)
|
||||||
if isAnonymousStructure(sourceCode) {
|
if isAnonymousStructure(sourceCode) {
|
||||||
if debugParse {
|
ct.logln("ProcessUnderlyingType: is anonymous structure")
|
||||||
log.Println("ProcessUnderlyingType: is anonymous structure")
|
|
||||||
}
|
|
||||||
ct.SetAnonyType(referTypeCursor)
|
ct.SetAnonyType(referTypeCursor)
|
||||||
typ, isValidType := ct.GetTypeDecl(referTypeCursor)
|
typ, isValidType := ct.GetTypeDecl(referTypeCursor)
|
||||||
if isValidType {
|
if isValidType {
|
||||||
@@ -457,15 +477,11 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr {
|
|||||||
// according to a normal anonymous decl
|
// according to a normal anonymous decl
|
||||||
switch declType := typ.(type) {
|
switch declType := typ.(type) {
|
||||||
case *ast.EnumTypeDecl:
|
case *ast.EnumTypeDecl:
|
||||||
if debugParse {
|
ct.logln("ProcessUnderlyingType: is actually anonymous enum,remove name")
|
||||||
log.Println("ProcessUnderlyingType: is actually anonymous enum,remove name")
|
|
||||||
}
|
|
||||||
declType.Name = nil
|
declType.Name = nil
|
||||||
case *ast.TypeDecl:
|
case *ast.TypeDecl:
|
||||||
if declType.Type.Tag != ast.Class {
|
if declType.Type.Tag != ast.Class {
|
||||||
if debugParse {
|
ct.logln("ProcessUnderlyingType: is actually anonymous struct,remove name")
|
||||||
log.Println("ProcessUnderlyingType: is actually anonymous struct,remove name")
|
|
||||||
}
|
|
||||||
declType.Name = nil
|
declType.Name = nil
|
||||||
} else {
|
} else {
|
||||||
// Unreachable: There should be no anonymous classes in this context
|
// Unreachable: There should be no anonymous classes in this context
|
||||||
@@ -484,35 +500,30 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr {
|
|||||||
|
|
||||||
// converts functions, methods, constructors, destructors (including out-of-class decl) to ast.FuncDecl nodes.
|
// converts functions, methods, constructors, destructors (including out-of-class decl) to ast.FuncDecl nodes.
|
||||||
func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl {
|
func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl {
|
||||||
name := cursor.String()
|
ct.incIndent()
|
||||||
mangledName := cursor.Mangling()
|
defer ct.decIndent()
|
||||||
defer name.Dispose()
|
name, kind := getCursorDesc(cursor)
|
||||||
defer mangledName.Dispose()
|
mangledName := toStr(cursor.Mangling())
|
||||||
|
ct.logln("ProcessFuncDecl: CursorName:", name, "CursorKind:", kind)
|
||||||
|
|
||||||
// function type will only collect return type
|
// function type will only collect return type
|
||||||
// ProcessType can't get the field names,will collect in follows
|
// ProcessType can't get the field names,will collect in follows
|
||||||
if debugParse {
|
|
||||||
log.Println("ProcessFuncDecl: Get Base FuncType")
|
|
||||||
}
|
|
||||||
funcType, ok := ct.ProcessType(cursor.Type()).(*ast.FuncType)
|
funcType, ok := ct.ProcessType(cursor.Type()).(*ast.FuncType)
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Println("failed to process function type")
|
ct.logln("ProcessFuncDecl: failed to process function type")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if debugParse {
|
ct.logln("ProcessFuncDecl: ProcessFieldList")
|
||||||
log.Println("ProcessFuncDecl: ProcessFieldList")
|
|
||||||
}
|
|
||||||
params := ct.ProcessFieldList(cursor)
|
params := ct.ProcessFieldList(cursor)
|
||||||
funcType.Params = params
|
funcType.Params = params
|
||||||
|
|
||||||
mangledNameStr := c.GoString(mangledName.CStr())
|
mangledName = strings.TrimLeft(mangledName, "_")
|
||||||
mangledNameStr = strings.TrimLeft(mangledNameStr, "_")
|
|
||||||
|
|
||||||
funcDecl := &ast.FuncDecl{
|
funcDecl := &ast.FuncDecl{
|
||||||
DeclBase: ct.CreateDeclBase(cursor),
|
DeclBase: ct.CreateDeclBase(cursor),
|
||||||
Name: &ast.Ident{Name: c.GoString(name.CStr())},
|
Name: &ast.Ident{Name: name},
|
||||||
Type: funcType,
|
Type: funcType,
|
||||||
MangledName: mangledNameStr,
|
MangledName: mangledName,
|
||||||
}
|
}
|
||||||
|
|
||||||
if cursor.IsFunctionInlined() != 0 {
|
if cursor.IsFunctionInlined() != 0 {
|
||||||
@@ -520,9 +531,7 @@ func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isMethod(cursor) {
|
if isMethod(cursor) {
|
||||||
if debugParse {
|
ct.logln("ProcessFuncDecl: is method, ProcessMethodAttributes")
|
||||||
log.Println("ProcessFuncDecl: is method, ProcessMethodAttributes")
|
|
||||||
}
|
|
||||||
ct.ProcessMethodAttributes(cursor, funcDecl)
|
ct.ProcessMethodAttributes(cursor, funcDecl)
|
||||||
} else {
|
} else {
|
||||||
if cursor.StorageClass() == clang.SCStatic {
|
if cursor.StorageClass() == clang.SCStatic {
|
||||||
@@ -599,12 +608,11 @@ func (ct *Converter) ProcessEnumType(cursor clang.Cursor) *ast.EnumType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl {
|
func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl {
|
||||||
name := cursor.String()
|
name := toStr(cursor.String())
|
||||||
defer name.Dispose()
|
|
||||||
|
|
||||||
decl := &ast.EnumTypeDecl{
|
decl := &ast.EnumTypeDecl{
|
||||||
DeclBase: ct.CreateDeclBase(cursor),
|
DeclBase: ct.CreateDeclBase(cursor),
|
||||||
Name: &ast.Ident{Name: c.GoString(name.CStr())},
|
Name: &ast.Ident{Name: name},
|
||||||
Type: ct.ProcessEnumType(cursor),
|
Type: ct.ProcessEnumType(cursor),
|
||||||
}
|
}
|
||||||
ct.SetTypeDecl(cursor, decl)
|
ct.SetTypeDecl(cursor, decl)
|
||||||
@@ -613,20 +621,18 @@ func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl {
|
|||||||
|
|
||||||
// current only collect macro which defined in file
|
// current only collect macro which defined in file
|
||||||
func (ct *Converter) ProcessMacro(cursor clang.Cursor) *ast.Macro {
|
func (ct *Converter) ProcessMacro(cursor clang.Cursor) *ast.Macro {
|
||||||
name := cursor.String()
|
name := toStr(cursor.String())
|
||||||
defer name.Dispose()
|
|
||||||
|
|
||||||
macro := &ast.Macro{
|
macro := &ast.Macro{
|
||||||
Name: c.GoString(name.CStr()),
|
Name: name,
|
||||||
Tokens: ct.GetTokens(cursor),
|
Tokens: ct.GetTokens(cursor),
|
||||||
}
|
}
|
||||||
return macro
|
return macro
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) ProcessInclude(cursor clang.Cursor) *ast.Include {
|
func (ct *Converter) ProcessInclude(cursor clang.Cursor) *ast.Include {
|
||||||
name := cursor.String()
|
name := toStr(cursor.String())
|
||||||
defer name.Dispose()
|
return &ast.Include{Path: name}
|
||||||
return &ast.Include{Path: c.GoString(name.CStr())}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo(zzy): after https://github.com/goplus/llgo/issues/804 has be resolved
|
// todo(zzy): after https://github.com/goplus/llgo/issues/804 has be resolved
|
||||||
@@ -637,11 +643,19 @@ type visitFieldContext struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *visitFieldContext) createBaseField(cursor clang.Cursor) *ast.Field {
|
func (p *visitFieldContext) createBaseField(cursor clang.Cursor) *ast.Field {
|
||||||
|
p.converter.incIndent()
|
||||||
|
defer p.converter.decIndent()
|
||||||
|
|
||||||
|
fieldName := toStr(cursor.String())
|
||||||
|
|
||||||
|
typ := cursor.Type()
|
||||||
|
typeName, typeKind := getTypeDesc(typ)
|
||||||
|
|
||||||
|
p.converter.logf("createBaseField: ProcessType %s TypeKind: %s", typeName, typeKind)
|
||||||
|
|
||||||
field := &ast.Field{
|
field := &ast.Field{
|
||||||
Type: p.converter.ProcessType(cursor.Type()),
|
Type: p.converter.ProcessType(typ),
|
||||||
}
|
}
|
||||||
fieldName := cursor.String()
|
|
||||||
defer fieldName.Dispose()
|
|
||||||
|
|
||||||
commentGroup, isDoc := p.converter.ParseCommentGroup(cursor)
|
commentGroup, isDoc := p.converter.ParseCommentGroup(cursor)
|
||||||
if commentGroup != nil {
|
if commentGroup != nil {
|
||||||
@@ -651,8 +665,8 @@ func (p *visitFieldContext) createBaseField(cursor clang.Cursor) *ast.Field {
|
|||||||
field.Comment = commentGroup
|
field.Comment = commentGroup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if name := fieldName.CStr(); name != nil {
|
if fieldName != "" {
|
||||||
field.Names = []*ast.Ident{{Name: c.GoString(name)}}
|
field.Names = []*ast.Ident{{Name: fieldName}}
|
||||||
}
|
}
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
@@ -668,6 +682,12 @@ func visitFieldList(cursor, parent clang.Cursor, clientData unsafe.Pointer) clan
|
|||||||
// struct A {
|
// struct A {
|
||||||
// int a, b;
|
// int a, b;
|
||||||
// };
|
// };
|
||||||
|
if cursor.Kind == clang.CursorFieldDecl {
|
||||||
|
ctx.converter.logln("visitFieldList: CursorFieldDecl")
|
||||||
|
} else {
|
||||||
|
ctx.converter.logln("visitFieldList: CursorParmDecl")
|
||||||
|
}
|
||||||
|
|
||||||
field := ctx.createBaseField(cursor)
|
field := ctx.createBaseField(cursor)
|
||||||
if cursor.Kind == clang.CursorFieldDecl {
|
if cursor.Kind == clang.CursorFieldDecl {
|
||||||
field.Access = ast.AccessSpecifier(cursor.CXXAccessSpecifier())
|
field.Access = ast.AccessSpecifier(cursor.CXXAccessSpecifier())
|
||||||
@@ -690,11 +710,15 @@ func visitFieldList(cursor, parent clang.Cursor, clientData unsafe.Pointer) clan
|
|||||||
|
|
||||||
// For Record Type(struct,union ...) & Func 's FieldList
|
// For Record Type(struct,union ...) & Func 's FieldList
|
||||||
func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList {
|
func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList {
|
||||||
|
ct.incIndent()
|
||||||
|
defer ct.decIndent()
|
||||||
|
|
||||||
params := &ast.FieldList{}
|
params := &ast.FieldList{}
|
||||||
ctx := &visitFieldContext{
|
ctx := &visitFieldContext{
|
||||||
params: params,
|
params: params,
|
||||||
converter: ct,
|
converter: ct,
|
||||||
}
|
}
|
||||||
|
ct.logln("ProcessFieldList: VisitChildren")
|
||||||
clang.VisitChildren(cursor, visitFieldList, c.Pointer(ctx))
|
clang.VisitChildren(cursor, visitFieldList, c.Pointer(ctx))
|
||||||
if (cursor.Kind == clang.CursorFunctionDecl || isMethod(cursor)) && cursor.IsVariadic() != 0 {
|
if (cursor.Kind == clang.CursorFunctionDecl || isMethod(cursor)) && cursor.IsVariadic() != 0 {
|
||||||
params.List = append(params.List, &ast.Field{
|
params.List = append(params.List, &ast.Field{
|
||||||
@@ -732,12 +756,18 @@ func (ct *Converter) ProcessMethods(cursor clang.Cursor) []*ast.FuncDecl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) *ast.TypeDecl {
|
func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) *ast.TypeDecl {
|
||||||
|
ct.incIndent()
|
||||||
|
defer ct.decIndent()
|
||||||
|
cursorName, cursorKind := getCursorDesc(cursor)
|
||||||
|
ct.logln("ProcessRecordDecl: CursorName:", cursorName, "CursorKind:", cursorKind)
|
||||||
|
|
||||||
anony := cursor.IsAnonymousRecordDecl()
|
anony := cursor.IsAnonymousRecordDecl()
|
||||||
var name *ast.Ident
|
var name *ast.Ident
|
||||||
if anony == 0 {
|
if anony == 0 {
|
||||||
cursorName := cursor.String()
|
name = &ast.Ident{Name: cursorName}
|
||||||
defer cursorName.Dispose()
|
ct.logln("ProcessRecordDecl: has name", cursorName)
|
||||||
name = &ast.Ident{Name: c.GoString(cursorName.CStr())}
|
} else {
|
||||||
|
ct.logln("ProcessRecordDecl: is anonymous")
|
||||||
}
|
}
|
||||||
|
|
||||||
decl := &ast.TypeDecl{
|
decl := &ast.TypeDecl{
|
||||||
@@ -759,6 +789,9 @@ func (ct *Converter) ProcessUnionDecl(cursor clang.Cursor) *ast.TypeDecl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) ProcessClassDecl(cursor clang.Cursor) *ast.TypeDecl {
|
func (ct *Converter) ProcessClassDecl(cursor clang.Cursor) *ast.TypeDecl {
|
||||||
|
cursorName, cursorKind := getCursorDesc(cursor)
|
||||||
|
ct.logln("ProcessClassDecl: CursorName:", cursorName, "CursorKind:", cursorKind)
|
||||||
|
|
||||||
// Pushing class scope before processing its type and popping after
|
// Pushing class scope before processing its type and popping after
|
||||||
base := ct.CreateDeclBase(cursor)
|
base := ct.CreateDeclBase(cursor)
|
||||||
typ := ct.ProcessRecordType(cursor)
|
typ := ct.ProcessRecordType(cursor)
|
||||||
@@ -768,15 +801,31 @@ func (ct *Converter) ProcessClassDecl(cursor clang.Cursor) *ast.TypeDecl {
|
|||||||
Name: &ast.Ident{Name: c.GoString(cursor.String().CStr())},
|
Name: &ast.Ident{Name: c.GoString(cursor.String().CStr())},
|
||||||
Type: typ,
|
Type: typ,
|
||||||
}
|
}
|
||||||
|
|
||||||
ct.SetTypeDecl(cursor, decl)
|
ct.SetTypeDecl(cursor, decl)
|
||||||
return decl
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) ProcessRecordType(cursor clang.Cursor) *ast.RecordType {
|
func (ct *Converter) ProcessRecordType(cursor clang.Cursor) *ast.RecordType {
|
||||||
|
ct.incIndent()
|
||||||
|
defer ct.decIndent()
|
||||||
|
|
||||||
|
cursorName, cursorKind := getCursorDesc(cursor)
|
||||||
|
ct.logln("ProcessRecordType: CursorName:", cursorName, "CursorKind:", cursorKind)
|
||||||
|
|
||||||
|
tag := toTag(cursor.Kind)
|
||||||
|
ct.logln("ProcessRecordType: toTag", tag)
|
||||||
|
|
||||||
|
ct.logln("ProcessRecordType: ProcessFieldList")
|
||||||
|
fields := ct.ProcessFieldList(cursor)
|
||||||
|
|
||||||
|
ct.logln("ProcessRecordType: ProcessMethods")
|
||||||
|
methods := ct.ProcessMethods(cursor)
|
||||||
|
|
||||||
return &ast.RecordType{
|
return &ast.RecordType{
|
||||||
Tag: toTag(cursor.Kind),
|
Tag: tag,
|
||||||
Fields: ct.ProcessFieldList(cursor),
|
Fields: fields,
|
||||||
Methods: ct.ProcessMethods(cursor),
|
Methods: methods,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,8 +839,10 @@ func (ct *Converter) ProcessRecordType(cursor clang.Cursor) *ast.RecordType {
|
|||||||
// - Examples: struct { int x; int y; }, union { int a; float b; }
|
// - Examples: struct { int x; int y; }, union { int a; float b; }
|
||||||
// - Handling: Retrieve their corresponding concrete types
|
// - Handling: Retrieve their corresponding concrete types
|
||||||
func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr {
|
func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr {
|
||||||
name := t.String()
|
ct.incIndent()
|
||||||
defer name.Dispose()
|
defer ct.decIndent()
|
||||||
|
typeName, typeKind := getTypeDesc(t)
|
||||||
|
ct.logln("ProcessElaboratedType: TypeName:", typeName, "TypeKind:", typeKind)
|
||||||
|
|
||||||
decl := t.TypeDeclaration()
|
decl := t.TypeDeclaration()
|
||||||
isAnony, ok := ct.GetAnonyType(decl)
|
isAnony, ok := ct.GetAnonyType(decl)
|
||||||
@@ -804,8 +855,6 @@ func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr {
|
|||||||
return ct.ProcessRecordType(decl)
|
return ct.ProcessRecordType(decl)
|
||||||
}
|
}
|
||||||
|
|
||||||
typeName := c.GoString(name.CStr())
|
|
||||||
|
|
||||||
// for elaborated type, it could have a tag description
|
// for elaborated type, it could have a tag description
|
||||||
// like struct A, union B, class C, enum D
|
// like struct A, union B, class C, enum D
|
||||||
parts := strings.SplitN(typeName, " ", 2)
|
parts := strings.SplitN(typeName, " ", 2)
|
||||||
@@ -822,6 +871,11 @@ func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) ProcessBuiltinType(t clang.Type) *ast.BuiltinType {
|
func (ct *Converter) ProcessBuiltinType(t clang.Type) *ast.BuiltinType {
|
||||||
|
ct.incIndent()
|
||||||
|
defer ct.decIndent()
|
||||||
|
typeName, typeKind := getTypeDesc(t)
|
||||||
|
ct.logln("ProcessBuiltinType: TypeName:", typeName, "TypeKind:", typeKind)
|
||||||
|
|
||||||
kind := ast.Void
|
kind := ast.Void
|
||||||
var flags ast.TypeFlag
|
var flags ast.TypeFlag
|
||||||
|
|
||||||
@@ -874,9 +928,8 @@ func (ct *Converter) ProcessBuiltinType(t clang.Type) *ast.BuiltinType {
|
|||||||
// float complfex flag is not set
|
// float complfex flag is not set
|
||||||
default:
|
default:
|
||||||
// like IBM128,NullPtr,Accum
|
// like IBM128,NullPtr,Accum
|
||||||
kindStr := t.Kind.String()
|
kindStr := toStr(t.Kind.String())
|
||||||
defer kindStr.Dispose()
|
fmt.Fprintln(os.Stderr, "todo: unknown builtin type:", kindStr)
|
||||||
fmt.Fprintln(os.Stderr, "todo: unknown builtin type:", c.GoString(kindStr.CStr()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if IsExplicitSigned(t) {
|
if IsExplicitSigned(t) {
|
||||||
@@ -983,3 +1036,23 @@ func isAnonymousStructure(sourceCode []*ast.Token) bool {
|
|||||||
sourceCode[1].Token == token.PUNCT &&
|
sourceCode[1].Token == token.PUNCT &&
|
||||||
sourceCode[1].Lit == "{"
|
sourceCode[1].Lit == "{"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toStr(clangStr clang.String) (str string) {
|
||||||
|
defer clangStr.Dispose()
|
||||||
|
if clangStr.CStr() != nil {
|
||||||
|
str = c.GoString(clangStr.CStr())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTypeDesc(t clang.Type) (name string, kind string) {
|
||||||
|
name = toStr(t.String())
|
||||||
|
kind = toStr(t.Kind.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCursorDesc(cursor clang.Cursor) (name string, kind string) {
|
||||||
|
name = toStr(cursor.String())
|
||||||
|
kind = toStr(cursor.Kind.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user