Skip to content

Commit 2fa7236

Browse files
committed
pkg/codesearch: support finding field reads/writes
1 parent cf894e0 commit 2fa7236

17 files changed

+235
-19
lines changed

pkg/aflow/tool/codesearcher/codesearcher.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ For example, how a function works, what precondition error checks it has, etc.
4848
aflow.NewFuncTool("codesearch-find-references", findReferences, `
4949
Tool finds and lists all references to (uses of) the given entity.
5050
Entity can be function, struct, or global variable.
51-
If can be used to find all calls or other uses of the given function.
51+
If can be used to find all calls or other uses of the given function,
52+
definition of the given struct/union/enum,
53+
or all reads/writes of the given struct/union field.
54+
To find field references use 'struct_name::field_name' syntax.
5255
`),
5356
}
5457

pkg/codesearch/codesearch.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,14 @@ type ReferenceInfo struct {
259259

260260
func (index *Index) FindReferences(contextFile, name, srcPrefix string, contextLines, outputLimit int) (
261261
[]ReferenceInfo, int, error) {
262+
// Just in case LLM decides to reference structs/fields with the tag.
263+
name = strings.TrimSpace(strings.TrimPrefix(strings.TrimPrefix(strings.TrimSpace(name),
264+
"struct "), "union "))
265+
// We don't export each field as a separate definition,
266+
// so we do just name-based match for them.
267+
isField := strings.Contains(name, "::")
262268
target := index.findDefinition(contextFile, name)
263-
if target == nil {
269+
if target == nil && !isField {
264270
return nil, 0, aflow.BadCallError("requested entity does not exist")
265271
}
266272
if srcPrefix != "" {
@@ -278,8 +284,8 @@ func (index *Index) FindReferences(contextFile, name, srcPrefix string, contextL
278284
// the target is a non-static 'foo' in some file,
279285
// the reference is in another file and refers to a static 'foo'
280286
// defined in that file (which is not the target 'foo').
281-
if ref.EntityKind != target.Kind || ref.Name != target.Name ||
282-
target.IsStatic && target.Body.File != def.Body.File {
287+
if ref.Name != name || !isField && (ref.EntityKind != target.Kind ||
288+
target.IsStatic && target.Body.File != def.Body.File) {
283289
continue
284290
}
285291
totalCount++

pkg/codesearch/codesearch_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ func testCommand(t *testing.T, index *Index, covered map[string]bool, file strin
5454
cmd := fields[0]
5555
var args []string
5656
for _, arg := range fields[1:] {
57-
if arg == `""` {
58-
arg = ""
57+
if len(arg) >= 2 && arg[0] == '"' && arg[len(arg)-1] == '"' {
58+
arg = arg[1 : len(arg)-1]
5959
}
6060
args = append(args, arg)
6161
}

pkg/codesearch/database.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ const (
5757
EntityKindMacro
5858
EntityKindEnum
5959
EntityKindTypedef
60+
EntityKindField
6061
entityKindLast
6162
)
6263

@@ -68,6 +69,7 @@ var entityKindNames = [...]string{
6869
EntityKindMacro: "macro",
6970
EntityKindEnum: "enum",
7071
EntityKindTypedef: "typedef",
72+
EntityKindField: "field",
7173
}
7274

7375
var entityKindBytes = func() [entityKindLast][]byte {
@@ -103,13 +105,17 @@ const (
103105
refKindInvalid RefKind = iota
104106
RefKindUses
105107
RefKindCall
108+
RefKindRead
109+
RefKindWrite
106110
RefKindTakesAddr
107111
refKindLast
108112
)
109113

110114
var refKindNames = [...]string{
111115
RefKindUses: "uses",
112116
RefKindCall: "calls",
117+
RefKindRead: "reads",
118+
RefKindWrite: "writes",
113119
RefKindTakesAddr: "takes-address-of",
114120
}
115121

pkg/codesearch/testdata/query-def-source-struct7

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ union some_union is defined in source0.h:
55
40: union some_union {
66
41: int x;
77
42: void* p;
8-
43: };
8+
43: struct some_struct s;
9+
44: };

pkg/codesearch/testdata/query-def-source-struct8

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ def-source source0.c some_enum yes
22

33
enum some_enum is defined in source0.h:
44

5-
45: enum some_enum {
6-
46: enum_foo = 1,
7-
47: enum_bar = 2,
8-
48: };
5+
46: enum some_enum {
6+
47: enum_foo = 1,
7+
48: enum_bar = 2,
8+
49: };

pkg/codesearch/testdata/query-def-source-struct9

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ def-source source0.c some_enum_t yes
22

33
typedef some_enum_t is defined in source0.h:
44

5-
50: typedef enum some_enum some_enum_t;
5+
51: typedef enum some_enum some_enum_t;

pkg/codesearch/testdata/query-file-index-source

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ file-index source0.c
33
file source0.c defines the following entities:
44

55
function close
6+
function field_refs
67
function func_accepting_a_struct
78
function function_with_comment_in_header
89
function function_with_quotes_in_type
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
find-references source0.c some_struct::x "" 1 10
2+
3+
some_struct::x has 5 references:
4+
5+
function field_refs writes it at source0.c:37
6+
36: {
7+
37: p->x = p->y;
8+
38: *(&p->x) = 1;
9+
10+
11+
function field_refs takes-address-of it at source0.c:38
12+
37: p->x = p->y;
13+
38: *(&p->x) = 1;
14+
39: u->p = 0;
15+
16+
17+
function field_refs writes it at source0.c:40
18+
39: u->p = 0;
19+
40: u->s.x = 2;
20+
41: return p->x;
21+
22+
23+
function field_refs reads it at source0.c:41
24+
40: u->s.x = 2;
25+
41: return p->x;
26+
42: }
27+
28+
29+
function func_accepting_a_struct reads it at source0.c:31
30+
30: {
31+
31: return ((some_struct_t*)p)->x +
32+
32: ((union some_union*)p)->x;
33+
34+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
find-references source0.c some_struct::y "" 1 10
2+
3+
some_struct::y has 1 references:
4+
5+
function field_refs reads it at source0.c:37
6+
36: {
7+
37: p->x = p->y;
8+
38: *(&p->x) = 1;
9+
10+

0 commit comments

Comments
 (0)