Skip to content

Commit b87b838

Browse files
committed
syntax: use LangError consistently and add a LangUsed field
1 parent cbc2c7b commit b87b838

File tree

3 files changed

+63
-55
lines changed

3 files changed

+63
-55
lines changed

syntax/example_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func ExampleNewParser_options() {
9292

9393
// Output:
9494
// <nil>
95-
// 1:5: c-style fors are a bash feature
95+
// 1:5: c-style fors are a bash feature; tried parsing as posix
9696
// for ((i = 0; i < 5; i++)); do echo $i >f; done
9797
// for ((i = 0; i < 5; i++)); do echo $i > f; done
9898
}

syntax/parser.go

+18-11
Original file line numberDiff line numberDiff line change
@@ -861,8 +861,13 @@ func (e ParseError) Error() string {
861861
type LangError struct {
862862
Filename string
863863
Pos Pos
864-
Feature string
865-
Langs []LangVariant
864+
865+
// Feature briefly describes which language feature caused the error.
866+
Feature string
867+
// Langs lists some of the language variants which support the feature.
868+
Langs []LangVariant
869+
// LangUsed is the language variant used which led to the error.
870+
LangUsed LangVariant
866871
}
867872

868873
func (e LangError) Error() string {
@@ -883,7 +888,8 @@ func (e LangError) Error() string {
883888
}
884889
sb.WriteString(lang.String())
885890
}
886-
sb.WriteString(" feature")
891+
sb.WriteString(" feature; tried parsing as ")
892+
sb.WriteString(e.LangUsed.String())
887893
return sb.String()
888894
}
889895

@@ -906,6 +912,7 @@ func (p *Parser) langErr(pos Pos, feature string, langs ...LangVariant) {
906912
Pos: pos,
907913
Feature: feature,
908914
Langs: langs,
915+
LangUsed: p.lang,
909916
})
910917
}
911918

