@@ -27,6 +27,7 @@ import (
2727
2828 sitter "github.com/smacker/go-tree-sitter"
2929
30+ "github.com/cloudwego/abcoder/lang/cpp"
3031 "github.com/cloudwego/abcoder/lang/cxx"
3132 "github.com/cloudwego/abcoder/lang/java"
3233 javaipc "github.com/cloudwego/abcoder/lang/java/ipc"
@@ -113,6 +114,8 @@ func switchSpec(l uniast.Language, repo string) LanguageSpec {
113114 return python .NewPythonSpec ()
114115 case uniast .Java :
115116 return java .NewJavaSpec (repo )
117+ case uniast .Cpp :
118+ return cpp .NewCppSpec ()
116119 default :
117120 panic (fmt .Sprintf ("unsupported language %s" , l ))
118121 }
@@ -1698,9 +1701,11 @@ func (c *Collector) getSymbolByLocation(ctx context.Context, loc Location, depth
16981701 // return sym, nil
16991702 // }
17001703
1701- // 1. already loaded
1702- if sym := c .findMatchingSymbolIn (loc , slices .Collect (maps .Values (c .syms ))); sym != nil {
1703- return sym , nil
1704+ if ! (from .Type == "typeParameter" && c .Language == uniast .Cpp ) {
1705+ // 1. already loaded
1706+ if sym := c .findMatchingSymbolIn (loc , slices .Collect (maps .Values (c .syms ))); sym != nil {
1707+ return sym , nil
1708+ }
17041709 }
17051710
17061711 if c .LoadExternalSymbol && ! c .internal (loc ) && (c .NeedStdSymbol || ! c .spec .IsStdToken (from )) {
@@ -1929,11 +1934,11 @@ func (c *Collector) processSymbol(ctx context.Context, sym *DocumentSymbol, dept
19291934
19301935 // function info: type params, inputs, outputs, receiver (if !needImpl)
19311936 if sym .Kind == SKFunction || sym .Kind == SKMethod {
1932- var rsym * dependency
1937+ var rd * dependency
19331938 rec , tps , ips , ops := c .spec .FunctionSymbol (* sym )
1934-
1935- if ! hasImpl && rec >= 0 {
1939+ if (! hasImpl || c .Language == uniast .Cpp ) && rec >= 0 {
19361940 rsym , err := c .getSymbolByTokenWithLimit (ctx , sym .Tokens [rec ], depth )
1941+ rd = & dependency {sym .Tokens [rec ].Location , rsym }
19371942 if err != nil || rsym == nil {
19381943 log .Error ("get receiver symbol for token %v failed: %v\n " , rec , err )
19391944 }
@@ -1942,6 +1947,18 @@ func (c *Collector) processSymbol(ctx context.Context, sym *DocumentSymbol, dept
19421947 ipsyms , is := c .getDepsWithLimit (ctx , sym , ips , depth - 1 )
19431948 opsyms , os := c .getDepsWithLimit (ctx , sym , ops , depth - 1 )
19441949
1950+ // filter tsym is type parameter
1951+ if c .Language == uniast .Cpp {
1952+ tsFiltered := make ([]dependency , 0 , len (ts ))
1953+ for _ , d := range ts {
1954+ if d .Symbol == nil || d .Symbol .Kind == SKTypeParameter {
1955+ continue
1956+ }
1957+ tsFiltered = append (tsFiltered , d )
1958+ }
1959+ ts = tsFiltered
1960+ }
1961+
19451962 //get last token of params for get signature
19461963 lastToken := rec
19471964 for _ , t := range tps {
@@ -1960,18 +1977,28 @@ func (c *Collector) processSymbol(ctx context.Context, sym *DocumentSymbol, dept
19601977 }
19611978 }
19621979
1963- c .updateFunctionInfo (sym , tsyms , ipsyms , opsyms , ts , is , os , rsym , lastToken )
1980+ c .updateFunctionInfo (sym , tsyms , ipsyms , opsyms , ts , is , os , rd , lastToken )
19641981 }
19651982
19661983 // variable info: type
19671984 if sym .Kind == SKVariable || sym .Kind == SKConstant {
19681985 i := c .spec .DeclareTokenOfSymbol (* sym )
1986+ // in cpp, it should search form behind to front to find the first entity token
19691987 // find first entity token
1970- for i = i + 1 ; i < len (sym .Tokens ); i ++ {
1971- if c .spec .IsEntityToken (sym .Tokens [i ]) {
1972- break
1988+ if c .Language == uniast .Cpp {
1989+ for i = i - 1 ; i >= 0 ; i -- {
1990+ if c .spec .IsEntityToken (sym .Tokens [i ]) {
1991+ break
1992+ }
1993+ }
1994+ } else {
1995+ for i = i + 1 ; i < len (sym .Tokens ); i ++ {
1996+ if c .spec .IsEntityToken (sym .Tokens [i ]) {
1997+ break
1998+ }
19731999 }
19742000 }
2001+
19752002 if i < 0 || i >= len (sym .Tokens ) {
19762003 log .Error ("get type token of variable symbol %s failed\n " , sym )
19772004 return
0 commit comments