Skip to content

Commit 56e878a

Browse files
authored
fix: resolve java method calls to long signature definitions correctly (#183)
* fix: resolve java method calls to long signature definitions correctly * fix(java): resolve internal method calls using two-pass approach When a method calls another method that is defined later in the same class, the current single-pass logic fails to find the callee method symbol and creates a stub. This commit introduces a two-pass approach within `processClass`: 1. Iterate over methods and create definitions/symbols. 2. Iterate over methods again to process method calls and resolve them against the symbols created in the first pass.
1 parent 0f42164 commit 56e878a

3 files changed

Lines changed: 40 additions & 11 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ require (
2323
github.com/stretchr/testify v1.10.0
2424
github.com/vifraa/gopom v1.0.0
2525
golang.org/x/mod v0.24.0
26+
golang.org/x/sync v0.13.0
2627
golang.org/x/tools v0.32.0
2728
)
2829

@@ -91,7 +92,6 @@ require (
9192
golang.org/x/arch v0.14.0 // indirect
9293
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa // indirect
9394
golang.org/x/net v0.39.0 // indirect
94-
golang.org/x/sync v0.13.0 // indirect
9595
golang.org/x/sys v0.33.0 // indirect
9696
golang.org/x/text v0.24.0 // indirect
9797
gopkg.in/yaml.v2 v2.4.0 // indirect

lang/collect/collect.go

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import (
2626
"sync"
2727
"unicode"
2828

29-
"golang.org/x/sync/errgroup"
3029
sitter "github.com/smacker/go-tree-sitter"
30+
"golang.org/x/sync/errgroup"
3131

3232
"github.com/cloudwego/abcoder/lang/cpp"
3333
"github.com/cloudwego/abcoder/lang/cxx"
@@ -819,7 +819,13 @@ func (c *Collector) ScannerByJavaIPC(ctx context.Context) ([]*DocumentSymbol, er
819819
}
820820
}
821821

822-
// 4) Methods (and method calls)
822+
// 4) Methods (Pass 1: Definitions)
823+
type methodAndSym struct {
824+
m *javapb.MethodDetail
825+
msym *DocumentSymbol
826+
}
827+
var methodSyms []methodAndSym
828+
823829
for _, m := range ci.Methods {
824830
if m == nil {
825831
continue
@@ -852,6 +858,12 @@ func (c *Collector) ScannerByJavaIPC(ctx context.Context) ([]*DocumentSymbol, er
852858
}
853859
if n := m.GetName(); n != "" {
854860
methodSymByKey[methodKey(fqcn, n)] = msym
861+
shortName := strings.TrimSpace(n)
862+
parts := strings.Split(shortName, " ")
863+
shortName = parts[len(parts)-1]
864+
if shortName != "" && shortName != n {
865+
methodSymByKey[methodKey(fqcn, shortName)] = msym
866+
}
855867
}
856868

857869
// Fill functionInfo
@@ -900,12 +912,23 @@ func (c *Collector) ScannerByJavaIPC(ctx context.Context) ([]*DocumentSymbol, er
900912
}
901913
}
902914
c.funcs[msym] = finfo
915+
methodSyms = append(methodSyms, methodAndSym{m: m, msym: msym})
916+
}
917+
918+
// 5) Process method calls (Pass 2)
919+
for _, pair := range methodSyms {
920+
m := pair.m
921+
msym := pair.msym
903922

904-
// Method calls
905923
for _, call := range m.MethodCalls {
906-
if call == nil || call.CalleeClass == "" {
924+
if call == nil {
925+
continue
926+
}
927+
928+
if call.CalleeClass == "" {
907929
continue
908930
}
931+
909932
calleeInfo := resolveClass(call.CalleeClass)
910933
if calleeInfo == nil {
911934
// drop if callee class can't be resolved
@@ -924,23 +947,29 @@ func (c *Collector) ScannerByJavaIPC(ctx context.Context) ([]*DocumentSymbol, er
924947
if call.CalleeMethod != "" {
925948
if s, ok := methodSymByKey[methodKey(call.CalleeClass, call.CalleeMethod)]; ok {
926949
calleeMethodSym = s
950+
} else {
951+
shortName := call.CalleeMethod
952+
if idx := strings.IndexByte(shortName, '('); idx >= 0 {
953+
shortName = shortName[:idx]
954+
}
955+
parts := strings.Split(shortName, " ")
956+
shortName = parts[len(parts)-1]
957+
if s, ok := methodSymByKey[methodKey(call.CalleeClass, shortName)]; ok {
958+
calleeMethodSym = s
959+
}
927960
}
928961
}
929962
if calleeMethodSym == nil {
930963
// Create a lightweight stub method symbol (one-layer only).
931964
// IMPORTANT: do NOT put it into c.syms to avoid clobbering class symbols.
932965
stubLoc := Location{URI: calleeClassSym.Location.URI, Range: Range{Start: calleeClassSym.Location.Range.Start, End: calleeClassSym.Location.Range.Start}}
933966
calleeMethodSym = &DocumentSymbol{
934-
Name: call.CalleeMethod,
967+
Name: calleeClassSym.Name + "." + call.CalleeMethod,
935968
Kind: SKMethod,
936969
Text: "",
937970
Location: stubLoc,
938971
Role: DEFINITION,
939972
}
940-
941-
if _, ok := localByName[call.CalleeClass]; !ok {
942-
calleeMethodSym.Name = call.CalleeClass + "." + call.CalleeMethod
943-
}
944973
}
945974

946975
tokFile := normalizePath(call.FilePath)

testdata/asts/localsession_g.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)