Merge pull request #683 from luoliwoshang/llcppsigfetch/basic
llcppsigfetch
This commit is contained in:
@@ -16,6 +16,169 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/cjson"
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse"
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsymg/config"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// TODO(xsw): implement llcppsigfetch tool
|
if len(os.Args) == 1 {
|
||||||
|
// run with default config file
|
||||||
|
runFromConfig()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Args[1] == "--extract" {
|
||||||
|
runExtract()
|
||||||
|
} else if os.Args[1] == "--help" || os.Args[1] == "-h" {
|
||||||
|
printUsage()
|
||||||
|
} else {
|
||||||
|
runFromConfig()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printUsage() {
|
||||||
|
fmt.Println("Usage:")
|
||||||
|
fmt.Println(" llcppsigfetch [<config_file>]")
|
||||||
|
fmt.Println(" OR")
|
||||||
|
fmt.Println(" llcppsigfetch --extract <file> <temp> [args...]")
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Println("Options:")
|
||||||
|
fmt.Println(" [<config_file>]: Path to the configuration file (use '-' for stdin)")
|
||||||
|
fmt.Println(" If not provided, uses default 'llcppg.cfg'")
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Println(" --extract: Extract information from a single file")
|
||||||
|
fmt.Println(" <file>: Path to the file to process, or file content if -temp=true")
|
||||||
|
fmt.Println(" -temp=<bool>: Optional. Set to 'true' if <file> contains file content,")
|
||||||
|
fmt.Println(" 'false' (default) if it's a file path")
|
||||||
|
fmt.Println(" -cpp=<bool>: Optional. Set to 'true' if the language is C++ (default: true)")
|
||||||
|
fmt.Println(" If not present, <file> is a file path")
|
||||||
|
fmt.Println(" [args]: Optional additional arguments")
|
||||||
|
fmt.Println(" Default for C++: -x c++")
|
||||||
|
fmt.Println(" Default for C: -x c")
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Println(" --help, -h: Show this help message")
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Println("Note: The two usage modes are mutually exclusive. Use either [<config_file>] OR --extract, not both.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runFromConfig() {
|
||||||
|
cfgFile := "llcppg.cfg"
|
||||||
|
if len(os.Args) > 1 {
|
||||||
|
cfgFile = os.Args[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
var err error
|
||||||
|
if cfgFile == "-" {
|
||||||
|
data, err = io.ReadAll(os.Stdin)
|
||||||
|
} else {
|
||||||
|
data, err = os.ReadFile(cfgFile)
|
||||||
|
}
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
conf, err := config.GetConf(data)
|
||||||
|
check(err)
|
||||||
|
defer conf.Delete()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "Failed to parse config file:", cfgFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
files := getHeaderFiles(conf.CFlags, conf.Include)
|
||||||
|
|
||||||
|
context := parse.NewContext(conf.Cplusplus)
|
||||||
|
err = context.ProcessFiles(files)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
outputInfo(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runExtract() {
|
||||||
|
if len(os.Args) < 3 {
|
||||||
|
fmt.Println("Error: Insufficient arguments for --extract")
|
||||||
|
printUsage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := &parse.Config{
|
||||||
|
File: os.Args[2],
|
||||||
|
Args: []string{},
|
||||||
|
IsCpp: true,
|
||||||
|
Temp: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 3; i < len(os.Args); i++ {
|
||||||
|
arg := os.Args[i]
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(arg, "-temp="):
|
||||||
|
cfg.Temp = parseBoolArg(arg, "temp", false)
|
||||||
|
os.Args = append(os.Args[:i], os.Args[i+1:]...)
|
||||||
|
i--
|
||||||
|
case strings.HasPrefix(arg, "-cpp="):
|
||||||
|
cfg.IsCpp = parseBoolArg(arg, "cpp", true)
|
||||||
|
os.Args = append(os.Args[:i], os.Args[i+1:]...)
|
||||||
|
i--
|
||||||
|
default:
|
||||||
|
cfg.Args = append(cfg.Args, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
converter, err := parse.NewConverter(cfg)
|
||||||
|
check(err)
|
||||||
|
_, err = converter.Convert()
|
||||||
|
check(err)
|
||||||
|
result := converter.MarshalOutputASTFiles()
|
||||||
|
cstr := result.Print()
|
||||||
|
c.Printf(cstr)
|
||||||
|
cjson.FreeCStr(cstr)
|
||||||
|
result.Delete()
|
||||||
|
converter.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(err error) {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHeaderFiles(cflags string, files []string) []string {
|
||||||
|
prefix := cflags
|
||||||
|
prefix = strings.TrimPrefix(prefix, "-I")
|
||||||
|
var paths []string
|
||||||
|
for _, f := range files {
|
||||||
|
paths = append(paths, filepath.Join(prefix, f))
|
||||||
|
}
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
|
||||||
|
func outputInfo(context *parse.Context) {
|
||||||
|
info := context.Output()
|
||||||
|
str := info.Print()
|
||||||
|
defer cjson.FreeCStr(str)
|
||||||
|
defer info.Delete()
|
||||||
|
c.Printf(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBoolArg(arg, name string, defaultValue bool) bool {
|
||||||
|
parts := strings.SplitN(arg, "=", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
fmt.Printf("Warning: Invalid -%s= argument, defaulting to %v\n", name, defaultValue)
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
value, err := strconv.ParseBool(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Warning: Invalid -%s= value '%s', defaulting to %v\n", name, parts[1], defaultValue)
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
|
|||||||
955
chore/_xtool/llcppsigfetch/parse/cvt.go
Normal file
955
chore/_xtool/llcppsigfetch/parse/cvt.go
Normal file
@@ -0,0 +1,955 @@
|
|||||||
|
package parse
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/cjson"
|
||||||
|
"github.com/goplus/llgo/c/clang"
|
||||||
|
"github.com/goplus/llgo/chore/llcppg/ast"
|
||||||
|
"github.com/goplus/llgo/chore/llcppg/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileEntry struct {
|
||||||
|
Path string
|
||||||
|
Doc *ast.File
|
||||||
|
}
|
||||||
|
|
||||||
|
type Converter struct {
|
||||||
|
Files []*FileEntry
|
||||||
|
FileOrder []string // todo(zzy): more efficient struct
|
||||||
|
curLoc ast.Location
|
||||||
|
index *clang.Index
|
||||||
|
unit *clang.TranslationUnit
|
||||||
|
|
||||||
|
typeDecls map[string]ast.Decl // cursorUsr -> ast.Decl
|
||||||
|
|
||||||
|
// anonyTypeMap stores mappings for unexpected named declarations in typedefs
|
||||||
|
// that actually represent anonymous types.
|
||||||
|
//
|
||||||
|
// Key: The USR (Unified Symbol Resolution) of the declaration cursor.
|
||||||
|
// Value: The generated name for the anonymous type.
|
||||||
|
//
|
||||||
|
// This map is necessary due to a limitation in libclang where anonymous
|
||||||
|
// structs, unions, or enums within typedefs are incorrectly reported as
|
||||||
|
// named declarations. We use this map to keep track of these cases and
|
||||||
|
// generate appropriate names for them.
|
||||||
|
//
|
||||||
|
// Additionally, for all nodes referencing these anonymous types, their
|
||||||
|
// name references are updated to use the corresponding anonyname from
|
||||||
|
// this map. This ensures consistent naming across the entire AST for
|
||||||
|
// these anonymous types.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// typedef struct { int x; } MyStruct;
|
||||||
|
anonyTypeMap map[string]bool // cursorUsr
|
||||||
|
}
|
||||||
|
|
||||||
|
var tagMap = map[string]ast.Tag{
|
||||||
|
"struct": ast.Struct,
|
||||||
|
"union": ast.Union,
|
||||||
|
"enum": ast.Enum,
|
||||||
|
"class": ast.Class,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
File string
|
||||||
|
Temp bool
|
||||||
|
Args []string
|
||||||
|
IsCpp bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConverter(config *Config) (*Converter, error) {
|
||||||
|
index, unit, err := CreateTranslationUnit(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Converter{
|
||||||
|
Files: make([]*FileEntry, 0),
|
||||||
|
index: index,
|
||||||
|
unit: unit,
|
||||||
|
anonyTypeMap: make(map[string]bool),
|
||||||
|
typeDecls: make(map[string]ast.Decl),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateTranslationUnit(config *Config) (*clang.Index, *clang.TranslationUnit, error) {
|
||||||
|
// default use the c/c++ standard of clang; c:gnu17 c++:gnu++17
|
||||||
|
// https://clang.llvm.org/docs/CommandGuide/clang.html
|
||||||
|
defaultArgs := []string{"-x", "c"}
|
||||||
|
if config.IsCpp {
|
||||||
|
defaultArgs = []string{"-x", "c++"}
|
||||||
|
}
|
||||||
|
allArgs := append(defaultArgs, config.Args...)
|
||||||
|
|
||||||
|
cArgs := make([]*c.Char, len(allArgs))
|
||||||
|
for i, arg := range allArgs {
|
||||||
|
cArgs[i] = c.AllocaCStr(arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
index := clang.CreateIndex(0, 0)
|
||||||
|
|
||||||
|
var unit *clang.TranslationUnit
|
||||||
|
|
||||||
|
if config.Temp {
|
||||||
|
content := c.AllocaCStr(config.File)
|
||||||
|
tempFile := &clang.UnsavedFile{
|
||||||
|
Filename: c.Str("temp.h"),
|
||||||
|
Contents: content,
|
||||||
|
Length: c.Ulong(c.Strlen(content)),
|
||||||
|
}
|
||||||
|
|
||||||
|
unit = index.ParseTranslationUnit(
|
||||||
|
tempFile.Filename,
|
||||||
|
unsafe.SliceData(cArgs), c.Int(len(cArgs)),
|
||||||
|
tempFile, 1,
|
||||||
|
clang.DetailedPreprocessingRecord,
|
||||||
|
)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
cFile := c.AllocaCStr(config.File)
|
||||||
|
unit = index.ParseTranslationUnit(
|
||||||
|
cFile,
|
||||||
|
unsafe.SliceData(cArgs), c.Int(len(cArgs)),
|
||||||
|
nil, 0,
|
||||||
|
clang.DetailedPreprocessingRecord,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if unit == nil {
|
||||||
|
return nil, nil, errors.New("failed to parse translation unit")
|
||||||
|
}
|
||||||
|
|
||||||
|
return index, unit, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) Dispose() {
|
||||||
|
ct.index.Dispose()
|
||||||
|
ct.unit.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) GetTokens(cursor clang.Cursor) []*ast.Token {
|
||||||
|
ran := cursor.Extent()
|
||||||
|
var numTokens c.Uint
|
||||||
|
var tokens *clang.Token
|
||||||
|
ct.unit.Tokenize(ran, &tokens, &numTokens)
|
||||||
|
defer ct.unit.DisposeTokens(tokens, numTokens)
|
||||||
|
|
||||||
|
tokensSlice := unsafe.Slice(tokens, int(numTokens))
|
||||||
|
|
||||||
|
result := make([]*ast.Token, 0, int(numTokens))
|
||||||
|
for _, tok := range tokensSlice {
|
||||||
|
tokStr := ct.unit.Token(tok)
|
||||||
|
result = append(result, &ast.Token{
|
||||||
|
Token: toToken(tok),
|
||||||
|
Lit: c.GoString(tokStr.CStr()),
|
||||||
|
})
|
||||||
|
tokStr.Dispose()
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) UpdateLoc(cursor clang.Cursor) {
|
||||||
|
loc := cursor.Location()
|
||||||
|
var file clang.File
|
||||||
|
loc.SpellingLocation(&file, nil, nil, nil)
|
||||||
|
filename := file.FileName()
|
||||||
|
defer filename.Dispose()
|
||||||
|
|
||||||
|
if filename.CStr() == nil {
|
||||||
|
//todo(zzy): For some built-in macros, there is no file.
|
||||||
|
ct.curLoc = ast.Location{File: ""}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath := c.GoString(filename.CStr())
|
||||||
|
ct.curLoc = ast.Location{File: filePath}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) GetCurFile() *ast.File {
|
||||||
|
if ct.curLoc.File == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// todo(zzy): more efficient
|
||||||
|
for i, entry := range ct.Files {
|
||||||
|
if entry.Path == ct.curLoc.File {
|
||||||
|
return ct.Files[i].Doc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newDoc := &ast.File{}
|
||||||
|
ct.Files = append(ct.Files, &FileEntry{Path: ct.curLoc.File, Doc: newDoc})
|
||||||
|
return newDoc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) SetAnonyType(cursor clang.Cursor) {
|
||||||
|
usr := cursor.USR()
|
||||||
|
usrStr := c.GoString(usr.CStr())
|
||||||
|
defer usr.Dispose()
|
||||||
|
ct.anonyTypeMap[usrStr] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) GetAnonyType(cursor clang.Cursor) (bool, bool) {
|
||||||
|
usr := cursor.USR()
|
||||||
|
usrStr := c.GoString(usr.CStr())
|
||||||
|
defer usr.Dispose()
|
||||||
|
isAnony, ok := ct.anonyTypeMap[usrStr]
|
||||||
|
return isAnony, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) SetTypeDecl(cursor clang.Cursor, decl ast.Decl) {
|
||||||
|
usr := cursor.USR()
|
||||||
|
usrStr := c.GoString(usr.CStr())
|
||||||
|
ct.typeDecls[usrStr] = decl
|
||||||
|
usr.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) GetTypeDecl(cursor clang.Cursor) (ast.Decl, bool) {
|
||||||
|
usr := cursor.USR()
|
||||||
|
usrStr := c.GoString(usr.CStr())
|
||||||
|
decl, ok := ct.typeDecls[usrStr]
|
||||||
|
usr.Dispose()
|
||||||
|
return decl, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) CreateDeclBase(cursor clang.Cursor) ast.DeclBase {
|
||||||
|
base := ast.DeclBase{
|
||||||
|
Loc: &ct.curLoc,
|
||||||
|
Parent: ct.BuildScopingExpr(cursor.SemanticParent()),
|
||||||
|
}
|
||||||
|
commentGroup, isDoc := ct.ParseCommentGroup(cursor)
|
||||||
|
if isDoc {
|
||||||
|
base.Doc = commentGroup
|
||||||
|
}
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
|
||||||
|
// extracts and parses comments associated with a given Clang cursor,
|
||||||
|
// distinguishing between documentation comments and line comments.
|
||||||
|
// It uses libclang to parse only Doxygen-style comments.
|
||||||
|
|
||||||
|
// Reference for Doxygen documentation blocks: https://www.doxygen.nl/manual/docblocks.html
|
||||||
|
|
||||||
|
// The function determines whether a comment is a documentation comment or a line comment by
|
||||||
|
// comparing the range of the comment node with the range of the declaration node in the AST.
|
||||||
|
|
||||||
|
// Note: In cases where both documentation comments and line comments conceptually exist,
|
||||||
|
// only the line comment will be preserved.
|
||||||
|
func (ct *Converter) ParseCommentGroup(cursor clang.Cursor) (comentGroup *ast.CommentGroup, isDoc bool) {
|
||||||
|
rawComment := cursor.RawCommentText()
|
||||||
|
defer rawComment.Dispose()
|
||||||
|
commentGroup := &ast.CommentGroup{}
|
||||||
|
if rawComment.CStr() != nil {
|
||||||
|
commentRange := cursor.CommentRange()
|
||||||
|
cursorRange := cursor.Extent()
|
||||||
|
isDoc := getOffset(commentRange.RangeStart()) < getOffset(cursorRange.RangeStart())
|
||||||
|
commentGroup = ct.ParseComment(c.GoString(rawComment.CStr()))
|
||||||
|
if len(commentGroup.List) > 0 {
|
||||||
|
return commentGroup, isDoc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ParseComment(rawComment string) *ast.CommentGroup {
|
||||||
|
lines := strings.Split(rawComment, "\n")
|
||||||
|
commentGroup := &ast.CommentGroup{}
|
||||||
|
for _, line := range lines {
|
||||||
|
commentGroup.List = append(commentGroup.List, &ast.Comment{Text: line})
|
||||||
|
}
|
||||||
|
return commentGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
// visit top decls (struct,class,function,enum & macro,include)
|
||||||
|
func visitTop(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult {
|
||||||
|
ct := (*Converter)(clientData)
|
||||||
|
ct.UpdateLoc(cursor)
|
||||||
|
|
||||||
|
curFile := ct.GetCurFile()
|
||||||
|
if curFile == nil {
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch cursor.Kind {
|
||||||
|
case clang.CursorInclusionDirective:
|
||||||
|
include := ct.ProcessInclude(cursor)
|
||||||
|
curFile.Includes = append(curFile.Includes, include)
|
||||||
|
case clang.CursorMacroDefinition:
|
||||||
|
macro := ct.ProcessMacro(cursor)
|
||||||
|
curFile.Macros = append(curFile.Macros, macro)
|
||||||
|
case clang.CursorEnumDecl:
|
||||||
|
enum := ct.ProcessEnumDecl(cursor)
|
||||||
|
curFile.Decls = append(curFile.Decls, enum)
|
||||||
|
case clang.CursorClassDecl:
|
||||||
|
classDecl := ct.ProcessClassDecl(cursor)
|
||||||
|
curFile.Decls = append(curFile.Decls, classDecl)
|
||||||
|
case clang.CursorStructDecl:
|
||||||
|
structDecl := ct.ProcessStructDecl(cursor)
|
||||||
|
curFile.Decls = append(curFile.Decls, structDecl)
|
||||||
|
case clang.CursorUnionDecl:
|
||||||
|
unionDecl := ct.ProcessUnionDecl(cursor)
|
||||||
|
curFile.Decls = append(curFile.Decls, unionDecl)
|
||||||
|
case clang.CursorFunctionDecl, clang.CursorCXXMethod, clang.CursorConstructor, clang.CursorDestructor:
|
||||||
|
// Handle functions and class methods (including out-of-class method)
|
||||||
|
// Example: void MyClass::myMethod() { ... } out-of-class method
|
||||||
|
curFile.Decls = append(curFile.Decls, ct.ProcessFuncDecl(cursor))
|
||||||
|
case clang.CursorTypedefDecl:
|
||||||
|
curFile.Decls = append(curFile.Decls, ct.ProcessTypeDefDecl(cursor))
|
||||||
|
case clang.CursorNamespace:
|
||||||
|
clang.VisitChildren(cursor, visitTop, c.Pointer(ct))
|
||||||
|
}
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) Convert() ([]*FileEntry, error) {
|
||||||
|
cursor := ct.unit.Cursor()
|
||||||
|
// visit top decls (struct,class,function & macro,include)
|
||||||
|
clang.VisitChildren(cursor, visitTop, c.Pointer(ct))
|
||||||
|
return ct.Files, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessType(t clang.Type) ast.Expr {
|
||||||
|
if t.Kind >= clang.TypeFirstBuiltin && t.Kind <= clang.TypeLastBuiltin {
|
||||||
|
return ct.ProcessBuiltinType(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Kind == clang.TypeElaborated {
|
||||||
|
return ct.ProcessElaboratedType(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
var expr ast.Expr
|
||||||
|
switch t.Kind {
|
||||||
|
case clang.TypePointer:
|
||||||
|
expr = &ast.PointerType{X: ct.ProcessType(t.PointeeType())}
|
||||||
|
case clang.TypeLValueReference:
|
||||||
|
expr = &ast.LvalueRefType{X: ct.ProcessType(t.NonReferenceType())}
|
||||||
|
case clang.TypeRValueReference:
|
||||||
|
expr = &ast.RvalueRefType{X: ct.ProcessType(t.NonReferenceType())}
|
||||||
|
case clang.TypeFunctionProto, clang.TypeFunctionNoProto:
|
||||||
|
// treating TypeFunctionNoProto as a general function without parameters
|
||||||
|
// function type will only collect return type, params will be collected in ProcessFuncDecl
|
||||||
|
expr = ct.ProcessFunctionType(t)
|
||||||
|
case clang.TypeConstantArray, clang.TypeIncompleteArray, clang.TypeVariableArray, clang.TypeDependentSizedArray:
|
||||||
|
if t.Kind == clang.TypeConstantArray {
|
||||||
|
len := (*c.Char)(c.Malloc(unsafe.Sizeof(c.Char(0)) * 20))
|
||||||
|
c.Sprintf(len, c.Str("%lld"), t.ArraySize())
|
||||||
|
defer c.Free(unsafe.Pointer(len))
|
||||||
|
expr = &ast.ArrayType{
|
||||||
|
Elt: ct.ProcessType(t.ArrayElementType()),
|
||||||
|
Len: &ast.BasicLit{Kind: ast.IntLit, Value: c.GoString(len)},
|
||||||
|
}
|
||||||
|
} else if t.Kind == clang.TypeIncompleteArray {
|
||||||
|
// incomplete array havent len expr
|
||||||
|
expr = &ast.ArrayType{
|
||||||
|
Elt: ct.ProcessType(t.ArrayElementType()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
|
||||||
|
// For function types, we can only obtain the parameter types, but not the parameter names.
|
||||||
|
// 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.
|
||||||
|
func (ct *Converter) ProcessFunctionType(t clang.Type) *ast.FuncType {
|
||||||
|
// Note: Attempting to get the type declaration for a function type will result in CursorNoDeclFound
|
||||||
|
// cursor := t.TypeDeclaration()
|
||||||
|
// This would return CursorNoDeclFound
|
||||||
|
|
||||||
|
ret := ct.ProcessType(t.ResultType())
|
||||||
|
params := &ast.FieldList{}
|
||||||
|
numArgs := t.NumArgTypes()
|
||||||
|
for i := 0; i < int(numArgs); i++ {
|
||||||
|
argType := t.ArgType(c.Uint(i))
|
||||||
|
params.List = append(params.List, &ast.Field{
|
||||||
|
Type: ct.ProcessType(argType),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if t.IsFunctionTypeVariadic() != 0 {
|
||||||
|
params.List = append(params.List, &ast.Field{
|
||||||
|
Type: &ast.Variadic{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ast.FuncType{
|
||||||
|
Ret: ret,
|
||||||
|
Params: params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessTypeDefDecl(cursor clang.Cursor) *ast.TypedefDecl {
|
||||||
|
name := cursor.String()
|
||||||
|
defer name.Dispose()
|
||||||
|
|
||||||
|
typ := ct.ProcessUnderlyingType(cursor)
|
||||||
|
|
||||||
|
decl := &ast.TypedefDecl{
|
||||||
|
DeclBase: ct.CreateDeclBase(cursor),
|
||||||
|
Name: &ast.Ident{Name: c.GoString(name.CStr())},
|
||||||
|
Type: typ,
|
||||||
|
}
|
||||||
|
|
||||||
|
ct.SetTypeDecl(cursor, decl)
|
||||||
|
return decl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr {
|
||||||
|
underlyingTyp := cursor.TypedefDeclUnderlyingType()
|
||||||
|
if underlyingTyp.Kind != clang.TypeElaborated {
|
||||||
|
return ct.ProcessType(underlyingTyp)
|
||||||
|
}
|
||||||
|
|
||||||
|
referTypeCursor := underlyingTyp.TypeDeclaration()
|
||||||
|
|
||||||
|
// If the type decl for the reference already exists in anonyTypeMap
|
||||||
|
// then the refer has been processed in ProcessElaboratedType
|
||||||
|
if _, ok := ct.GetAnonyType(referTypeCursor); !ok && isCursorChildOf(referTypeCursor, cursor) {
|
||||||
|
// Handle unexpected named structures generated from anonymous RecordTypes in Typedefs
|
||||||
|
// In this case, libclang incorrectly reports an anonymous struct as a named struct
|
||||||
|
sourceCode := ct.GetTokens(referTypeCursor)
|
||||||
|
if isAnonymousStructure(sourceCode) {
|
||||||
|
ct.SetAnonyType(referTypeCursor)
|
||||||
|
typ, isValidType := ct.GetTypeDecl(referTypeCursor)
|
||||||
|
if isValidType {
|
||||||
|
// There will be no anonymous classes,here will execute enum,union,struct
|
||||||
|
// according to a normal anonymous decl
|
||||||
|
switch declType := typ.(type) {
|
||||||
|
case *ast.EnumTypeDecl:
|
||||||
|
declType.Name = nil
|
||||||
|
case *ast.TypeDecl:
|
||||||
|
if declType.Type.Tag != ast.Class {
|
||||||
|
declType.Name = nil
|
||||||
|
} else {
|
||||||
|
// Unreachable: There should be no anonymous classes in this context
|
||||||
|
fmt.Fprintln(os.Stderr, "unexpect typedef anonymous class %s", declType.Name.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unreachable:When referencing an anonymous node, its collection must have been completed beforehand
|
||||||
|
fmt.Fprintln(os.Stderr, "anonymous node not collected before reference")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ct.ProcessElaboratedType(underlyingTyp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts functions, methods, constructors, destructors (including out-of-class decl) to ast.FuncDecl nodes.
|
||||||
|
func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl {
|
||||||
|
name := cursor.String()
|
||||||
|
mangledName := cursor.Mangling()
|
||||||
|
defer name.Dispose()
|
||||||
|
defer mangledName.Dispose()
|
||||||
|
|
||||||
|
// function type will only collect return type
|
||||||
|
// ProcessType can't get the field names,will collect in follows
|
||||||
|
funcType, ok := ct.ProcessType(cursor.Type()).(*ast.FuncType)
|
||||||
|
if !ok {
|
||||||
|
fmt.Println("failed to process function type")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
params := ct.ProcessFieldList(cursor)
|
||||||
|
funcType.Params = params
|
||||||
|
|
||||||
|
mangledNameStr := c.GoString(mangledName.CStr())
|
||||||
|
if len(mangledNameStr) >= 1 && mangledNameStr[0] == '_' {
|
||||||
|
mangledNameStr = mangledNameStr[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
funcDecl := &ast.FuncDecl{
|
||||||
|
DeclBase: ct.CreateDeclBase(cursor),
|
||||||
|
Name: &ast.Ident{Name: c.GoString(name.CStr())},
|
||||||
|
Type: funcType,
|
||||||
|
MangledName: mangledNameStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
if cursor.IsFunctionInlined() != 0 {
|
||||||
|
funcDecl.IsInline = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if isMethod(cursor) {
|
||||||
|
ct.ProcessMethodAttributes(cursor, funcDecl)
|
||||||
|
} else {
|
||||||
|
if cursor.StorageClass() == clang.SCStatic {
|
||||||
|
funcDecl.IsStatic = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ct.SetTypeDecl(cursor, funcDecl)
|
||||||
|
|
||||||
|
return funcDecl
|
||||||
|
}
|
||||||
|
|
||||||
|
// get Methods Attributes
|
||||||
|
func (ct *Converter) ProcessMethodAttributes(cursor clang.Cursor, fn *ast.FuncDecl) {
|
||||||
|
if parent := cursor.SemanticParent(); parent.Equal(cursor.LexicalParent()) != 1 {
|
||||||
|
fn.DeclBase.Parent = ct.BuildScopingExpr(cursor.SemanticParent())
|
||||||
|
}
|
||||||
|
|
||||||
|
switch cursor.Kind {
|
||||||
|
case clang.CursorDestructor:
|
||||||
|
fn.IsDestructor = true
|
||||||
|
case clang.CursorConstructor:
|
||||||
|
fn.IsConstructor = true
|
||||||
|
if cursor.IsExplicit() != 0 {
|
||||||
|
fn.IsExplicit = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cursor.IsStatic() != 0 {
|
||||||
|
fn.IsStatic = true
|
||||||
|
}
|
||||||
|
if cursor.IsVirtual() != 0 || cursor.IsPureVirtual() != 0 {
|
||||||
|
fn.IsVirtual = true
|
||||||
|
}
|
||||||
|
if cursor.IsConst() != 0 {
|
||||||
|
fn.IsConst = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var numOverridden c.Uint
|
||||||
|
var overridden *clang.Cursor
|
||||||
|
cursor.OverriddenCursors(&overridden, &numOverridden)
|
||||||
|
if numOverridden > 0 {
|
||||||
|
fn.IsOverride = true
|
||||||
|
}
|
||||||
|
overridden.DisposeOverriddenCursors()
|
||||||
|
}
|
||||||
|
|
||||||
|
type visitEnumContext struct {
|
||||||
|
enum *[]*ast.EnumItem
|
||||||
|
converter *Converter
|
||||||
|
}
|
||||||
|
|
||||||
|
func visitEnum(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult {
|
||||||
|
ctx := (*visitEnumContext)(clientData)
|
||||||
|
if cursor.Kind == clang.CursorEnumConstantDecl {
|
||||||
|
name := cursor.String()
|
||||||
|
val := (*c.Char)(c.Malloc(unsafe.Sizeof(c.Char(0)) * 20))
|
||||||
|
c.Sprintf(val, c.Str("%lld"), cursor.EnumConstantDeclValue())
|
||||||
|
defer c.Free(unsafe.Pointer(val))
|
||||||
|
defer name.Dispose()
|
||||||
|
enum := &ast.EnumItem{
|
||||||
|
Name: &ast.Ident{Name: c.GoString(name.CStr())},
|
||||||
|
Value: &ast.BasicLit{
|
||||||
|
Kind: ast.IntLit,
|
||||||
|
Value: c.GoString(val),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
*ctx.enum = append(*ctx.enum, enum)
|
||||||
|
}
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessEnumType(cursor clang.Cursor) *ast.EnumType {
|
||||||
|
items := make([]*ast.EnumItem, 0)
|
||||||
|
ctx := &visitEnumContext{
|
||||||
|
enum: &items,
|
||||||
|
converter: ct,
|
||||||
|
}
|
||||||
|
clang.VisitChildren(cursor, visitEnum, c.Pointer(ctx))
|
||||||
|
return &ast.EnumType{
|
||||||
|
Items: items,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl {
|
||||||
|
name := cursor.String()
|
||||||
|
defer name.Dispose()
|
||||||
|
|
||||||
|
decl := &ast.EnumTypeDecl{
|
||||||
|
DeclBase: ct.CreateDeclBase(cursor),
|
||||||
|
Name: &ast.Ident{Name: c.GoString(name.CStr())},
|
||||||
|
Type: ct.ProcessEnumType(cursor),
|
||||||
|
}
|
||||||
|
ct.SetTypeDecl(cursor, decl)
|
||||||
|
return decl
|
||||||
|
}
|
||||||
|
|
||||||
|
// current only collect macro which defined in file
|
||||||
|
func (ct *Converter) ProcessMacro(cursor clang.Cursor) *ast.Macro {
|
||||||
|
name := cursor.String()
|
||||||
|
defer name.Dispose()
|
||||||
|
|
||||||
|
macro := &ast.Macro{
|
||||||
|
Name: c.GoString(name.CStr()),
|
||||||
|
Tokens: ct.GetTokens(cursor),
|
||||||
|
}
|
||||||
|
return macro
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessInclude(cursor clang.Cursor) *ast.Include {
|
||||||
|
name := cursor.String()
|
||||||
|
defer name.Dispose()
|
||||||
|
return &ast.Include{Path: c.GoString(name.CStr())}
|
||||||
|
}
|
||||||
|
|
||||||
|
type visitFieldContext struct {
|
||||||
|
params *ast.FieldList
|
||||||
|
converter *Converter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *visitFieldContext) createBaseField(cursor clang.Cursor) *ast.Field {
|
||||||
|
field := &ast.Field{
|
||||||
|
Type: p.converter.ProcessType(cursor.Type()),
|
||||||
|
}
|
||||||
|
fieldName := cursor.String()
|
||||||
|
defer fieldName.Dispose()
|
||||||
|
|
||||||
|
commentGroup, isDoc := p.converter.ParseCommentGroup(cursor)
|
||||||
|
if commentGroup != nil {
|
||||||
|
if isDoc {
|
||||||
|
field.Doc = commentGroup
|
||||||
|
} else {
|
||||||
|
field.Comment = commentGroup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if name := fieldName.CStr(); name != nil {
|
||||||
|
field.Names = []*ast.Ident{{Name: c.GoString(name)}}
|
||||||
|
}
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
func visitFieldList(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult {
|
||||||
|
ctx := (*visitFieldContext)(clientData)
|
||||||
|
|
||||||
|
switch cursor.Kind {
|
||||||
|
case clang.CursorParmDecl, clang.CursorFieldDecl:
|
||||||
|
// In C language, parameter lists do not have similar parameter grouping in Go.
|
||||||
|
// func foo(a, b int)
|
||||||
|
|
||||||
|
// For follows struct, it will also parse to two FieldDecl
|
||||||
|
// struct A {
|
||||||
|
// int a, b;
|
||||||
|
// };
|
||||||
|
field := ctx.createBaseField(cursor)
|
||||||
|
if cursor.Kind == clang.CursorFieldDecl {
|
||||||
|
field.Access = ast.AccessSpecifier(cursor.CXXAccessSpecifier())
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.params.List = append(ctx.params.List, field)
|
||||||
|
|
||||||
|
case clang.CursorVarDecl:
|
||||||
|
if cursor.StorageClass() == clang.SCStatic {
|
||||||
|
// static member variable
|
||||||
|
field := ctx.createBaseField(cursor)
|
||||||
|
field.Access = ast.AccessSpecifier(cursor.CXXAccessSpecifier())
|
||||||
|
field.IsStatic = true
|
||||||
|
ctx.params.List = append(ctx.params.List, field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// For Record Type(struct,union ...) & Func 's FieldList
|
||||||
|
func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList {
|
||||||
|
params := &ast.FieldList{}
|
||||||
|
ctx := &visitFieldContext{
|
||||||
|
params: params,
|
||||||
|
converter: ct,
|
||||||
|
}
|
||||||
|
clang.VisitChildren(cursor, visitFieldList, c.Pointer(ctx))
|
||||||
|
if (cursor.Kind == clang.CursorFunctionDecl || isMethod(cursor)) && cursor.IsVariadic() != 0 {
|
||||||
|
params.List = append(params.List, &ast.Field{
|
||||||
|
Type: &ast.Variadic{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
type visitMethodsContext struct {
|
||||||
|
methods *[]*ast.FuncDecl
|
||||||
|
converter *Converter
|
||||||
|
}
|
||||||
|
|
||||||
|
func visitMethods(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult {
|
||||||
|
ctx := (*visitMethodsContext)(clientData)
|
||||||
|
if isMethod(cursor) && cursor.CXXAccessSpecifier() == clang.CXXPublic {
|
||||||
|
method := ctx.converter.ProcessFuncDecl(cursor)
|
||||||
|
if method != nil {
|
||||||
|
*ctx.methods = append(*ctx.methods, method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note:Public Method is considered
|
||||||
|
func (ct *Converter) ProcessMethods(cursor clang.Cursor) []*ast.FuncDecl {
|
||||||
|
methods := make([]*ast.FuncDecl, 0)
|
||||||
|
ctx := &visitMethodsContext{
|
||||||
|
methods: &methods,
|
||||||
|
converter: ct,
|
||||||
|
}
|
||||||
|
clang.VisitChildren(cursor, visitMethods, c.Pointer(ctx))
|
||||||
|
return methods
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) *ast.TypeDecl {
|
||||||
|
anony := cursor.IsAnonymousRecordDecl()
|
||||||
|
var name *ast.Ident
|
||||||
|
if anony == 0 {
|
||||||
|
cursorName := cursor.String()
|
||||||
|
defer cursorName.Dispose()
|
||||||
|
name = &ast.Ident{Name: c.GoString(cursorName.CStr())}
|
||||||
|
}
|
||||||
|
|
||||||
|
decl := &ast.TypeDecl{
|
||||||
|
DeclBase: ct.CreateDeclBase(cursor),
|
||||||
|
Name: name,
|
||||||
|
Type: ct.ProcessRecordType(cursor),
|
||||||
|
}
|
||||||
|
ct.SetTypeDecl(cursor, decl)
|
||||||
|
|
||||||
|
return decl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessStructDecl(cursor clang.Cursor) *ast.TypeDecl {
|
||||||
|
return ct.ProcessRecordDecl(cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessUnionDecl(cursor clang.Cursor) *ast.TypeDecl {
|
||||||
|
return ct.ProcessRecordDecl(cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessClassDecl(cursor clang.Cursor) *ast.TypeDecl {
|
||||||
|
// Pushing class scope before processing its type and popping after
|
||||||
|
base := ct.CreateDeclBase(cursor)
|
||||||
|
typ := ct.ProcessRecordType(cursor)
|
||||||
|
|
||||||
|
decl := &ast.TypeDecl{
|
||||||
|
DeclBase: base,
|
||||||
|
Name: &ast.Ident{Name: c.GoString(cursor.String().CStr())},
|
||||||
|
Type: typ,
|
||||||
|
}
|
||||||
|
ct.SetTypeDecl(cursor, decl)
|
||||||
|
|
||||||
|
return decl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessRecordType(cursor clang.Cursor) *ast.RecordType {
|
||||||
|
return &ast.RecordType{
|
||||||
|
Tag: toTag(cursor.Kind),
|
||||||
|
Fields: ct.ProcessFieldList(cursor),
|
||||||
|
Methods: ct.ProcessMethods(cursor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// process ElaboratedType Reference
|
||||||
|
//
|
||||||
|
// 1. Named elaborated type references:
|
||||||
|
// - Examples: struct MyStruct, union MyUnion, class MyClass, enum MyEnum
|
||||||
|
// - Handling: Constructed as TagExpr or ScopingExpr references
|
||||||
|
//
|
||||||
|
// 2. Anonymous elaborated type references:
|
||||||
|
// - Examples: struct { int x; int y; }, union { int a; float b; }
|
||||||
|
// - Handling: Retrieve their corresponding concrete types
|
||||||
|
func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr {
|
||||||
|
name := t.String()
|
||||||
|
defer name.Dispose()
|
||||||
|
|
||||||
|
decl := t.TypeDeclaration()
|
||||||
|
isAnony, ok := ct.GetAnonyType(decl)
|
||||||
|
|
||||||
|
if decl.IsAnonymous() != 0 || isAnony && ok {
|
||||||
|
// anonymous type refer (except anonymous RecordType&EnumType in TypedefDecl)
|
||||||
|
if decl.Kind == clang.CursorEnumDecl {
|
||||||
|
return ct.ProcessEnumType(decl)
|
||||||
|
}
|
||||||
|
return ct.ProcessRecordType(decl)
|
||||||
|
}
|
||||||
|
|
||||||
|
typeName := c.GoString(name.CStr())
|
||||||
|
|
||||||
|
// for elaborated type, it could have a tag description
|
||||||
|
// like struct A, union B, class C, enum D
|
||||||
|
parts := strings.SplitN(typeName, " ", 2)
|
||||||
|
if len(parts) == 2 {
|
||||||
|
if tagValue, ok := tagMap[parts[0]]; ok {
|
||||||
|
return &ast.TagExpr{
|
||||||
|
Tag: tagValue,
|
||||||
|
Name: ct.BuildScopingExpr(decl),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ct.BuildScopingExpr(decl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessBuiltinType(t clang.Type) *ast.BuiltinType {
|
||||||
|
kind := ast.Void
|
||||||
|
var flags ast.TypeFlag
|
||||||
|
|
||||||
|
switch t.Kind {
|
||||||
|
case clang.TypeVoid:
|
||||||
|
kind = ast.Void
|
||||||
|
case clang.TypeBool:
|
||||||
|
kind = ast.Bool
|
||||||
|
case clang.TypeCharU, clang.TypeUChar, clang.TypeCharS, clang.TypeSChar:
|
||||||
|
kind = ast.Char
|
||||||
|
case clang.TypeChar16:
|
||||||
|
kind = ast.Char16
|
||||||
|
case clang.TypeChar32:
|
||||||
|
kind = ast.Char32
|
||||||
|
case clang.TypeWChar:
|
||||||
|
kind = ast.WChar
|
||||||
|
case clang.TypeShort, clang.TypeUShort:
|
||||||
|
kind = ast.Int
|
||||||
|
flags |= ast.Short
|
||||||
|
case clang.TypeInt, clang.TypeUInt:
|
||||||
|
kind = ast.Int
|
||||||
|
case clang.TypeLong, clang.TypeULong:
|
||||||
|
kind = ast.Int
|
||||||
|
flags |= ast.Long
|
||||||
|
case clang.TypeLongLong, clang.TypeULongLong:
|
||||||
|
kind = ast.Int
|
||||||
|
flags |= ast.LongLong
|
||||||
|
case clang.TypeInt128, clang.TypeUInt128:
|
||||||
|
kind = ast.Int128
|
||||||
|
case clang.TypeFloat:
|
||||||
|
kind = ast.Float
|
||||||
|
case clang.TypeHalf, clang.TypeFloat16:
|
||||||
|
kind = ast.Float16
|
||||||
|
case clang.TypeDouble:
|
||||||
|
kind = ast.Float
|
||||||
|
flags |= ast.Double
|
||||||
|
case clang.TypeLongDouble:
|
||||||
|
kind = ast.Float
|
||||||
|
flags |= ast.Long | ast.Double
|
||||||
|
case clang.TypeFloat128:
|
||||||
|
kind = ast.Float128
|
||||||
|
case clang.TypeComplex:
|
||||||
|
kind = ast.Complex
|
||||||
|
complexKind := t.ElementType().Kind
|
||||||
|
if complexKind == clang.TypeLongDouble {
|
||||||
|
flags |= ast.Long | ast.Double
|
||||||
|
} else if complexKind == clang.TypeDouble {
|
||||||
|
flags |= ast.Double
|
||||||
|
}
|
||||||
|
// float complfex flag is not set
|
||||||
|
default:
|
||||||
|
// like IBM128,NullPtr,Accum
|
||||||
|
kindStr := t.Kind.String()
|
||||||
|
defer kindStr.Dispose()
|
||||||
|
fmt.Fprintln(os.Stderr, "todo: unknown builtin type:", c.GoString(kindStr.CStr()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsExplicitSigned(t) {
|
||||||
|
flags |= ast.Signed
|
||||||
|
} else if IsExplicitUnsigned(t) {
|
||||||
|
flags |= ast.Unsigned
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ast.BuiltinType{
|
||||||
|
Kind: kind,
|
||||||
|
Flags: flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a complete scoping expression by traversing the semantic parents, starting from the given clang.Cursor
|
||||||
|
// For anonymous decl of typedef references, use their anonymous name
|
||||||
|
func (ct *Converter) BuildScopingExpr(cursor clang.Cursor) ast.Expr {
|
||||||
|
parts := ct.BuildScopingParts(cursor)
|
||||||
|
return buildScopingFromParts(parts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) BuildScopingParts(cursor clang.Cursor) []string {
|
||||||
|
var parts []string
|
||||||
|
// Traverse up the semantic parents
|
||||||
|
for cursor.IsNull() != 1 && cursor.Kind != clang.CursorTranslationUnit {
|
||||||
|
name := cursor.String()
|
||||||
|
qualified := c.GoString(name.CStr())
|
||||||
|
parts = append([]string{qualified}, parts...)
|
||||||
|
cursor = cursor.SemanticParent()
|
||||||
|
name.Dispose()
|
||||||
|
}
|
||||||
|
return parts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) MarshalASTFiles() *cjson.JSON {
|
||||||
|
return MarshalASTFiles(ct.Files)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) MarshalOutputASTFiles() *cjson.JSON {
|
||||||
|
return MarshalOutputASTFiles(ct.Files)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsExplicitSigned(t clang.Type) bool {
|
||||||
|
return t.Kind == clang.TypeCharS || t.Kind == clang.TypeSChar
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsExplicitUnsigned(t clang.Type) bool {
|
||||||
|
return t.Kind == clang.TypeCharU || t.Kind == clang.TypeUChar ||
|
||||||
|
t.Kind == clang.TypeUShort || t.Kind == clang.TypeUInt ||
|
||||||
|
t.Kind == clang.TypeULong || t.Kind == clang.TypeULongLong ||
|
||||||
|
t.Kind == clang.TypeUInt128
|
||||||
|
}
|
||||||
|
|
||||||
|
func toTag(kind clang.CursorKind) ast.Tag {
|
||||||
|
switch kind {
|
||||||
|
case clang.CursorStructDecl:
|
||||||
|
return ast.Struct
|
||||||
|
case clang.CursorUnionDecl:
|
||||||
|
return ast.Union
|
||||||
|
case clang.CursorClassDecl:
|
||||||
|
return ast.Class
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Unexpected cursor kind in toTag: %v", kind))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toToken(tok clang.Token) token.Token {
|
||||||
|
if tok.Kind() < clang.Punctuation || tok.Kind() > clang.Comment {
|
||||||
|
return token.ILLEGAL
|
||||||
|
} else {
|
||||||
|
return token.Token(tok.Kind() + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func isMethod(cursor clang.Cursor) bool {
|
||||||
|
return cursor.Kind == clang.CursorCXXMethod || cursor.Kind == clang.CursorConstructor || cursor.Kind == clang.CursorDestructor
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildScopingFromParts(parts []string) ast.Expr {
|
||||||
|
if len(parts) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var expr ast.Expr = &ast.Ident{Name: parts[0]}
|
||||||
|
for _, part := range parts[1:] {
|
||||||
|
expr = &ast.ScopingExpr{
|
||||||
|
Parent: expr,
|
||||||
|
X: &ast.Ident{Name: part},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
|
||||||
|
// isCursorChildOf checks if the child cursor is contained within the parent cursor.
|
||||||
|
// This function is necessary because libclang doesn't correctly report the lexical
|
||||||
|
// or semantic parent for anonymous structs inside typedefs. By comparing source ranges,
|
||||||
|
// we can determine if one cursor is nested inside another.
|
||||||
|
func isCursorChildOf(child, parent clang.Cursor) bool {
|
||||||
|
return isRangeChildOf(child.Extent(), parent.Extent())
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRangeChildOf(childRange, parentRange clang.SourceRange) bool {
|
||||||
|
return getOffset(childRange.RangeStart()) >= getOffset(parentRange.RangeStart()) &&
|
||||||
|
getOffset(childRange.RangeEnd()) <= getOffset(parentRange.RangeEnd())
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOffset(location clang.SourceLocation) c.Uint {
|
||||||
|
var offset c.Uint
|
||||||
|
location.SpellingLocation(nil, nil, nil, &offset)
|
||||||
|
return offset
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if the source code represents an actual anonymous structure
|
||||||
|
func isAnonymousStructure(sourceCode []*ast.Token) bool {
|
||||||
|
_, isValidTag := tagMap[sourceCode[0].Lit]
|
||||||
|
return sourceCode[0].Token == token.KEYWORD &&
|
||||||
|
isValidTag &&
|
||||||
|
sourceCode[1].Token == token.PUNCT &&
|
||||||
|
sourceCode[1].Lit == "{"
|
||||||
|
}
|
||||||
94
chore/_xtool/llcppsigfetch/parse/cvt_test/cvt.go
Normal file
94
chore/_xtool/llcppsigfetch/parse/cvt_test/cvt.go
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
package cvttest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/cjson"
|
||||||
|
"github.com/goplus/llgo/c/clang"
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RunTest(testName string, testCases []string) {
|
||||||
|
for i, content := range testCases {
|
||||||
|
converter, err := parse.NewConverter(&parse.Config{
|
||||||
|
File: content,
|
||||||
|
Temp: true,
|
||||||
|
IsCpp: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = converter.Convert()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := converter.MarshalASTFiles()
|
||||||
|
str := result.Print()
|
||||||
|
c.Printf(c.Str("%s Case %d:\n%s\n\n"), c.AllocaCStr(testName), c.Int(i+1), str)
|
||||||
|
|
||||||
|
cjson.FreeCStr(str)
|
||||||
|
result.Delete()
|
||||||
|
converter.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetTypeOptions struct {
|
||||||
|
TypeCode string // e.g. "char*", "char**"
|
||||||
|
|
||||||
|
// ExpectTypeKind specifies the expected type kind (optional)
|
||||||
|
// Use clang.Type_Invalid to accept any type (default behavior)
|
||||||
|
// *For complex types (when <complex.h> is included), specifying this is crucial
|
||||||
|
// to filter out the correct type, as there will be multiple VarDecl fields present
|
||||||
|
ExpectTypeKind clang.TypeKind
|
||||||
|
|
||||||
|
// Args contains additional compilation arguments passed to Clang (optional)
|
||||||
|
// These are appended after the default language-specific arguments
|
||||||
|
// Example: []string{"-std=c++11"}
|
||||||
|
Args []string
|
||||||
|
|
||||||
|
// IsCpp indicates whether the code should be treated as C++ (true) or C (false)
|
||||||
|
// This affects the default language arguments passed to Clang:
|
||||||
|
// - For C++: []string{"-x", "c++"}
|
||||||
|
// - For C: []string{"-x", "c"}
|
||||||
|
// *For complex C types, C Must be specified
|
||||||
|
IsCpp bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetType returns the clang.Type of the given type code
|
||||||
|
// Need to dispose the index and unit after using
|
||||||
|
// e.g. index.Dispose(), unit.Dispose()
|
||||||
|
func GetType(option *GetTypeOptions) (clang.Type, *clang.Index, *clang.TranslationUnit) {
|
||||||
|
code := fmt.Sprintf("%s placeholder;", option.TypeCode)
|
||||||
|
index, unit, err := parse.CreateTranslationUnit(&parse.Config{
|
||||||
|
File: code,
|
||||||
|
Temp: true,
|
||||||
|
Args: option.Args,
|
||||||
|
IsCpp: option.IsCpp,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
cursor := unit.Cursor()
|
||||||
|
visitType := &typeVisitData{typ: &clang.Type{}, expectTypeKind: option.ExpectTypeKind}
|
||||||
|
|
||||||
|
clang.VisitChildren(cursor, typeVisit, unsafe.Pointer(visitType))
|
||||||
|
return *visitType.typ, index, unit
|
||||||
|
}
|
||||||
|
|
||||||
|
type typeVisitData struct {
|
||||||
|
typ *clang.Type
|
||||||
|
expectTypeKind clang.TypeKind
|
||||||
|
}
|
||||||
|
|
||||||
|
func typeVisit(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult {
|
||||||
|
visitData := (*typeVisitData)(clientData)
|
||||||
|
if cursor.Kind == clang.CursorVarDecl && (visitData.expectTypeKind == clang.TypeInvalid || cursor.Type().Kind == visitData.expectTypeKind) {
|
||||||
|
*visitData.typ = cursor.Type()
|
||||||
|
return clang.ChildVisit_Break
|
||||||
|
}
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestClassDecl()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClassDecl() {
|
||||||
|
testCases := []string{
|
||||||
|
`class A {
|
||||||
|
public:
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
};`,
|
||||||
|
`class A {
|
||||||
|
public:
|
||||||
|
static int a;
|
||||||
|
int b;
|
||||||
|
float foo(int a,double b);
|
||||||
|
private:
|
||||||
|
static void bar();
|
||||||
|
protected:
|
||||||
|
void bar2();
|
||||||
|
};`,
|
||||||
|
`class A {
|
||||||
|
public:
|
||||||
|
A();
|
||||||
|
explicit A();
|
||||||
|
~A();
|
||||||
|
static inline void foo();
|
||||||
|
};`,
|
||||||
|
`class Base {
|
||||||
|
public:
|
||||||
|
Base();
|
||||||
|
virtual ~Base();
|
||||||
|
virtual void foo();
|
||||||
|
};
|
||||||
|
class Derived : public Base {
|
||||||
|
public:
|
||||||
|
Derived();
|
||||||
|
~Derived() override;
|
||||||
|
void foo() override;
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
`namespace A{
|
||||||
|
class Foo{}
|
||||||
|
}
|
||||||
|
void A::Foo::bar();
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
test.RunTest("TestClassDecl", testCases)
|
||||||
|
}
|
||||||
@@ -0,0 +1,713 @@
|
|||||||
|
#stdout
|
||||||
|
TestClassDecl Case 1:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestClassDecl Case 2:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": true,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1A3fooEid",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 8,
|
||||||
|
"Flags": 16
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 8,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestClassDecl Case 3:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Methods": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1AC1Ev",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": true,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}, {
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1AC1Ev",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": true,
|
||||||
|
"IsConstructor": true,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}, {
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "~A"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1AD1Ev",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": true,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}, {
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1A3fooEv",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": true,
|
||||||
|
"IsStatic": true,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestClassDecl Case 4:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Base"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Methods": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Base"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Base"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN4BaseC1Ev",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": true,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}, {
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Base"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "~Base"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN4BaseD1Ev",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": true,
|
||||||
|
"IsVirtual": true,
|
||||||
|
"IsOverride": false
|
||||||
|
}, {
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Base"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN4Base3fooEv",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": true,
|
||||||
|
"IsOverride": false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Derived"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Methods": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Derived"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Derived"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN7DerivedC1Ev",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": true,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}, {
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Derived"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "~Derived"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN7DerivedD1Ev",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": true,
|
||||||
|
"IsVirtual": true,
|
||||||
|
"IsOverride": true
|
||||||
|
}, {
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Derived"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN7Derived3fooEv",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": true,
|
||||||
|
"IsOverride": true
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestClassDecl Case 5:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "ScopingExpr",
|
||||||
|
"X": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "bar"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1A3Foo3barEv",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#stderr
|
||||||
|
|
||||||
|
#exit 0
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestDoc()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDoc() {
|
||||||
|
testCases := []string{
|
||||||
|
`
|
||||||
|
// not read doc 1
|
||||||
|
void foo();`,
|
||||||
|
`
|
||||||
|
/* not read doc 2 */
|
||||||
|
void foo();`,
|
||||||
|
`
|
||||||
|
/// doc
|
||||||
|
void foo();`,
|
||||||
|
`
|
||||||
|
/** doc */
|
||||||
|
void foo();`,
|
||||||
|
`
|
||||||
|
/*! doc */
|
||||||
|
void foo();`,
|
||||||
|
`
|
||||||
|
/// doc 1
|
||||||
|
/// doc 2
|
||||||
|
void foo();`,
|
||||||
|
`
|
||||||
|
/*! doc 1 */
|
||||||
|
/*! doc 2 */
|
||||||
|
void foo();`,
|
||||||
|
`
|
||||||
|
/** doc 1 */
|
||||||
|
/** doc 1 */
|
||||||
|
void foo();`,
|
||||||
|
`
|
||||||
|
/**
|
||||||
|
* doc 1
|
||||||
|
* doc 2
|
||||||
|
*/
|
||||||
|
void foo();`,
|
||||||
|
`
|
||||||
|
struct Foo {
|
||||||
|
/// doc
|
||||||
|
int x;
|
||||||
|
int y; ///< comment
|
||||||
|
/**
|
||||||
|
* field doc (parse ignore with comment in same cursor)
|
||||||
|
*/
|
||||||
|
int z; /*!< comment */
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
`
|
||||||
|
class Doc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* static field doc
|
||||||
|
*/
|
||||||
|
static int x;
|
||||||
|
static int y; /*!< static field comment */
|
||||||
|
/**
|
||||||
|
* field doc
|
||||||
|
*/
|
||||||
|
int a;
|
||||||
|
int b; ///< field comment
|
||||||
|
/**
|
||||||
|
* method doc
|
||||||
|
*/
|
||||||
|
void Foo();
|
||||||
|
protected:
|
||||||
|
int value; /*!< protected field comment */
|
||||||
|
};`,
|
||||||
|
}
|
||||||
|
test.RunTest("TestDoc", testCases)
|
||||||
|
}
|
||||||
@@ -0,0 +1,742 @@
|
|||||||
|
#stdout
|
||||||
|
TestDoc Case 1:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 2:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 3:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/// doc"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 4:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/** doc */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 5:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/*! doc */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 6:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/// doc 1"
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/// doc 2"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 7:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/*! doc 1 */"
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/*! doc 2 */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 8:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/** doc 1 */"
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/** doc 1 */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 9:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/**"
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": " * doc 1"
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": " * doc 2"
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": " */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 10:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 0,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/// doc"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "x"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "///< comment"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "y"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/*!< comment */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "z"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDoc Case 11:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Doc"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/** "
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": " * static field doc"
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": " */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": true,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "x"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/*!< static field comment */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"IsStatic": true,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "y"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/** "
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": " * field doc"
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": " */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "///< field comment"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/*!< protected field comment */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 2,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "value"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": {
|
||||||
|
"_Type": "CommentGroup",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": "/** "
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": " * method doc"
|
||||||
|
}, {
|
||||||
|
"_Type": "Comment",
|
||||||
|
"Text": " */"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Doc"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN3Doc3FooEv",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#stderr
|
||||||
|
|
||||||
|
#exit 0
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestEnumDecl()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnumDecl() {
|
||||||
|
testCases := []string{
|
||||||
|
`enum Foo {
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
};`,
|
||||||
|
`enum Foo {
|
||||||
|
a = 1,
|
||||||
|
b = 2,
|
||||||
|
c = 4,
|
||||||
|
};`,
|
||||||
|
`enum Foo {
|
||||||
|
a = 1,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
};`,
|
||||||
|
}
|
||||||
|
test.RunTest("TestEnumDecl", testCases)
|
||||||
|
}
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
#stdout
|
||||||
|
TestEnumDecl Case 1:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "EnumTypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "EnumType",
|
||||||
|
"Items": [{
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "0"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "1"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "c"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "2"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestEnumDecl Case 2:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "EnumTypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "EnumType",
|
||||||
|
"Items": [{
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "1"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "2"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "c"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "4"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestEnumDecl Case 3:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "EnumTypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "EnumType",
|
||||||
|
"Items": [{
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "1"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "2"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "c"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "3"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#stderr
|
||||||
|
|
||||||
|
#exit 0
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestFuncDecl()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFuncDecl() {
|
||||||
|
testCases := []string{
|
||||||
|
`void foo();`,
|
||||||
|
`void foo(int a);`,
|
||||||
|
`void foo(int a,...);`,
|
||||||
|
`float* foo(int a,double b);`,
|
||||||
|
`static inline int add(int a, int b);`,
|
||||||
|
}
|
||||||
|
test.RunTest("TestFuncDecl", testCases)
|
||||||
|
}
|
||||||
@@ -0,0 +1,323 @@
|
|||||||
|
#stdout
|
||||||
|
TestFuncDecl Case 1:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncDecl Case 2:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3fooi",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncDecl Case 3:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3fooiz",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "Variadic"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": null
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncDecl Case 4:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3fooid",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 8,
|
||||||
|
"Flags": 16
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "PointerType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 8,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncDecl Case 5:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "add"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZL3addii",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": true,
|
||||||
|
"IsStatic": true,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#stderr
|
||||||
|
|
||||||
|
#exit 0
|
||||||
@@ -0,0 +1,291 @@
|
|||||||
|
#stdout
|
||||||
|
TestScope Case 1:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_Z3foov",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestScope Case 2:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1a3fooEv",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestScope Case 3:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "ScopingExpr",
|
||||||
|
"X": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
},
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1a1b3fooEv",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestScope Case 4:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Methods": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1a3fooEv",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestScope Case 5:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Methods": [{
|
||||||
|
"_Type": "FuncDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "ScopingExpr",
|
||||||
|
"X": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
},
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "foo"
|
||||||
|
},
|
||||||
|
"MangledName": "_ZN1a1b3fooEv",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": null
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 0,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IsInline": false,
|
||||||
|
"IsStatic": false,
|
||||||
|
"IsConst": false,
|
||||||
|
"IsExplicit": false,
|
||||||
|
"IsConstructor": false,
|
||||||
|
"IsDestructor": false,
|
||||||
|
"IsVirtual": false,
|
||||||
|
"IsOverride": false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#stderr
|
||||||
|
|
||||||
|
#exit 0
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestScope()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestScope() {
|
||||||
|
testCases := []string{
|
||||||
|
`void foo();`,
|
||||||
|
`namespace a {
|
||||||
|
void foo();
|
||||||
|
}`,
|
||||||
|
`namespace a {
|
||||||
|
namespace b {
|
||||||
|
void foo();
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
`class a {
|
||||||
|
public:
|
||||||
|
void foo();
|
||||||
|
};`,
|
||||||
|
`namespace a {
|
||||||
|
class b {
|
||||||
|
public:
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
test.RunTest("TestScope", testCases)
|
||||||
|
}
|
||||||
@@ -0,0 +1,375 @@
|
|||||||
|
#stdout
|
||||||
|
TestStructDecl Case 1:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": null,
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 0,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestStructDecl Case 2:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 0,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestStructDecl Case 3:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 0,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestStructDecl Case 4:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 0,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "PointerType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": null
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": null
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestStructDecl Case 5:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Person"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 0,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "age"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 0,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "year"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "day"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "month"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "birthday"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#stderr
|
||||||
|
|
||||||
|
#exit 0
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestStructDecl()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStructDecl() {
|
||||||
|
testCases := []string{
|
||||||
|
`struct {
|
||||||
|
int a;
|
||||||
|
};`,
|
||||||
|
`struct A {
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
};`,
|
||||||
|
`struct A {
|
||||||
|
int a, b;
|
||||||
|
};`,
|
||||||
|
`struct A {
|
||||||
|
int a;
|
||||||
|
int (*Foo)(int, int);
|
||||||
|
};`,
|
||||||
|
`struct Person {
|
||||||
|
int age;
|
||||||
|
struct {
|
||||||
|
int year;
|
||||||
|
int day;
|
||||||
|
int month;
|
||||||
|
} birthday;
|
||||||
|
};`,
|
||||||
|
}
|
||||||
|
test.RunTest("TestStructDecl", testCases)
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestTypeDefDecl()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTypeDefDecl() {
|
||||||
|
testCases := []string{
|
||||||
|
`typedef int INT;`,
|
||||||
|
|
||||||
|
`typedef int INT;
|
||||||
|
typedef INT STANDARD_INT;`,
|
||||||
|
|
||||||
|
`typedef int INT,*IntPtr,IntArr[];`,
|
||||||
|
|
||||||
|
`typedef int (*Foo)(int, int, ...);`,
|
||||||
|
|
||||||
|
`typedef int (*Foo)(int, int),(*Bar)(void*,void*);`,
|
||||||
|
|
||||||
|
`namespace A {
|
||||||
|
typedef class Foo{
|
||||||
|
int x;
|
||||||
|
} MyClass,*MyClassPtr,MyClassArray[];
|
||||||
|
}`,
|
||||||
|
|
||||||
|
`typedef struct {
|
||||||
|
int x;
|
||||||
|
} MyStruct`,
|
||||||
|
`typedef union {
|
||||||
|
int x;
|
||||||
|
} MyUnion`,
|
||||||
|
`typedef enum {
|
||||||
|
RED,
|
||||||
|
GREEN,
|
||||||
|
BLUE
|
||||||
|
} MyEnum`,
|
||||||
|
|
||||||
|
`typedef struct {
|
||||||
|
int x;
|
||||||
|
} MyStruct,MyStruct2,*StructPtr, StructArr[];`,
|
||||||
|
|
||||||
|
`namespace A{
|
||||||
|
namespace B{
|
||||||
|
typedef struct {
|
||||||
|
int x;
|
||||||
|
} MyStruct,MyStruct2,*StructPtr, StructArr[];
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
test.RunTest("TestTypeDefDecl", testCases)
|
||||||
|
}
|
||||||
@@ -0,0 +1,234 @@
|
|||||||
|
#stdout
|
||||||
|
TestUnionDecl Case 1:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": null,
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 1,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestUnionDecl Case 2:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "A"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 1,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestUnionDecl Case 3:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "OuterUnion"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 1,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "i"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 8,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "f"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 1,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 2,
|
||||||
|
"Flags": 1
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "c"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 32
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "s"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "inner"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#stderr
|
||||||
|
|
||||||
|
#exit 0
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestUnionDecl()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnionDecl() {
|
||||||
|
testCases := []string{
|
||||||
|
`union {
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
};`,
|
||||||
|
`union A {
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
};`,
|
||||||
|
`union OuterUnion {
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
union {
|
||||||
|
char c;
|
||||||
|
short s;
|
||||||
|
} inner;
|
||||||
|
};`,
|
||||||
|
}
|
||||||
|
test.RunTest("TestUnionDecl", testCases)
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
#stdout
|
||||||
|
TestDefine Case 1:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [],
|
||||||
|
"includes": [],
|
||||||
|
"macros": [{
|
||||||
|
"_Type": "Macro",
|
||||||
|
"Name": "DEBUG",
|
||||||
|
"Tokens": [{
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 3,
|
||||||
|
"Lit": "DEBUG"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDefine Case 2:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [],
|
||||||
|
"includes": [],
|
||||||
|
"macros": [{
|
||||||
|
"_Type": "Macro",
|
||||||
|
"Name": "OK",
|
||||||
|
"Tokens": [{
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 3,
|
||||||
|
"Lit": "OK"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 4,
|
||||||
|
"Lit": "1"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestDefine Case 3:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [],
|
||||||
|
"includes": [],
|
||||||
|
"macros": [{
|
||||||
|
"_Type": "Macro",
|
||||||
|
"Name": "SQUARE",
|
||||||
|
"Tokens": [{
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 3,
|
||||||
|
"Lit": "SQUARE"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": "("
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 3,
|
||||||
|
"Lit": "x"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": ")"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": "("
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": "("
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 3,
|
||||||
|
"Lit": "x"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": ")"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": "*"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": "("
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 3,
|
||||||
|
"Lit": "x"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": ")"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": ")"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestInclude Case 1:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [],
|
||||||
|
"includes": [{
|
||||||
|
"_Type": "Include",
|
||||||
|
"Path": "foo.h"
|
||||||
|
}],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#stderr
|
||||||
|
|
||||||
|
#exit 0
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestDefine()
|
||||||
|
TestInclude()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefine() {
|
||||||
|
testCases := []string{
|
||||||
|
`#define DEBUG`,
|
||||||
|
`#define OK 1`,
|
||||||
|
`#define SQUARE(x) ((x) * (x))`,
|
||||||
|
}
|
||||||
|
test.RunTest("TestDefine", testCases)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInclude() {
|
||||||
|
testCases := []string{
|
||||||
|
`#include "foo.h"`,
|
||||||
|
// `#include <limits.h>`, // Standard libraries are mostly platform-dependent
|
||||||
|
}
|
||||||
|
test.RunTest("TestInclude", testCases)
|
||||||
|
}
|
||||||
350
chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/llgo.expect
Normal file
350
chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/llgo.expect
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
#stdout
|
||||||
|
Void:flags:0 kind:0
|
||||||
|
Bool:flags:0 kind:1
|
||||||
|
Char_S:flags:1 kind:2
|
||||||
|
Char_U:flags:2 kind:2
|
||||||
|
Char16:flags:0 kind:3
|
||||||
|
Char32:flags:0 kind:4
|
||||||
|
WChar:flags:0 kind:5
|
||||||
|
Short:flags:32 kind:6
|
||||||
|
UShort:flags:34 kind:6
|
||||||
|
Int:flags:0 kind:6
|
||||||
|
UInt:flags:2 kind:6
|
||||||
|
Long:flags:4 kind:6
|
||||||
|
ULong:flags:6 kind:6
|
||||||
|
LongLong:flags:8 kind:6
|
||||||
|
ULongLong:flags:10 kind:6
|
||||||
|
Int128:flags:0 kind:7
|
||||||
|
UInt128:flags:2 kind:7
|
||||||
|
Float:flags:0 kind:8
|
||||||
|
Half:flags:0 kind:9
|
||||||
|
Float16:flags:0 kind:9
|
||||||
|
Double:flags:16 kind:8
|
||||||
|
LongDouble:flags:20 kind:8
|
||||||
|
Float128:flags:0 kind:10
|
||||||
|
Complex:flags:0 kind:11
|
||||||
|
Complex:flags:16 kind:11
|
||||||
|
Complex:flags:20 kind:11
|
||||||
|
Unknown:flags:0 kind:0
|
||||||
|
Type: char *:
|
||||||
|
{
|
||||||
|
"_Type": "PointerType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 2,
|
||||||
|
"Flags": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type: char ***:
|
||||||
|
{
|
||||||
|
"_Type": "PointerType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "PointerType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "PointerType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 2,
|
||||||
|
"Flags": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type: char[]:
|
||||||
|
{
|
||||||
|
"_Type": "ArrayType",
|
||||||
|
"Elt": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 2,
|
||||||
|
"Flags": 1
|
||||||
|
},
|
||||||
|
"Len": null
|
||||||
|
}
|
||||||
|
Type: char[10]:
|
||||||
|
{
|
||||||
|
"_Type": "ArrayType",
|
||||||
|
"Elt": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 2,
|
||||||
|
"Flags": 1
|
||||||
|
},
|
||||||
|
"Len": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type: char[3][4]:
|
||||||
|
{
|
||||||
|
"_Type": "ArrayType",
|
||||||
|
"Elt": {
|
||||||
|
"_Type": "ArrayType",
|
||||||
|
"Elt": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 2,
|
||||||
|
"Flags": 1
|
||||||
|
},
|
||||||
|
"Len": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Len": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type: int &:
|
||||||
|
{
|
||||||
|
"_Type": "LvalueRefType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type: int &&:
|
||||||
|
{
|
||||||
|
"_Type": "RvalueRefType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type: Foo:
|
||||||
|
{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
}
|
||||||
|
Type: struct Foo:
|
||||||
|
{
|
||||||
|
"_Type": "TagExpr",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Tag": 0
|
||||||
|
}
|
||||||
|
Type: struct (unnamed struct at temp.h:1:1):
|
||||||
|
{
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 0,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "x"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
Type: Foo:
|
||||||
|
{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
}
|
||||||
|
Type: union Foo:
|
||||||
|
{
|
||||||
|
"_Type": "TagExpr",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Tag": 1
|
||||||
|
}
|
||||||
|
Type: union (unnamed union at temp.h:1:1):
|
||||||
|
{
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 1,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "x"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
Type: Foo:
|
||||||
|
{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
}
|
||||||
|
Type: enum Foo:
|
||||||
|
{
|
||||||
|
"_Type": "TagExpr",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Tag": 2
|
||||||
|
}
|
||||||
|
Type: enum (unnamed enum at temp.h:1:1):
|
||||||
|
{
|
||||||
|
"_Type": "EnumType",
|
||||||
|
"Items": [{
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "x"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "42"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
Type: Foo:
|
||||||
|
{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
}
|
||||||
|
Type: class Foo:
|
||||||
|
{
|
||||||
|
"_Type": "TagExpr",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "Foo"
|
||||||
|
},
|
||||||
|
"Tag": 3
|
||||||
|
}
|
||||||
|
Type: class (unnamed class at temp.h:1:1):
|
||||||
|
{
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 3,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 3,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "x"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
Type: a::b::c:
|
||||||
|
{
|
||||||
|
"_Type": "ScopingExpr",
|
||||||
|
"X": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "c"
|
||||||
|
},
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "ScopingExpr",
|
||||||
|
"X": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
},
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type: class a::b::c:
|
||||||
|
{
|
||||||
|
"_Type": "TagExpr",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "ScopingExpr",
|
||||||
|
"X": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "c"
|
||||||
|
},
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "ScopingExpr",
|
||||||
|
"X": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "b"
|
||||||
|
},
|
||||||
|
"Parent": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Tag": 3
|
||||||
|
}
|
||||||
|
Type: int (*)(int, char):
|
||||||
|
{
|
||||||
|
"_Type": "PointerType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "FuncType",
|
||||||
|
"Params": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": null
|
||||||
|
}, {
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 2,
|
||||||
|
"Flags": 1
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 0,
|
||||||
|
"Names": null
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Ret": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#stderr
|
||||||
|
todo: unknown builtin type: Ibm128
|
||||||
|
|
||||||
|
#exit 0
|
||||||
175
chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/type.go
Normal file
175
chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/type.go
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/cjson"
|
||||||
|
"github.com/goplus/llgo/c/clang"
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse"
|
||||||
|
test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
"github.com/goplus/llgo/chore/llcppg/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TestBuiltinType()
|
||||||
|
TestNonBuiltinTypes()
|
||||||
|
}
|
||||||
|
func TestBuiltinType() {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
typ clang.Type
|
||||||
|
expected ast.BuiltinType
|
||||||
|
}{
|
||||||
|
{"Void", btType(clang.TypeVoid), ast.BuiltinType{Kind: ast.Void}},
|
||||||
|
{"Bool", btType(clang.TypeBool), ast.BuiltinType{Kind: ast.Bool}},
|
||||||
|
{"Char_S", btType(clang.TypeCharS), ast.BuiltinType{Kind: ast.Char, Flags: ast.Signed}},
|
||||||
|
{"Char_U", btType(clang.TypeCharU), ast.BuiltinType{Kind: ast.Char, Flags: ast.Unsigned}},
|
||||||
|
{"Char16", btType(clang.TypeChar16), ast.BuiltinType{Kind: ast.Char16}},
|
||||||
|
{"Char32", btType(clang.TypeChar32), ast.BuiltinType{Kind: ast.Char32}},
|
||||||
|
{"WChar", btType(clang.TypeWChar), ast.BuiltinType{Kind: ast.WChar}},
|
||||||
|
{"Short", btType(clang.TypeShort), ast.BuiltinType{Kind: ast.Int, Flags: ast.Short}},
|
||||||
|
{"UShort", btType(clang.TypeUShort), ast.BuiltinType{Kind: ast.Int, Flags: ast.Short | ast.Unsigned}},
|
||||||
|
{"Int", btType(clang.TypeInt), ast.BuiltinType{Kind: ast.Int}},
|
||||||
|
{"UInt", btType(clang.TypeUInt), ast.BuiltinType{Kind: ast.Int, Flags: ast.Unsigned}},
|
||||||
|
{"Long", btType(clang.TypeLong), ast.BuiltinType{Kind: ast.Int, Flags: ast.Long}},
|
||||||
|
{"ULong", btType(clang.TypeULong), ast.BuiltinType{Kind: ast.Int, Flags: ast.Long | ast.Unsigned}},
|
||||||
|
{"LongLong", btType(clang.TypeLongLong), ast.BuiltinType{Kind: ast.Int, Flags: ast.LongLong}},
|
||||||
|
{"ULongLong", btType(clang.TypeULongLong), ast.BuiltinType{Kind: ast.Int, Flags: ast.LongLong | ast.Unsigned}},
|
||||||
|
{"Int128", btType(clang.TypeInt128), ast.BuiltinType{Kind: ast.Int128}},
|
||||||
|
{"UInt128", btType(clang.TypeUInt128), ast.BuiltinType{Kind: ast.Int128, Flags: ast.Unsigned}},
|
||||||
|
{"Float", btType(clang.TypeFloat), ast.BuiltinType{Kind: ast.Float}},
|
||||||
|
{"Half", btType(clang.TypeHalf), ast.BuiltinType{Kind: ast.Float16}},
|
||||||
|
{"Float16", btType(clang.TypeFloat16), ast.BuiltinType{Kind: ast.Float16}},
|
||||||
|
{"Double", btType(clang.TypeDouble), ast.BuiltinType{Kind: ast.Float, Flags: ast.Double}},
|
||||||
|
{"LongDouble", btType(clang.TypeLongDouble), ast.BuiltinType{Kind: ast.Float, Flags: ast.Long | ast.Double}},
|
||||||
|
{"Float128", btType(clang.TypeFloat128), ast.BuiltinType{Kind: ast.Float128}},
|
||||||
|
{"Complex", getComplexType(0), ast.BuiltinType{Kind: ast.Complex}},
|
||||||
|
{"Complex", getComplexType(ast.Double), ast.BuiltinType{Flags: ast.Double, Kind: ast.Complex}},
|
||||||
|
{"Complex", getComplexType(ast.Long | ast.Double), ast.BuiltinType{Flags: ast.Long | ast.Double, Kind: ast.Complex}},
|
||||||
|
{"Unknown", btType(clang.TypeIbm128), ast.BuiltinType{Kind: ast.Void}},
|
||||||
|
}
|
||||||
|
|
||||||
|
converter := &parse.Converter{}
|
||||||
|
converter.Convert()
|
||||||
|
for _, bt := range tests {
|
||||||
|
res := converter.ProcessBuiltinType(bt.typ)
|
||||||
|
if res.Kind != bt.expected.Kind {
|
||||||
|
fmt.Printf("%s Kind mismatch:got %d want %d, \n", bt.name, res.Kind, bt.expected.Kind)
|
||||||
|
}
|
||||||
|
if res.Flags != bt.expected.Flags {
|
||||||
|
fmt.Printf("%s Flags mismatch:got %d,want %d\n", bt.name, res.Flags, bt.expected.Flags)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s:flags:%d kind:%d\n", bt.name, res.Flags, res.Kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNonBuiltinTypes() {
|
||||||
|
tests := []string{
|
||||||
|
"char*",
|
||||||
|
"char***",
|
||||||
|
|
||||||
|
"char[]",
|
||||||
|
"char[10]",
|
||||||
|
"char[3][4]",
|
||||||
|
|
||||||
|
"int&",
|
||||||
|
"int&&",
|
||||||
|
|
||||||
|
`struct Foo {};
|
||||||
|
Foo`,
|
||||||
|
`struct Foo {};
|
||||||
|
struct Foo`,
|
||||||
|
`struct {
|
||||||
|
int x;
|
||||||
|
}`,
|
||||||
|
|
||||||
|
`union Foo {};
|
||||||
|
Foo`,
|
||||||
|
`union Foo {};
|
||||||
|
union Foo`,
|
||||||
|
`union {
|
||||||
|
int x;
|
||||||
|
}`,
|
||||||
|
|
||||||
|
`enum Foo {};
|
||||||
|
Foo`,
|
||||||
|
`enum Foo {};
|
||||||
|
enum Foo`,
|
||||||
|
`enum { x = 42 }`,
|
||||||
|
|
||||||
|
`class Foo {};
|
||||||
|
Foo`,
|
||||||
|
`class Foo {};
|
||||||
|
class Foo`,
|
||||||
|
`class {
|
||||||
|
int x;
|
||||||
|
}`,
|
||||||
|
|
||||||
|
`namespace a {
|
||||||
|
namespace b {
|
||||||
|
class c {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a::b::c`,
|
||||||
|
|
||||||
|
`namespace a {
|
||||||
|
namespace b {
|
||||||
|
class c {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class a::b::c`,
|
||||||
|
|
||||||
|
`int (*p)(int, char);`,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range tests {
|
||||||
|
typ, index, unit := test.GetType(&test.GetTypeOptions{
|
||||||
|
TypeCode: t,
|
||||||
|
IsCpp: true,
|
||||||
|
})
|
||||||
|
converter := &parse.Converter{}
|
||||||
|
expr := converter.ProcessType(typ)
|
||||||
|
json := parse.MarshalASTExpr(expr)
|
||||||
|
str := json.Print()
|
||||||
|
typstr := typ.String()
|
||||||
|
|
||||||
|
c.Printf(c.Str("Type: %s:\n"), typstr)
|
||||||
|
c.Printf(c.Str("%s\n"), str)
|
||||||
|
|
||||||
|
typstr.Dispose()
|
||||||
|
cjson.FreeCStr(str)
|
||||||
|
json.Delete()
|
||||||
|
index.Dispose()
|
||||||
|
unit.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func btType(kind clang.TypeKind) clang.Type {
|
||||||
|
return clang.Type{Kind: kind}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get complex type from source code parsed
|
||||||
|
func getComplexType(flag ast.TypeFlag) clang.Type {
|
||||||
|
var typeStr string
|
||||||
|
if flag&(ast.Long|ast.Double) == (ast.Long | ast.Double) {
|
||||||
|
typeStr = "long double"
|
||||||
|
} else if flag&ast.Double != 0 {
|
||||||
|
typeStr = "double"
|
||||||
|
} else {
|
||||||
|
typeStr = "float"
|
||||||
|
}
|
||||||
|
|
||||||
|
code := fmt.Sprintf("#include <complex.h>\n%s complex", typeStr)
|
||||||
|
|
||||||
|
// todo(zzy):free index and unit after test
|
||||||
|
typ, _, _ := test.GetType(&test.GetTypeOptions{
|
||||||
|
TypeCode: code,
|
||||||
|
ExpectTypeKind: clang.TypeComplex,
|
||||||
|
IsCpp: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
return typ
|
||||||
|
}
|
||||||
273
chore/_xtool/llcppsigfetch/parse/dump.go
Normal file
273
chore/_xtool/llcppsigfetch/parse/dump.go
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
package parse
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/cjson"
|
||||||
|
"github.com/goplus/llgo/chore/llcppg/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MarshalOutputASTFiles(files []*FileEntry) *cjson.JSON {
|
||||||
|
root := cjson.Array()
|
||||||
|
for _, entry := range files {
|
||||||
|
f := cjson.Object()
|
||||||
|
path := cjson.String(c.AllocaCStr(entry.Path))
|
||||||
|
f.SetItem(c.Str("path"), path)
|
||||||
|
f.SetItem(c.Str("doc"), MarshalASTFile(entry.Doc))
|
||||||
|
root.AddItem(f)
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalASTFiles(files []*FileEntry) *cjson.JSON {
|
||||||
|
root := cjson.Object()
|
||||||
|
for _, entry := range files {
|
||||||
|
root.SetItem(c.AllocaCStr(entry.Path), MarshalASTFile(entry.Doc))
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalDeclList(list []ast.Decl) *cjson.JSON {
|
||||||
|
root := cjson.Array()
|
||||||
|
for _, item := range list {
|
||||||
|
root.AddItem(MarshalASTDecl(item))
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalFieldList(list []*ast.Field) *cjson.JSON {
|
||||||
|
if list == nil {
|
||||||
|
return cjson.Null()
|
||||||
|
}
|
||||||
|
root := cjson.Array()
|
||||||
|
for _, item := range list {
|
||||||
|
root.AddItem(MarshalASTExpr(item))
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalIncludeList(list []*ast.Include) *cjson.JSON {
|
||||||
|
root := cjson.Array()
|
||||||
|
for _, item := range list {
|
||||||
|
include := cjson.Object()
|
||||||
|
include.SetItem(c.Str("_Type"), stringField("Include"))
|
||||||
|
include.SetItem(c.Str("Path"), stringField(item.Path))
|
||||||
|
root.AddItem(include)
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalMacroList(list []*ast.Macro) *cjson.JSON {
|
||||||
|
root := cjson.Array()
|
||||||
|
for _, item := range list {
|
||||||
|
macro := cjson.Object()
|
||||||
|
macro.SetItem(c.Str("_Type"), stringField("Macro"))
|
||||||
|
macro.SetItem(c.Str("Name"), stringField(item.Name))
|
||||||
|
macro.SetItem(c.Str("Tokens"), MarshalTokenList(item.Tokens))
|
||||||
|
root.AddItem(macro)
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalTokenList(list []*ast.Token) *cjson.JSON {
|
||||||
|
if list == nil {
|
||||||
|
return cjson.Null()
|
||||||
|
}
|
||||||
|
root := cjson.Array()
|
||||||
|
for _, item := range list {
|
||||||
|
root.AddItem(MarshalToken(item))
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalIdentList(list []*ast.Ident) *cjson.JSON {
|
||||||
|
if list == nil {
|
||||||
|
return cjson.Null()
|
||||||
|
}
|
||||||
|
root := cjson.Array()
|
||||||
|
for _, item := range list {
|
||||||
|
root.AddItem(MarshalASTExpr(item))
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalASTFile(file *ast.File) *cjson.JSON {
|
||||||
|
root := cjson.Object()
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("File"))
|
||||||
|
root.SetItem(c.Str("decls"), MarshalDeclList(file.Decls))
|
||||||
|
root.SetItem(c.Str("includes"), MarshalIncludeList(file.Includes))
|
||||||
|
root.SetItem(c.Str("macros"), MarshalMacroList(file.Macros))
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalToken(tok *ast.Token) *cjson.JSON {
|
||||||
|
root := cjson.Object()
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("Token"))
|
||||||
|
root.SetItem(c.Str("Token"), numberField(uint(tok.Token)))
|
||||||
|
root.SetItem(c.Str("Lit"), stringField(tok.Lit))
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalASTDecl(decl ast.Decl) *cjson.JSON {
|
||||||
|
if decl == nil {
|
||||||
|
return cjson.Null()
|
||||||
|
}
|
||||||
|
root := cjson.Object()
|
||||||
|
switch d := decl.(type) {
|
||||||
|
case *ast.EnumTypeDecl:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("EnumTypeDecl"))
|
||||||
|
MarshalASTDeclBase(d.DeclBase, root)
|
||||||
|
root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name))
|
||||||
|
root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type))
|
||||||
|
case *ast.TypedefDecl:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("TypedefDecl"))
|
||||||
|
MarshalASTDeclBase(d.DeclBase, root)
|
||||||
|
root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name))
|
||||||
|
root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type))
|
||||||
|
case *ast.FuncDecl:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("FuncDecl"))
|
||||||
|
MarshalASTDeclBase(d.DeclBase, root)
|
||||||
|
root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name))
|
||||||
|
root.SetItem(c.Str("MangledName"), stringField(d.MangledName))
|
||||||
|
root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type))
|
||||||
|
root.SetItem(c.Str("IsInline"), boolField(d.IsInline))
|
||||||
|
root.SetItem(c.Str("IsStatic"), boolField(d.IsStatic))
|
||||||
|
root.SetItem(c.Str("IsConst"), boolField(d.IsConst))
|
||||||
|
root.SetItem(c.Str("IsExplicit"), boolField(d.IsExplicit))
|
||||||
|
root.SetItem(c.Str("IsConstructor"), boolField(d.IsConstructor))
|
||||||
|
root.SetItem(c.Str("IsDestructor"), boolField(d.IsDestructor))
|
||||||
|
root.SetItem(c.Str("IsVirtual"), boolField(d.IsVirtual))
|
||||||
|
root.SetItem(c.Str("IsOverride"), boolField(d.IsOverride))
|
||||||
|
case *ast.TypeDecl:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("TypeDecl"))
|
||||||
|
MarshalASTDeclBase(d.DeclBase, root)
|
||||||
|
root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name))
|
||||||
|
root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type))
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalASTDeclBase(decl ast.DeclBase, root *cjson.JSON) {
|
||||||
|
loc := cjson.Object()
|
||||||
|
loc.SetItem(c.Str("_Type"), stringField("Location"))
|
||||||
|
loc.SetItem(c.Str("File"), stringField(decl.Loc.File))
|
||||||
|
root.SetItem(c.Str("Loc"), loc)
|
||||||
|
root.SetItem(c.Str("Doc"), MarshalASTExpr(decl.Doc))
|
||||||
|
root.SetItem(c.Str("Parent"), MarshalASTExpr(decl.Parent))
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalASTExpr(t ast.Expr) *cjson.JSON {
|
||||||
|
if t == nil {
|
||||||
|
return cjson.Null()
|
||||||
|
}
|
||||||
|
|
||||||
|
root := cjson.Object()
|
||||||
|
|
||||||
|
switch d := t.(type) {
|
||||||
|
case *ast.EnumType:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("EnumType"))
|
||||||
|
items := cjson.Array()
|
||||||
|
for _, e := range d.Items {
|
||||||
|
items.AddItem(MarshalASTExpr(e))
|
||||||
|
}
|
||||||
|
root.SetItem(c.Str("Items"), items)
|
||||||
|
case *ast.EnumItem:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("EnumItem"))
|
||||||
|
root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name))
|
||||||
|
root.SetItem(c.Str("Value"), MarshalASTExpr(d.Value))
|
||||||
|
case *ast.RecordType:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("RecordType"))
|
||||||
|
root.SetItem(c.Str("Tag"), numberField(uint(d.Tag)))
|
||||||
|
root.SetItem(c.Str("Fields"), MarshalASTExpr(d.Fields))
|
||||||
|
methods := cjson.Array()
|
||||||
|
for _, m := range d.Methods {
|
||||||
|
methods.AddItem(MarshalASTDecl(m))
|
||||||
|
}
|
||||||
|
root.SetItem(c.Str("Methods"), methods)
|
||||||
|
case *ast.FuncType:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("FuncType"))
|
||||||
|
root.SetItem(c.Str("Params"), MarshalASTExpr(d.Params))
|
||||||
|
root.SetItem(c.Str("Ret"), MarshalASTExpr(d.Ret))
|
||||||
|
case *ast.FieldList:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("FieldList"))
|
||||||
|
root.SetItem(c.Str("List"), MarshalFieldList(d.List))
|
||||||
|
case *ast.Field:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("Field"))
|
||||||
|
root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type))
|
||||||
|
root.SetItem(c.Str("Doc"), MarshalASTExpr(d.Doc))
|
||||||
|
root.SetItem(c.Str("Comment"), MarshalASTExpr(d.Comment))
|
||||||
|
root.SetItem(c.Str("IsStatic"), boolField(d.IsStatic))
|
||||||
|
root.SetItem(c.Str("Access"), numberField(uint(d.Access)))
|
||||||
|
root.SetItem(c.Str("Names"), MarshalIdentList(d.Names))
|
||||||
|
case *ast.Variadic:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("Variadic"))
|
||||||
|
case *ast.Ident:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("Ident"))
|
||||||
|
if d == nil {
|
||||||
|
return cjson.Null()
|
||||||
|
}
|
||||||
|
root.SetItem(c.Str("Name"), stringField(d.Name))
|
||||||
|
case *ast.TagExpr:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("TagExpr"))
|
||||||
|
root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name))
|
||||||
|
root.SetItem(c.Str("Tag"), numberField(uint(d.Tag)))
|
||||||
|
case *ast.BasicLit:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("BasicLit"))
|
||||||
|
root.SetItem(c.Str("Kind"), numberField(uint(d.Kind)))
|
||||||
|
root.SetItem(c.Str("Value"), stringField(d.Value))
|
||||||
|
case *ast.LvalueRefType:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("LvalueRefType"))
|
||||||
|
root.SetItem(c.Str("X"), MarshalASTExpr(d.X))
|
||||||
|
case *ast.RvalueRefType:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("RvalueRefType"))
|
||||||
|
root.SetItem(c.Str("X"), MarshalASTExpr(d.X))
|
||||||
|
case *ast.PointerType:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("PointerType"))
|
||||||
|
root.SetItem(c.Str("X"), MarshalASTExpr(d.X))
|
||||||
|
case *ast.ArrayType:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("ArrayType"))
|
||||||
|
root.SetItem(c.Str("Elt"), MarshalASTExpr(d.Elt))
|
||||||
|
root.SetItem(c.Str("Len"), MarshalASTExpr(d.Len))
|
||||||
|
case *ast.BuiltinType:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("BuiltinType"))
|
||||||
|
root.SetItem(c.Str("Kind"), numberField(uint(d.Kind)))
|
||||||
|
root.SetItem(c.Str("Flags"), numberField(uint(d.Flags)))
|
||||||
|
case *ast.Comment:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("Comment"))
|
||||||
|
if d == nil {
|
||||||
|
return cjson.Null()
|
||||||
|
}
|
||||||
|
root.SetItem(c.Str("Text"), stringField(d.Text))
|
||||||
|
case *ast.CommentGroup:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("CommentGroup"))
|
||||||
|
if d == nil {
|
||||||
|
return cjson.Null()
|
||||||
|
}
|
||||||
|
list := cjson.Array()
|
||||||
|
for _, c := range d.List {
|
||||||
|
list.AddItem(MarshalASTExpr(c))
|
||||||
|
}
|
||||||
|
root.SetItem(c.Str("List"), list)
|
||||||
|
case *ast.ScopingExpr:
|
||||||
|
root.SetItem(c.Str("_Type"), stringField("ScopingExpr"))
|
||||||
|
root.SetItem(c.Str("X"), MarshalASTExpr(d.X))
|
||||||
|
root.SetItem(c.Str("Parent"), MarshalASTExpr(d.Parent))
|
||||||
|
default:
|
||||||
|
return cjson.Null()
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringField(s string) *cjson.JSON {
|
||||||
|
return cjson.String(c.AllocaCStr(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
func numberField(n uint) *cjson.JSON {
|
||||||
|
return cjson.Number(float64(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
func boolField(b bool) *cjson.JSON {
|
||||||
|
if b {
|
||||||
|
return cjson.True()
|
||||||
|
}
|
||||||
|
return cjson.False()
|
||||||
|
}
|
||||||
68
chore/_xtool/llcppsigfetch/parse/parse.go
Normal file
68
chore/_xtool/llcppsigfetch/parse/parse.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package parse
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c/cjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Context struct {
|
||||||
|
Files []*FileEntry
|
||||||
|
IsCpp bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewContext(isCpp bool) *Context {
|
||||||
|
return &Context{
|
||||||
|
Files: make([]*FileEntry, 0),
|
||||||
|
IsCpp: isCpp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Context) Output() *cjson.JSON {
|
||||||
|
return MarshalOutputASTFiles(p.Files)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessFiles processes the given files and adds them to the context
|
||||||
|
func (p *Context) ProcessFiles(files []string) error {
|
||||||
|
for _, file := range files {
|
||||||
|
if err := p.processFile(file); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse file and add it to the context,avoid duplicate parsing
|
||||||
|
func (p *Context) processFile(path string) error {
|
||||||
|
for _, entry := range p.Files {
|
||||||
|
if entry.Path == path {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parsedFiles, err := p.parseFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("failed to parse file: " + path)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Files = append(p.Files, parsedFiles...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Context) parseFile(path string) ([]*FileEntry, error) {
|
||||||
|
converter, err := NewConverter(&Config{
|
||||||
|
File: path,
|
||||||
|
Temp: false,
|
||||||
|
IsCpp: p.IsCpp,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to create converter " + path)
|
||||||
|
}
|
||||||
|
defer converter.Dispose()
|
||||||
|
|
||||||
|
files, err := converter.Convert()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user