@@ -1052,12 +1059,12 @@ func (p *Parser) wordPart() WordPart {
10521059
switch p.r {
10531060
case '|':
10541061
if p.lang != LangMirBSDKorn {
1055-
p.curErr(`"${|stmts;}" is a mksh feature`)
1062+
p.langErr(p.pos, `"${|stmts;}"`, LangMirBSDKorn)
10561063
}
10571064
fallthrough
10581065
case ' ', '\t', '\n':
10591066
if p.lang != LangMirBSDKorn {
1060-
p.curErr(`"${ stmts;}" is a mksh feature`)
1067+
p.langErr(p.pos, `"${ stmts;}"`, LangMirBSDKorn)
10611068
}
10621069
cs := &CmdSubst{
10631070
Left: p.pos,
@@ -1303,7 +1310,7 @@ func (p *Parser) paramExp() *ParamExp {
13031310
}
13041311
case perc:
13051312
if p.lang != LangMirBSDKorn {
1306-
p.posErr(pe.Pos(), `"${%%foo}" is a mksh feature`)
1313+
p.langErr(pe.Pos(), `"${%foo}"`, LangMirBSDKorn)
13071314
}
13081315
if paramNameOp(p.r) {
13091316
pe.Width = true
@@ -1343,7 +1350,7 @@ func (p *Parser) paramExp() *ParamExp {
13431350
p.curErr("%s cannot be followed by a word", op)
13441351
case rightBrace:
13451352
if pe.Excl && p.lang == LangPOSIX {
1346-
p.posErr(pe.Pos(), `"${!foo}" is a bash/mksh feature`)
1353+
p.langErr(pe.Pos(), `"${!foo}"`, LangBash, LangMirBSDKorn)
13471354
}
13481355
pe.Rbrace = p.pos
13491356
p.quote = old
@@ -1416,7 +1423,7 @@ func (p *Parser) paramExp() *ParamExp {
14161423
p.curErr("not a valid parameter expansion operator: %v", p.tok)
14171424
case pe.Excl && p.r == '}':
14181425
if !p.lang.isBash() {
1419-
p.posErr(pe.Pos(), `"${!foo%s}" is a bash feature`, p.tok)
1426+
p.langErr(pe.Pos(), fmt.Sprintf(`"${!foo%s}"`, p.tok), LangBash)
14201427
}
14211428
pe.Names = ParNamesOperator(p.tok)
14221429
p.next()
@@ -2123,7 +2130,7 @@ func (p *Parser) caseClause(s *Stmt) {
21232130
cc.In = pos
21242131
cc.Braces = true
21252132
if p.lang != LangMirBSDKorn {
2126-
p.posErr(cc.Pos(), `"case i {" is a mksh feature`)
2133+
p.langErr(cc.Pos(), `"case i {"`, LangMirBSDKorn)
21272134
}
21282135
end = "}"
21292136
} else {
@@ -2480,7 +2487,7 @@ loop:
24802487
}
24812488
// Avoid failing later with the confusing "} can only be used to close a block".
24822489
if p.lang == LangPOSIX && p.val == "{" && w != nil && w.Lit() == "function" {
2483-
p.curErr("the %q builtin is a bash feature; tried parsing as posix", "function")
2490+
p.langErr(p.pos, `the "function" builtin`, LangBash)
24842491
}
24852492
ce.Args = append(ce.Args, p.wordOne(p.lit(p.pos, p.val)))
24862493
p.next()
@@ -2513,7 +2520,7 @@ loop:
25132520
// Note that we'll only keep the first error that happens.
25142521
if len(ce.Args) > 0 {
25152522
if cmd := ce.Args[0].Lit(); p.lang == LangPOSIX && isBashCompoundCommand(_LitWord, cmd) {
2516-
p.curErr("the %q builtin is a bash feature; tried parsing as posix", cmd)
2523+
p.langErr(p.pos, fmt.Sprintf("the %q builtin", cmd), LangBash)
25172524
}
25182525
}
25192526
p.curErr("a command can only contain words and redirects; encountered %s", p.tok)

syntax/parser_test.go

+44-43
Original file line numberDiff line numberDiff line change
@@ -429,17 +429,17 @@ var shellTests = []errorCase{
429429
},
430430
{
431431
in: `((# 1 + 2))`,
432-
bash: `1:1: unsigned expressions are a mksh feature`,
432+
bash: `1:1: unsigned expressions are a mksh feature; tried parsing as bash`,
433433
},
434434
{
435435
in: `$((# 1 + 2))`,
436-
posix: `1:1: unsigned expressions are a mksh feature`,
437-
bash: `1:1: unsigned expressions are a mksh feature`,
436+
posix: `1:1: unsigned expressions are a mksh feature; tried parsing as posix`,
437+
bash: `1:1: unsigned expressions are a mksh feature; tried parsing as bash`,
438438
},
439439
{
440440
in: `${ foo;}`,
441-
posix: `1:1: "${ stmts;}" is a mksh feature`,
442-
bash: `1:1: "${ stmts;}" is a mksh feature`,
441+
posix: `1:1: "${ stmts;}" is a mksh feature; tried parsing as posix`,
442+
bash: `1:1: "${ stmts;}" is a mksh feature; tried parsing as bash`,
443443
},
444444
{
445445
in: `${ `,
@@ -455,8 +455,8 @@ var shellTests = []errorCase{
455455
},
456456
{
457457
in: `${|foo;}`,
458-
posix: `1:1: "${|stmts;}" is a mksh feature`,
459-
bash: `1:1: "${|stmts;}" is a mksh feature`,
458+
posix: `1:1: "${|stmts;}" is a mksh feature; tried parsing as posix`,
459+
bash: `1:1: "${|stmts;}" is a mksh feature; tried parsing as bash`,
460460
},
461461
{
462462
in: `${|`,
@@ -769,11 +769,11 @@ var shellTests = []errorCase{
769769
},
770770
{
771771
in: "foo &>/dev/null",
772-
posix: `1:5: &> redirects are a bash/mksh feature`,
772+
posix: `1:5: &> redirects are a bash/mksh feature; tried parsing as posix`,
773773
},
774774
{
775775
in: "foo &>>/dev/null",
776-
posix: `1:5: &> redirects are a bash/mksh feature`,
776+
posix: `1:5: &> redirects are a bash/mksh feature; tried parsing as posix`,
777777
},
778778
{
779779
in: "<<",
@@ -1151,7 +1151,7 @@ var shellTests = []errorCase{
11511151
},
11521152
{
11531153
in: "echo ${%",
1154-
common: `1:6: "${%foo}" is a mksh feature`,
1154+
common: `1:6: "${%foo}" is a mksh feature; tried parsing as LANG`,
11551155
mksh: `1:8: parameter expansion requires a literal`,
11561156
},
11571157
{
@@ -1280,7 +1280,7 @@ var shellTests = []errorCase{
12801280
},
12811281
{
12821282
in: "case i {",
1283-
common: `1:1: "case i {" is a mksh feature`,
1283+
common: `1:1: "case i {" is a mksh feature; tried parsing as LANG`,
12841284
mksh: `1:1: case statement must end with "}"`,
12851285
},
12861286
{
@@ -1483,7 +1483,7 @@ var shellTests = []errorCase{
14831483
{
14841484
in: "[[ a =~",
14851485
bash: `1:6: =~ must be followed by a word`,
1486-
mksh: `1:6: regex tests are a bash feature`,
1486+
mksh: `1:6: regex tests are a bash feature; tried parsing as mksh`,
14871487
},
14881488
{
14891489
in: "[[ -f a",
@@ -1851,8 +1851,8 @@ var shellTests = []errorCase{
18511851
// so that users won't think this will work like they expect in
18521852
// POSIX shell.
18531853
in: "echo {var}>foo",
1854-
posix: `1:6: {varname} redirects are a bash feature #NOERR`,
1855-
mksh: `1:6: {varname} redirects are a bash feature #NOERR`,
1854+
posix: `1:6: {varname} redirects are a bash feature; tried parsing as posix #NOERR`,
1855+
mksh: `1:6: {varname} redirects are a bash feature; tried parsing as mksh #NOERR`,
18561856
},
18571857
{
18581858
in: "echo ;&",
@@ -1871,115 +1871,115 @@ var shellTests = []errorCase{
18711871
},
18721872
{
18731873
in: "for i in 1 2 3; { echo; }",
1874-
posix: `1:17: for loops with braces are a bash/mksh feature`,
1874+
posix: `1:17: for loops with braces are a bash/mksh feature; tried parsing as posix`,
18751875
},
18761876
{
18771877
in: "for ((i=0; i<5; i++)); do echo; done",
1878-
posix: `1:5: c-style fors are a bash feature`,
1879-
mksh: `1:5: c-style fors are a bash feature`,
1878+
posix: `1:5: c-style fors are a bash feature; tried parsing as posix`,
1879+
mksh: `1:5: c-style fors are a bash feature; tried parsing as mksh`,
18801880
},
18811881
{
18821882
in: "echo !(a)",
1883-
posix: `1:6: extended globs are a bash/mksh feature`,
1883+
posix: `1:6: extended globs are a bash/mksh feature; tried parsing as posix`,
18841884
},
18851885
{
18861886
in: "echo $a@(b)",
1887-
posix: `1:8: extended globs are a bash/mksh feature`,
1887+
posix: `1:8: extended globs are a bash/mksh feature; tried parsing as posix`,
18881888
},
18891889
{
18901890
in: "foo=(1 2)",
1891-
posix: `1:5: arrays are a bash/mksh feature`,
1891+
posix: `1:5: arrays are a bash/mksh feature; tried parsing as posix`,
18921892
},
18931893
{
18941894
in: "a=$c\n'",
18951895
common: `2:1: reached EOF without closing quote '`,
18961896
},
18971897
{
18981898
in: "echo ${!foo}",
1899-
posix: `1:6: "${!foo}" is a bash/mksh feature`,
1899+
posix: `1:6: "${!foo}" is a bash/mksh feature; tried parsing as posix`,
19001900
},
19011901
{
19021902
in: "echo ${!foo*}",
1903-
posix: `1:6: "${!foo*}" is a bash feature`,
1904-
mksh: `1:6: "${!foo*}" is a bash feature`,
1903+
posix: `1:6: "${!foo*}" is a bash feature; tried parsing as posix`,
1904+
mksh: `1:6: "${!foo*}" is a bash feature; tried parsing as mksh`,
19051905
},
19061906
{
19071907
in: "echo ${!foo@}",
1908-
posix: `1:12: this expansion operator is a bash/mksh feature`,
1909-
mksh: `1:6: "${!foo@}" is a bash feature`,
1908+
posix: `1:12: this expansion operator is a bash/mksh feature; tried parsing as posix`,
1909+
mksh: `1:6: "${!foo@}" is a bash feature; tried parsing as mksh`,
19101910
},
19111911
{
19121912
in: "echo ${!foo[@]}",
1913-
posix: `1:12: arrays are a bash/mksh feature`,
1913+
posix: `1:12: arrays are a bash/mksh feature; tried parsing as posix`,
19141914
},
19151915
{
19161916
in: "echo ${foo[1]}",
1917-
posix: `1:11: arrays are a bash/mksh feature`,
1917+
posix: `1:11: arrays are a bash/mksh feature; tried parsing as posix`,
19181918
},
19191919
{
19201920
in: "echo ${foo/a/b}",
1921-
posix: `1:11: search and replace is a bash/mksh feature`,
1921+
posix: `1:11: search and replace is a bash/mksh feature; tried parsing as posix`,
19221922
},
19231923
{
19241924
in: "echo ${foo:1}",
1925-
posix: `1:11: slicing is a bash/mksh feature`,
1925+
posix: `1:11: slicing is a bash/mksh feature; tried parsing as posix`,
19261926
},
19271927
{
19281928
in: "foo <<< bar",
1929-
posix: `1:5: herestrings are a bash/mksh feature`,
1929+
posix: `1:5: herestrings are a bash/mksh feature; tried parsing as posix`,
19301930
},
19311931
{
19321932
in: "foo << < bar",
19331933
posix: `1:5: << must be followed by a word`,
19341934
},
19351935
{
19361936
in: "echo ${foo,bar}",
1937-
posix: `1:11: this expansion operator is a bash feature`,
1938-
mksh: `1:11: this expansion operator is a bash feature`,
1937+
posix: `1:11: this expansion operator is a bash feature; tried parsing as posix`,
1938+
mksh: `1:11: this expansion operator is a bash feature; tried parsing as mksh`,
19391939
},
19401940
{
19411941
in: "echo ${foo@Q}",
1942-
posix: `1:11: this expansion operator is a bash/mksh feature`,
1942+
posix: `1:11: this expansion operator is a bash/mksh feature; tried parsing as posix`,
19431943
},
19441944
{
19451945
in: "echo ${foo@a}",
1946-
mksh: `1:12: this expansion operator is a bash feature`,
1946+
mksh: `1:12: this expansion operator is a bash feature; tried parsing as mksh`,
19471947
},
19481948
{
19491949
in: "echo ${foo@u}",
1950-
mksh: `1:12: this expansion operator is a bash feature`,
1950+
mksh: `1:12: this expansion operator is a bash feature; tried parsing as mksh`,
19511951
},
19521952
{
19531953
in: "echo ${foo@A}",
1954-
mksh: `1:12: this expansion operator is a bash feature`,
1954+
mksh: `1:12: this expansion operator is a bash feature; tried parsing as mksh`,
19551955
},
19561956
{
19571957
in: "echo ${foo@E}",
1958-
mksh: `1:12: this expansion operator is a bash feature`,
1958+
mksh: `1:12: this expansion operator is a bash feature; tried parsing as mksh`,
19591959
},
19601960
{
19611961
in: "echo ${foo@K}",
1962-
mksh: `1:12: this expansion operator is a bash feature`,
1962+
mksh: `1:12: this expansion operator is a bash feature; tried parsing as mksh`,
19631963
},
19641964
{
19651965
in: "echo ${foo@k}",
1966-
mksh: `1:12: this expansion operator is a bash feature`,
1966+
mksh: `1:12: this expansion operator is a bash feature; tried parsing as mksh`,
19671967
},
19681968
{
19691969
in: "echo ${foo@L}",
1970-
mksh: `1:12: this expansion operator is a bash feature`,
1970+
mksh: `1:12: this expansion operator is a bash feature; tried parsing as mksh`,
19711971
},
19721972
{
19731973
in: "echo ${foo@P}",
1974-
mksh: `1:12: this expansion operator is a bash feature`,
1974+
mksh: `1:12: this expansion operator is a bash feature; tried parsing as mksh`,
19751975
},
19761976
{
19771977
in: "echo ${foo@U}",
1978-
mksh: `1:12: this expansion operator is a bash feature`,
1978+
mksh: `1:12: this expansion operator is a bash feature; tried parsing as mksh`,
19791979
},
19801980
{
19811981
in: "echo ${foo@#}",
1982-
bash: `1:12: this expansion operator is a mksh feature #NOERR`,
1982+
bash: `1:12: this expansion operator is a mksh feature; tried parsing as bash #NOERR`,
19831983
},
19841984
{
19851985
in: "`\"`\\",
@@ -1992,6 +1992,7 @@ func checkError(p *Parser, in, want string) func(*testing.T) {
19921992
if i := strings.Index(want, " #NOERR"); i >= 0 {
19931993
want = want[:i]
19941994
}
1995+
want = strings.Replace(want, "LANG", p.lang.String(), 1)
19951996
_, err := p.Parse(newStrictReader(in), "")
19961997
if err == nil {
19971998
t.Fatalf("Expected error in %q: %v", in, want)

0 commit comments

Comments
 (0)