Skip to content

Commit 1cb5ed7

Browse files
authored
Tolerate missing '=' value in compact options (#219)
While still producing an error, see: #200
1 parent ebf3519 commit 1cb5ed7

File tree

4 files changed

+269
-211
lines changed

4 files changed

+269
-211
lines changed

ast/options.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,18 @@ func NewCompactOptionNode(name *OptionNameNode, equals *RuneNode, val ValueNode)
100100
if name == nil {
101101
panic("name is nil")
102102
}
103-
if equals == nil {
104-
panic("equals is nil")
103+
if equals == nil && val != nil {
104+
panic("equals is nil but val is not")
105105
}
106-
if val == nil {
107-
panic("val is nil")
106+
if val == nil && equals != nil {
107+
panic("val is nil but equals is not")
108+
}
109+
var children []Node
110+
if equals == nil && val == nil {
111+
children = []Node{name}
112+
} else {
113+
children = []Node{name, equals, val}
108114
}
109-
children := []Node{name, equals, val}
110115
return &OptionNode{
111116
compositeNode: compositeNode{
112117
children: children,

parser/parser_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,47 @@ func TestLenientParse_EmptyCompactOptions(t *testing.T) {
408408
}
409409
}
410410

411+
func TestLenientParse_EmptyCompactValue(t *testing.T) {
412+
t.Parallel()
413+
inputs := map[string]struct {
414+
Error string
415+
NoError string
416+
}{
417+
"field-options": {
418+
Error: `syntax = "proto2";
419+
message Foo {
420+
optional int32 bar = 1 [deprecated=true, default];
421+
}`,
422+
NoError: `syntax = "proto3";
423+
message Foo {
424+
optional int32 bar = 1 [deprecated=true, default=1];
425+
}`,
426+
},
427+
"enum-options": {
428+
Error: `syntax = "proto3";
429+
enum Foo {
430+
FOO = 0 [deprecated];
431+
}`,
432+
NoError: `syntax = "proto3";
433+
enum Foo {
434+
FOO = 0 [deprecated=true];
435+
}`,
436+
},
437+
}
438+
for name, input := range inputs {
439+
name, input := name, input
440+
t.Run(name, func(t *testing.T) {
441+
t.Parallel()
442+
errHandler := reporter.NewHandler(nil)
443+
protoName := fmt.Sprintf("%s.proto", name)
444+
_, err := Parse(protoName, strings.NewReader(input.NoError), errHandler)
445+
require.NoError(t, err)
446+
_, err = Parse(protoName, strings.NewReader(input.Error), errHandler)
447+
require.ErrorContains(t, err, "compact option must have a value")
448+
})
449+
}
450+
}
451+
411452
func TestSimpleParse(t *testing.T) {
412453
t.Parallel()
413454
protos := map[string]Result{}

parser/proto.y

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,11 @@ compactOptionDecls : compactOption {
616616
compactOption: optionName '=' optionValue {
617617
optName := ast.NewOptionNameNode($1.refs, $1.dots)
618618
$$ = ast.NewCompactOptionNode(optName, $2, $3)
619+
} |
620+
optionName {
621+
optName := ast.NewOptionNameNode($1.refs, $1.dots)
622+
protolex.(*protoLex).Error("compact option must have a value")
623+
$$ = ast.NewCompactOptionNode(optName, nil, nil)
619624
}
620625

621626
groupDecl : fieldCardinality _GROUP identifier '=' _INT_LIT '{' messageBody '}' {

0 commit comments

Comments
 (0)