Skip to content

Commit ed735fa

Browse files
fix/query: resolve type lifting after OR parsing (#1023)
The parser used to lift `type:` directives before converting `or` placeholders into real boolean nodes. That let parse-time `orOp` sentinels leak into `Type` children for unparenthesized queries and allowed malformed inputs like `type:repo or` to parse successfully until runtime. Resolve operator placeholders before wrapping with `Type` so unparenthesized `or` inside a type scope produces a valid `Or` subtree and malformed `or` placement is rejected during parsing. The docs now clarify that `type:` applies to the whole expression in its current scope, including `or` clauses. Amp-Thread-ID: https://ampcode.com/threads/T-019d0be7-4c9d-76fd-b556-103420d14be9 Co-authored-by: Amp <amp@ampcode.com>
1 parent cf27384 commit ed735fa

3 files changed

Lines changed: 13 additions & 1 deletion

File tree

doc/query_syntax.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ This returns repository names instead of file matches. Valid values include:
111111
- `filename` - Returns only matching filenames
112112
- `repo` - Returns only repository names
113113

114+
`type:` applies to the whole expression in its current scope, including `or`
115+
clauses. For example, `type:repo foo or bar` is equivalent to
116+
`type:repo (foo or bar)`. Use parentheses to scope `type:` to only one branch,
117+
for example `(type:repo foo) or bar`.
118+
114119
---
115120

116121
## Special Query Values

query/parse.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,11 @@ func parseExprList(in []byte) ([]Q, int, error) {
416416
return q
417417
})
418418
if typeT != 100 {
419-
qs = []Q{&Type{Type: typeT, Child: NewAnd(qs...)}}
419+
typedQ, err := parseOperators(qs)
420+
if err != nil {
421+
return nil, 0, err
422+
}
423+
qs = []Q{&Type{Type: typeT, Child: typedQ}}
420424
}
421425

422426
if hasCaseScope {

query/parse_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ func TestParseQuery(t *testing.T) {
132132
// type
133133
{"type:repo abc", &Type{Type: TypeRepo, Child: &Substring{Pattern: "abc"}}},
134134
{"type:file abc def", &Type{Type: TypeFileName, Child: NewAnd(&Substring{Pattern: "abc"}, &Substring{Pattern: "def"})}},
135+
{"type:repo foo or bar", &Type{Type: TypeRepo, Child: NewOr(&Substring{Pattern: "foo"}, &Substring{Pattern: "bar"})}},
135136
{"(type:repo abc) def", NewAnd(&Type{Type: TypeRepo, Child: &Substring{Pattern: "abc"}}, &Substring{Pattern: "def"})},
136137

137138
// errors.
@@ -144,6 +145,8 @@ func TestParseQuery(t *testing.T) {
144145
{"abc or", nil},
145146
{"or abc", nil},
146147
{"def or or abc", nil},
148+
{"type:repo or", nil},
149+
{"or type:repo", nil},
147150

148151
// unbalanced parentheses
149152
{"(", nil},

0 commit comments

Comments
 (0)