llcppsigfetch:Scope Context

This commit is contained in:
luoliwoshang
2024-08-15 11:26:34 +08:00
parent f613316046
commit 2c8a9d1160
4 changed files with 236 additions and 59 deletions

View File

@@ -12,12 +12,12 @@ import (
) )
type Converter struct { type Converter struct {
files map[string]*ast.File files map[string]*ast.File
curLoc ast.Location curLoc ast.Location
curFile *ast.File curFile *ast.File
index *clang.Index index *clang.Index
unit *clang.TranslationUnit unit *clang.TranslationUnit
// todo(zzy):current namespace expr scopeStack []ast.Expr //namespace & class
} }
func NewConverter(file string, temp bool) (*Converter, error) { func NewConverter(file string, temp bool) (*Converter, error) {
@@ -68,41 +68,31 @@ func (ct *Converter) Dispose() {
ct.unit.Dispose() ct.unit.Dispose()
} }
// visit top decls (struct,class,function,enum & marco,include) func (ct *Converter) PushScope(cursor clang.Cursor) {
func visit(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult { name := cursor.String()
ct := (*Converter)(clientData) defer name.Dispose()
ct.UpdateCurFile(cursor) ident := &ast.Ident{Name: c.GoString(name.CStr())}
switch cursor.Kind { if len(ct.scopeStack) == 0 {
case clang.CursorInclusionDirective: ct.scopeStack = append(ct.scopeStack, ident)
// todo(zzy) } else {
return clang.ChildVisit_Continue parent := ct.scopeStack[len(ct.scopeStack)-1]
case clang.CursorMacroDefinition: newContext := &ast.ScopingExpr{Parent: parent, X: ident}
// todo(zzy) ct.scopeStack = append(ct.scopeStack, newContext)
return clang.ChildVisit_Continue
case clang.CursorEnumDecl:
// todo(zzy)
return clang.ChildVisit_Continue
case clang.CursorClassDecl:
ct.ProcessClass(cursor)
return clang.ChildVisit_Continue
case clang.CursorStructDecl:
// todo(zzy)
return clang.ChildVisit_Continue
case clang.CursorFunctionDecl:
ct.ProcessFunc(cursor)
return clang.ChildVisit_Continue
default:
// non-top-level decl, continue recursion
return clang.ChildVisit_Recurse
} }
} }
func (ct *Converter) Convert() (map[string]*ast.File, error) { func (ct *Converter) PopScope() {
cursor := ct.unit.Cursor() if len(ct.scopeStack) > 0 {
// visit top decls (struct,class,function & marco,include) ct.scopeStack = ct.scopeStack[:len(ct.scopeStack)-1]
clang.VisitChildren(cursor, visit, c.Pointer(ct)) }
return ct.files, nil }
func (ct *Converter) GetCurScope() ast.Expr {
if len(ct.scopeStack) == 0 {
return nil
}
return ct.scopeStack[len(ct.scopeStack)-1]
} }
func (ct *Converter) UpdateCurFile(cursor clang.Cursor) { func (ct *Converter) UpdateCurFile(cursor clang.Cursor) {
@@ -118,6 +108,8 @@ func (ct *Converter) UpdateCurFile(cursor clang.Cursor) {
} }
filePath := c.GoString(filename.CStr()) filePath := c.GoString(filename.CStr())
ct.curLoc = ast.Location{File: filePath}
if ct.curFile == nil || ct.curFile.Path != filePath { if ct.curFile == nil || ct.curFile.Path != filePath {
if f, ok := ct.files[filePath]; ok { if f, ok := ct.files[filePath]; ok {
ct.curFile = f ct.curFile = f
@@ -128,11 +120,53 @@ func (ct *Converter) UpdateCurFile(cursor clang.Cursor) {
Includes: make([]*ast.Include, 0), Includes: make([]*ast.Include, 0),
Macros: make([]*ast.Macro, 0), Macros: make([]*ast.Macro, 0),
} }
ct.files[filePath] = ct.curFile
} }
ct.files[filePath] = ct.curFile
} }
} }
func (ct *Converter) CreateDeclBase(cursor clang.Cursor) ast.DeclBase {
return ast.DeclBase{
Loc: &ct.curLoc,
Parent: ct.GetCurScope(),
}
}
// visit top decls (struct,class,function,enum & marco,include)
func visit(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult {
ct := (*Converter)(clientData)
ct.UpdateCurFile(cursor)
switch cursor.Kind {
case clang.CursorInclusionDirective:
// todo(zzy)
case clang.CursorMacroDefinition:
// todo(zzy)
case clang.CursorEnumDecl:
// todo(zzy)
case clang.CursorClassDecl:
ct.PushScope(cursor)
ct.ProcessClass(cursor)
ct.PopScope()
case clang.CursorStructDecl:
// todo(zzy)
case clang.CursorFunctionDecl:
ct.ProcessFunc(cursor)
case clang.CursorNamespace:
ct.PushScope(cursor)
clang.VisitChildren(cursor, visit, c.Pointer(ct))
ct.PopScope()
}
return clang.ChildVisit_Continue
}
func (ct *Converter) Convert() (map[string]*ast.File, error) {
cursor := ct.unit.Cursor()
// visit top decls (struct,class,function & marco,include)
clang.VisitChildren(cursor, visit, c.Pointer(ct))
return ct.files, nil
}
func (ct *Converter) ProcessType(t clang.Type) ast.Expr { func (ct *Converter) ProcessType(t clang.Type) ast.Expr {
var expr ast.Expr var expr ast.Expr
if t.Kind >= clang.TypeFirstBuiltin && t.Kind <= clang.TypeLastBuiltin { if t.Kind >= clang.TypeFirstBuiltin && t.Kind <= clang.TypeLastBuiltin {
@@ -179,12 +213,11 @@ func (ct *Converter) ProcessFunc(cursor clang.Cursor) {
params := ct.ProcessFuncParams(cursor) params := ct.ProcessFuncParams(cursor)
funcType.Params = params funcType.Params = params
fn := &ast.FuncDecl{ fn := &ast.FuncDecl{
Name: &ast.Ident{Name: c.GoString(name.CStr())}, DeclBase: ct.CreateDeclBase(cursor),
Type: funcType, Name: &ast.Ident{Name: c.GoString(name.CStr())},
// todo(zzy):DeclBase use the converter's current namespace expr Type: funcType,
} }
ct.curFile.Decls = append(ct.curFile.Decls, fn) ct.curFile.Decls = append(ct.curFile.Decls, fn)
// ct.declMap[cursor] = fn
} }
type visitParamContext struct { type visitParamContext struct {

View File

@@ -7,6 +7,7 @@ import (
func main() { func main() {
TestFuncDecl() TestFuncDecl()
TestScope()
} }
func TestFuncDecl() { func TestFuncDecl() {
@@ -35,7 +36,38 @@ func TestFuncDecl() {
} }
json := converter.GetFilesJSON() json := converter.GetFilesJSON()
c.Printf(c.Str("Test Case %d:\n%s\n\n"), c.Int(i+1), json.Print()) c.Printf(c.Str("TestFuncDecl Case %d:\n%s\n\n"), c.Int(i+1), json.Print())
converter.Dispose()
}
}
func TestScope() {
testCases := []string{
`void foo();`,
`namespace a {
void foo();
}`,
`namespace a {
namespace b {
void foo();
}
}`,
}
for i, content := range testCases {
converter, err := parse.NewConverter(content, true)
if err != nil {
panic(err)
}
_, err = converter.Convert()
if err != nil {
panic(err)
}
json := converter.GetFilesJSON()
c.Printf(c.Str("TestScope Case %d:\n%s\n\n"), c.Int(i+1), json.Print())
converter.Dispose() converter.Dispose()
} }

View File

@@ -1,10 +1,12 @@
#stdout #stdout
Test Case 1: TestFuncDecl Case 1:
{ {
"temp.h": { "temp.h": {
"path": "temp.h", "path": "temp.h",
"decls": [{ "decls": [{
"Loc": null, "Loc": {
"File": "temp.h"
},
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": {
@@ -25,12 +27,14 @@ Test Case 1:
} }
} }
Test Case 2: TestFuncDecl Case 2:
{ {
"temp.h": { "temp.h": {
"path": "temp.h", "path": "temp.h",
"decls": [{ "decls": [{
"Loc": null, "Loc": {
"File": "temp.h"
},
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": {
@@ -61,12 +65,14 @@ Test Case 2:
} }
} }
Test Case 3: TestFuncDecl Case 3:
{ {
"temp.h": { "temp.h": {
"path": "temp.h", "path": "temp.h",
"decls": [{ "decls": [{
"Loc": null, "Loc": {
"File": "temp.h"
},
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": {
@@ -107,12 +113,14 @@ Test Case 3:
} }
} }
Test Case 4: TestFuncDecl Case 4:
{ {
"temp.h": { "temp.h": {
"path": "temp.h", "path": "temp.h",
"decls": [{ "decls": [{
"Loc": null, "Loc": {
"File": "temp.h"
},
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": {
@@ -155,12 +163,14 @@ Test Case 4:
} }
} }
Test Case 5: TestFuncDecl Case 5:
{ {
"temp.h": { "temp.h": {
"path": "temp.h", "path": "temp.h",
"decls": [{ "decls": [{
"Loc": null, "Loc": {
"File": "temp.h"
},
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": {
@@ -205,12 +215,14 @@ Test Case 5:
} }
} }
Test Case 6: TestFuncDecl Case 6:
{ {
"temp.h": { "temp.h": {
"path": "temp.h", "path": "temp.h",
"decls": [{ "decls": [{
"Loc": null, "Loc": {
"File": "temp.h"
},
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": {
@@ -259,12 +271,14 @@ Test Case 6:
} }
} }
Test Case 7: TestFuncDecl Case 7:
{ {
"temp.h": { "temp.h": {
"path": "temp.h", "path": "temp.h",
"decls": [{ "decls": [{
"Loc": null, "Loc": {
"File": "temp.h"
},
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": {
@@ -310,12 +324,14 @@ Test Case 7:
} }
} }
Test Case 8: TestFuncDecl Case 8:
{ {
"temp.h": { "temp.h": {
"path": "temp.h", "path": "temp.h",
"decls": [{ "decls": [{
"Loc": null, "Loc": {
"File": "temp.h"
},
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": {
@@ -360,6 +376,99 @@ Test Case 8:
} }
} }
TestScope Case 1:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": null,
"Name": {
"Name": "foo"
},
"Type": {
"Params": {
"List": []
},
"Ret": {
"Kind": 0,
"Flags": 0
}
}
}],
"includes": [],
"macros": []
}
}
TestScope Case 2:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": {
"Name": "a"
},
"Name": {
"Name": "foo"
},
"Type": {
"Params": {
"List": []
},
"Ret": {
"Kind": 0,
"Flags": 0
}
}
}],
"includes": [],
"macros": []
}
}
TestScope Case 3:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": {
"X": {
"Name": "b"
},
"Parent": {
"Name": "a"
}
},
"Name": {
"Name": "foo"
},
"Type": {
"Params": {
"List": []
},
"Ret": {
"Kind": 0,
"Flags": 0
}
}
}],
"includes": [],
"macros": []
}
}
#stderr #stderr

View File

@@ -109,6 +109,9 @@ func (ct *Converter) TypeJSON(t ast.Expr) *cjson.JSON {
list.AddItem(ct.TypeJSON(c)) list.AddItem(ct.TypeJSON(c))
} }
root.SetItem(c.Str("List"), list) root.SetItem(c.Str("List"), list)
case *ast.ScopingExpr:
root.SetItem(c.Str("X"), ct.TypeJSON(d.X))
root.SetItem(c.Str("Parent"), ct.TypeJSON(d.Parent))
default: default:
return cjson.Null() return cjson.Null()
} }