llcppsymg:refine logic & parse symbol test

This commit is contained in:
luoliwoshang
2024-09-24 19:17:36 +08:00
parent 29d527bee1
commit a83f7a822e
5 changed files with 292 additions and 68 deletions

View File

@@ -15,27 +15,27 @@ type SymbolInfo struct {
ProtoName string
}
type Context struct {
prefixes []string
symbolMap map[string]*SymbolInfo
currentFile string
nameCounts map[string]int
type SymbolProcessor struct {
Prefixes []string
SymbolMap map[string]*SymbolInfo
CurrentFile string
NameCounts map[string]int
}
func newContext(prefixes []string) *Context {
return &Context{
prefixes: prefixes,
symbolMap: make(map[string]*SymbolInfo),
nameCounts: make(map[string]int),
func NewSymbolProcessor(Prefixes []string) *SymbolProcessor {
return &SymbolProcessor{
Prefixes: Prefixes,
SymbolMap: make(map[string]*SymbolInfo),
NameCounts: make(map[string]int),
}
}
func (c *Context) setCurrentFile(filename string) {
c.currentFile = filename
func (p *SymbolProcessor) setCurrentFile(filename string) {
p.CurrentFile = filename
}
func (c *Context) removePrefix(str string) string {
for _, prefix := range c.prefixes {
func (p *SymbolProcessor) TrimPrefixes(str string) string {
for _, prefix := range p.Prefixes {
if strings.HasPrefix(str, prefix) {
return strings.TrimPrefix(str, prefix)
}
@@ -47,10 +47,10 @@ func toTitle(s string) string {
if s == "" {
return ""
}
return strings.ToUpper(s[:1]) + strings.ToLower(s[1:])
return strings.ToUpper(s[:1]) + (s[1:])
}
func toCamel(originName string) string {
func toUpperCamelCase(originName string) string {
if originName == "" {
return ""
}
@@ -64,38 +64,44 @@ func toCamel(originName string) string {
// 1. remove prefix from config
// 2. convert to camel case
func (c *Context) toGoName(name string) string {
name = c.removePrefix(name)
return toCamel(name)
func (p *SymbolProcessor) ToGoName(name string) string {
return toUpperCamelCase(p.TrimPrefixes(name))
}
func (p *Context) genGoName(cursor clang.Cursor) string {
funcName := cursor.String()
defer funcName.Dispose()
name := p.toGoName(c.GoString(funcName.CStr()))
if parent := cursor.SemanticParent(); parent.Kind == clang.CursorClassDecl {
parentName := parent.String()
defer parentName.Dispose()
class := p.toGoName(c.GoString(parentName.CStr()))
return p.addSuffix(p.genMethodName(class, name))
}
return p.addSuffix(name)
}
func (c *Context) genMethodName(class, name string) string {
func (p *SymbolProcessor) GenMethodName(class, name string, isDestructor bool) string {
prefix := "(*" + class + ")."
if isDestructor {
return prefix + "Dispose"
}
if class == name {
return prefix + "Init"
}
if name == "~"+class {
return prefix + "Dispose"
}
return prefix + name
}
func (p *Context) genProtoName(cursor clang.Cursor) string {
func (p *SymbolProcessor) genGoName(cursor clang.Cursor) string {
funcName := cursor.String()
defer funcName.Dispose()
originName := c.GoString(funcName.CStr())
isDestructor := cursor.Kind == clang.CursorDestructor
var convertedName string
if isDestructor {
convertedName = p.ToGoName(originName[1:])
} else {
convertedName = p.ToGoName(originName)
}
if parent := cursor.SemanticParent(); parent.Kind == clang.CursorClassDecl {
parentName := parent.String()
defer parentName.Dispose()
class := p.ToGoName(c.GoString(parentName.CStr()))
return p.AddSuffix(p.GenMethodName(class, convertedName, isDestructor))
}
return p.AddSuffix(convertedName)
}
func (p *SymbolProcessor) genProtoName(cursor clang.Cursor) string {
displayName := cursor.DisplayName()
defer displayName.Dispose()
@@ -111,36 +117,32 @@ func (p *Context) genProtoName(cursor clang.Cursor) string {
return builder.String()
}
func (c *Context) addSuffix(name string) string {
c.nameCounts[name]++
count := c.nameCounts[name]
if count > 1 {
func (p *SymbolProcessor) AddSuffix(name string) string {
p.NameCounts[name]++
if count := p.NameCounts[name]; count > 1 {
return name + "__" + strconv.Itoa(count-1)
}
return name
}
var context = newContext([]string{})
func collectFuncInfo(cursor clang.Cursor) {
func (p *SymbolProcessor) collectFuncInfo(cursor clang.Cursor) {
symbol := cursor.Mangling()
defer symbol.Dispose()
symbolName := c.GoString(symbol.CStr())
if len(symbolName) >= 1 && symbolName[0] == '_' {
symbolName = symbolName[1:]
}
defer symbol.Dispose()
context.symbolMap[symbolName] = &SymbolInfo{
GoName: context.genGoName(cursor),
ProtoName: context.genProtoName(cursor),
p.SymbolMap[symbolName] = &SymbolInfo{
GoName: p.genGoName(cursor),
ProtoName: p.genProtoName(cursor),
}
}
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
func (p *SymbolProcessor) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResult {
switch cursor.Kind {
case clang.CursorNamespace, clang.CursorClassDecl:
clang.VisitChildren(cursor, visit, nil)
clangutils.VisitChildren(cursor, p.visitTop)
case clang.CursorCXXMethod, clang.CursorFunctionDecl, clang.CursorConstructor, clang.CursorDestructor:
loc := cursor.Location()
var file clang.File
@@ -148,35 +150,38 @@ func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitRe
filename := file.FileName()
defer filename.Dispose()
isCurrentFile := c.Strcmp(filename.CStr(), c.AllocaCStr(context.currentFile)) == 0
isCurrentFile := c.Strcmp(filename.CStr(), c.AllocaCStr(p.CurrentFile)) == 0
isPublicMethod := (cursor.CXXAccessSpecifier() == clang.CXXPublic) && cursor.Kind == clang.CursorCXXMethod || cursor.Kind == clang.CursorConstructor || cursor.Kind == clang.CursorDestructor
if isCurrentFile && (cursor.Kind == clang.CursorFunctionDecl || isPublicMethod) {
collectFuncInfo(cursor)
p.collectFuncInfo(cursor)
}
}
return clang.ChildVisit_Continue
}
func ParseHeaderFile(filepaths []string, prefixes []string, isCpp bool) (map[string]*SymbolInfo, error) {
context = newContext(prefixes)
func ParseHeaderFile(files []string, Prefixes []string, isCpp bool, isTemp bool) (map[string]*SymbolInfo, error) {
processer := NewSymbolProcessor(Prefixes)
index := clang.CreateIndex(0, 0)
for _, filename := range filepaths {
for _, file := range files {
_, unit, err := clangutils.CreateTranslationUnit(&clangutils.Config{
File: filename,
Temp: false,
File: file,
Temp: isTemp,
IsCpp: isCpp,
Index: index,
})
if err != nil {
return nil, errors.New("Unable to parse translation unit for file " + filename)
return nil, errors.New("Unable to parse translation unit for file " + file)
}
cursor := unit.Cursor()
context.setCurrentFile(filename)
clang.VisitChildren(cursor, visit, nil)
if isTemp {
processer.setCurrentFile(clangutils.TEMP_FILE)
} else {
processer.setCurrentFile(file)
}
clangutils.VisitChildren(cursor, processer.visitTop)
unit.Dispose()
}
index.Dispose()
return context.symbolMap, nil
return processer.SymbolMap, nil
}