-
Notifications
You must be signed in to change notification settings - Fork 0
/
visitchildren.go
83 lines (63 loc) · 2.36 KB
/
visitchildren.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package libclang
/*
#include <clang-c/Index.h>
enum CXChildVisitResult visitChildrenCallback(CXCursor cursor, CXCursor parent, CXClientData client_data);
static void visitChildren(CXCursor parent, CXClientData client_data) {
clang_visitChildren(parent, visitChildrenCallback, client_data);
}
*/
import "C"
import (
"runtime"
"sync"
)
type ChildVisitResult C.enum_CXChildVisitResult
const ChildVisit_Break = ChildVisitResult(C.CXChildVisit_Break)
const ChildVisit_Continue = ChildVisitResult(C.CXChildVisit_Continue)
const ChildVisit_Recurse = ChildVisitResult(C.CXChildVisit_Recurse)
type childVisitCallback func(cursor C.CXCursor, parent C.CXCursor) C.enum_CXChildVisitResult
type ChildVisitCallback func(cursor Cursor, parent Cursor) ChildVisitResult
var childVisitCallbackId int
var childVisitCallbackInstanceMap = make(map[int]childVisitCallback)
var childVisitCallbackLock sync.Mutex
func getChildVisitCallbackForId(data C.CXClientData) childVisitCallback {
childVisitCallbackLock.Lock()
defer childVisitCallbackLock.Unlock()
return childVisitCallbackInstanceMap[int(uintptr(data))]
}
func getChildVisitCallbackId(cb childVisitCallback) C.CXClientData {
childVisitCallbackLock.Lock()
defer childVisitCallbackLock.Unlock()
childVisitCallbackId++
childVisitCallbackInstanceMap[childVisitCallbackId] = cb
return intToCXClientData(childVisitCallbackId)
}
//export visitChildrenCallback
func visitChildrenCallback(cursor C.CXCursor, parent C.CXCursor, data C.CXClientData) C.enum_CXChildVisitResult {
var pinner runtime.Pinner
pinner.Pin(&cursor)
pinner.Pin(&parent)
defer pinner.Unpin()
cb := getChildVisitCallbackForId(data)
return cb(cursor, parent)
}
func visitChildren(cursor C.CXCursor, cb childVisitCallback) {
C.visitChildren(cursor, getChildVisitCallbackId(cb))
}
func VisitChildren(cursor Cursor, cb ChildVisitCallback) {
visitChildren(cursor.c(), func(cursor, parent C.CXCursor) C.enum_CXChildVisitResult {
var pinner runtime.Pinner
pinner.Pin(&cursor)
pinner.Pin(&parent)
defer pinner.Unpin()
// Ignore children that are in system headers.
// May want to make this configurable in the future.
loc := C.clang_getCursorLocation(cursor)
inSystemHeader := C.clang_Location_isInSystemHeader(loc) != 0
if inSystemHeader {
return C.CXChildVisit_Continue
}
res := cb(Cursor(cursor), Cursor(parent))
return C.enum_CXChildVisitResult(res)
})
}