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 {
files map[string]*ast.File
curLoc ast.Location
curFile *ast.File
index *clang.Index
unit *clang.TranslationUnit
// todo(zzy):current namespace expr
files map[string]*ast.File
curLoc ast.Location
curFile *ast.File
index *clang.Index
unit *clang.TranslationUnit
scopeStack []ast.Expr //namespace & class
}
func NewConverter(file string, temp bool) (*Converter, error) {
@@ -68,41 +68,31 @@ func (ct *Converter) Dispose() {
ct.unit.Dispose()
}
// 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)
func (ct *Converter) PushScope(cursor clang.Cursor) {
name := cursor.String()
defer name.Dispose()
ident := &ast.Ident{Name: c.GoString(name.CStr())}
switch cursor.Kind {
case clang.CursorInclusionDirective:
// todo(zzy)
return clang.ChildVisit_Continue
case clang.CursorMacroDefinition:
// todo(zzy)
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
if len(ct.scopeStack) == 0 {
ct.scopeStack = append(ct.scopeStack, ident)
} else {
parent := ct.scopeStack[len(ct.scopeStack)-1]
newContext := &ast.ScopingExpr{Parent: parent, X: ident}
ct.scopeStack = append(ct.scopeStack, newContext)
}
}
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) PopScope() {
if len(ct.scopeStack) > 0 {
ct.scopeStack = ct.scopeStack[:len(ct.scopeStack)-1]
}
}
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) {
@@ -118,6 +108,8 @@ func (ct *Converter) UpdateCurFile(cursor clang.Cursor) {
}
filePath := c.GoString(filename.CStr())
ct.curLoc = ast.Location{File: filePath}
if ct.curFile == nil || ct.curFile.Path != filePath {
if f, ok := ct.files[filePath]; ok {
ct.curFile = f
@@ -128,11 +120,53 @@ func (ct *Converter) UpdateCurFile(cursor clang.Cursor) {
Includes: make([]*ast.Include, 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 {
var expr ast.Expr
if t.Kind >= clang.TypeFirstBuiltin && t.Kind <= clang.TypeLastBuiltin {
@@ -179,12 +213,11 @@ func (ct *Converter) ProcessFunc(cursor clang.Cursor) {
params := ct.ProcessFuncParams(cursor)
funcType.Params = params
fn := &ast.FuncDecl{
Name: &ast.Ident{Name: c.GoString(name.CStr())},
Type: funcType,
// todo(zzy):DeclBase use the converter's current namespace expr
DeclBase: ct.CreateDeclBase(cursor),
Name: &ast.Ident{Name: c.GoString(name.CStr())},
Type: funcType,
}
ct.curFile.Decls = append(ct.curFile.Decls, fn)
// ct.declMap[cursor] = fn
}
type visitParamContext struct {

View File

@@ -7,6 +7,7 @@ import (
func main() {
TestFuncDecl()
TestScope()
}
func TestFuncDecl() {
@@ -35,7 +36,38 @@ func TestFuncDecl() {
}
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()
}

View File

@@ -1,10 +1,12 @@
#stdout
Test Case 1:
TestFuncDecl Case 1:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": null,
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": null,
"Name": {
@@ -25,12 +27,14 @@ Test Case 1:
}
}
Test Case 2:
TestFuncDecl Case 2:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": null,
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": null,
"Name": {
@@ -61,12 +65,14 @@ Test Case 2:
}
}
Test Case 3:
TestFuncDecl Case 3:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": null,
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": null,
"Name": {
@@ -107,12 +113,14 @@ Test Case 3:
}
}
Test Case 4:
TestFuncDecl Case 4:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": null,
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": null,
"Name": {
@@ -155,12 +163,14 @@ Test Case 4:
}
}
Test Case 5:
TestFuncDecl Case 5:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": null,
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": null,
"Name": {
@@ -205,12 +215,14 @@ Test Case 5:
}
}
Test Case 6:
TestFuncDecl Case 6:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": null,
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": null,
"Name": {
@@ -259,12 +271,14 @@ Test Case 6:
}
}
Test Case 7:
TestFuncDecl Case 7:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": null,
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": null,
"Name": {
@@ -310,12 +324,14 @@ Test Case 7:
}
}
Test Case 8:
TestFuncDecl Case 8:
{
"temp.h": {
"path": "temp.h",
"decls": [{
"Loc": null,
"Loc": {
"File": "temp.h"
},
"Doc": null,
"Parent": null,
"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

View File

@@ -109,6 +109,9 @@ func (ct *Converter) TypeJSON(t ast.Expr) *cjson.JSON {
list.AddItem(ct.TypeJSON(c))
}
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:
return cjson.Null()
}