this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cue: remove all support for quoted identifiers

Note that QuoteIdent has now been removed alltogether.

Affected packages:
- cue/scanner
- cue/parser
- cue/ast
- tools/fix
- faulty spec reference

Fixes #1475

Signed-off-by: Marcel van Lohuizen <mpvl@golang.org>

Change-Id: Ide35cb383bc303955eef516928a7e1e5d0602fc7
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/531206
Unity-Result: CUEcueckoo <cueckoo@cuelang.org>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Paul Jolly <paul@myitcv.io>

authored by

Marcel van Lohuizen and committed by
Marcel van Lohuizen
a7eda136 6bc922c8

+3 -196
-32
cue/ast/ident.go
··· 68 68 return true 69 69 } 70 70 71 - // QuoteIdent quotes an identifier, if needed, and reports 72 - // an error if the identifier is invalid. 73 - // 74 - // Deprecated: quoted identifiers are deprecated. Use aliases. 75 - func QuoteIdent(ident string) (string, error) { 76 - if ident != "" && ident[0] == '`' { 77 - if _, err := strconv.Unquote(ident); err != nil { 78 - return "", errors.Newf(token.NoPos, "invalid quoted identifier %q", ident) 79 - } 80 - return ident, nil 81 - } 82 - 83 - // TODO: consider quoting keywords 84 - // switch ident { 85 - // case "for", "in", "if", "let", "true", "false", "null": 86 - // goto escape 87 - // } 88 - 89 - for _, r := range ident { 90 - if isLetter(r) || isDigit(r) || r == '_' || r == '$' { 91 - continue 92 - } 93 - if r == '-' { 94 - return "`" + ident + "`", nil 95 - } 96 - return "", errors.Newf(token.NoPos, "invalid character '%s' in identifier", string(r)) 97 - } 98 - 99 - _, err := parseIdent(token.NoPos, ident) 100 - return ident, err 101 - } 102 - 103 71 // ParseIdent unquotes a possibly quoted identifier and validates 104 72 // if the result is valid. 105 73 //
-4
cue/parser/parser.go
··· 388 388 p.comments.add(comment) 389 389 } 390 390 } 391 - 392 - if p.tok == token.IDENT && p.lit[0] == '`' { 393 - p.assertV0(p.pos, 0, 13, "quoted identifiers") 394 - } 395 391 } 396 392 397 393 // assertV0 indicates the last version at which a certain feature was
-30
cue/scanner/scanner.go
··· 296 296 return strings.IndexRune("-_#$%. ", r) >= 0 297 297 } 298 298 299 - func (s *Scanner) scanQuotedIdentifier() string { 300 - offs := s.offset - 1 // quote already consumed 301 - hasInvalid := false 302 - for ; ; s.next() { 303 - switch { 304 - default: 305 - if !hasInvalid { 306 - s.errf(s.offset, "invalid character '%s' in identifier", string(s.ch)) 307 - hasInvalid = true 308 - } 309 - continue 310 - 311 - case isLetter(s.ch) || isDigit(s.ch) || isExtendedIdent(s.ch): 312 - continue 313 - 314 - case s.ch == '`': 315 - s.next() 316 - return string(s.src[offs:s.offset]) 317 - 318 - case s.ch == '\n': 319 - s.errf(s.offset, "quoted identifier not terminated") 320 - return string(s.src[offs:s.offset]) 321 - } 322 - } 323 - } 324 - 325 299 func digitVal(ch rune) int { 326 300 switch { 327 301 case '0' <= ch && ch <= '9': ··· 820 794 tok = token.IDENT 821 795 lit = "_" + s.scanFieldIdentifier() 822 796 } 823 - insertEOL = true 824 - case '`': 825 - tok = token.IDENT 826 - lit = s.scanQuotedIdentifier() 827 797 insertEOL = true 828 798 829 799 case '\n':
+3 -4
cue/scanner/scanner_test.go
··· 85 85 {token.IDENT, "#_foobar", literal}, 86 86 {token.IDENT, "_#foobar", literal}, 87 87 {token.IDENT, "__#foobar", literal}, 88 - {token.IDENT, "`foobar`", literal}, 89 88 {token.IDENT, "a۰۱۸", literal}, 90 89 {token.IDENT, "foo६४", literal}, 91 90 {token.IDENT, "bar9876", literal}, ··· 739 738 lit string 740 739 err string 741 740 }{ 741 + {"`", token.ILLEGAL, 0, "", "illegal character U+0060 '`'"}, 742 + 742 743 {"\a", token.ILLEGAL, 0, "", "illegal character U+0007"}, 743 744 {`^`, token.ILLEGAL, 0, "", "illegal character U+005E '^'"}, 744 745 {`…`, token.ILLEGAL, 0, "", "illegal character U+2026 '…'"}, 745 746 {`_|`, token.ILLEGAL, 0, "", "illegal token '_|'; expected '_'"}, 746 - 747 - {"`foo=bar`", token.IDENT, 4, "`foo=bar`", "invalid character '=' in identifier"}, 748 - {"`foo\nbar`", token.IDENT, 4, "`foo", "quoted identifier not terminated"}, 749 747 750 748 {`@`, token.ATTRIBUTE, 1, `@`, "invalid attribute: expected '('"}, 751 749 {`@foo`, token.ATTRIBUTE, 4, `@foo`, "invalid attribute: expected '('"}, ··· 784 782 {`"\U00000000"`, token.STRING, 0, `"\U00000000"`, ""}, 785 783 {`"\Uffffffff"`, token.STRING, 2, `"\Uffffffff"`, "escape sequence is invalid Unicode code point"}, 786 784 {`'`, token.STRING, 0, `'`, "string literal not terminated"}, 785 + {`"`, token.STRING, 0, `"`, "string literal not terminated"}, 787 786 {`""`, token.STRING, 0, `""`, ""}, 788 787 {`"abc`, token.STRING, 0, `"abc`, "string literal not terminated"}, 789 788 {`""abc`, token.STRING, 0, `""`, ""},
-7
cue/testdata/resolve/003_resolution_of_quoted_identifiers.txtar
··· 1 - # DO NOT EDIT; generated by go run testdata/gen.go 2 - # 3 - #name: resolution of quoted identifiers 4 - #skip 5 - #evalPartial 6 - -- out/legacy-debug -- 7 - <0>{"foo-bar": 2, baz: 2, a: <1>{qux: 3, "qux-quux": 3, qaz: 3}}
-1
doc/ref/spec.md
··· 484 484 ``` 485 485 "日本語" // UTF-8 input text 486 486 '日本語' // UTF-8 input text as byte sequence 487 - `日本語` // UTF-8 input text as a raw literal 488 487 "\u65e5\u672c\u8a9e" // the explicit Unicode code points 489 488 "\U000065e5\U0000672c\U00008a9e" // the explicit Unicode code points 490 489 '\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e' // the explicit UTF-8 bytes
-90
tools/fix/fix.go
··· 20 20 package fix 21 21 22 22 import ( 23 - "fmt" 24 23 "strings" 25 24 26 25 "cuelang.org/go/cue/ast" ··· 118 117 } 119 118 x.List = comments 120 119 return false 121 - } 122 - return true 123 - }, nil) 124 - 125 - // Referred nodes and used identifiers. 126 - referred := map[ast.Node]string{} 127 - used := map[string]bool{} 128 - replacement := map[ast.Node]string{} 129 - 130 - ast.Walk(f, func(n ast.Node) bool { 131 - if i, ok := n.(*ast.Ident); ok { 132 - str, err := ast.ParseIdent(i) 133 - if err != nil { 134 - return false 135 - } 136 - referred[i.Node] = str 137 - used[str] = true 138 - } 139 - return true 140 - }, nil) 141 - 142 - num := 0 143 - newIdent := func() string { 144 - for num++; ; num++ { 145 - str := fmt.Sprintf("X%d", num) 146 - if !used[str] { 147 - used[str] = true 148 - return str 149 - } 150 - } 151 - } 152 - 153 - // Rewrite quoted identifier fields that are referenced. 154 - f = astutil.Apply(f, func(c astutil.Cursor) bool { 155 - n := c.Node() 156 - switch x := n.(type) { 157 - case *ast.Field: 158 - m, ok := referred[x.Value] 159 - if !ok { 160 - break 161 - } 162 - 163 - if b, ok := x.Label.(*ast.Ident); ok { 164 - str, err := ast.ParseIdent(b) 165 - var expr ast.Expr = b 166 - 167 - switch { 168 - case token.Lookup(str) != token.IDENT: 169 - // quote keywords 170 - expr = ast.NewString(b.Name) 171 - 172 - case err != nil || str != m || str == b.Name: 173 - return true 174 - 175 - case ast.IsValidIdent(str): 176 - x.Label = astutil.CopyMeta(ast.NewIdent(str), x.Label).(ast.Label) 177 - return true 178 - } 179 - 180 - ident := newIdent() 181 - replacement[x.Value] = ident 182 - expr = &ast.Alias{Ident: ast.NewIdent(ident), Expr: expr} 183 - ast.SetRelPos(x.Label, token.NoRelPos) 184 - x.Label = astutil.CopyMeta(expr, x.Label).(ast.Label) 185 - } 186 - } 187 - return true 188 - }, nil).(*ast.File) 189 - 190 - // Replace quoted references with their alias identifier. 191 - astutil.Apply(f, func(c astutil.Cursor) bool { 192 - n := c.Node() 193 - switch x := n.(type) { 194 - case *ast.Ident: 195 - if r, ok := replacement[x.Node]; ok { 196 - c.Replace(astutil.CopyMeta(ast.NewIdent(r), n)) 197 - break 198 - } 199 - str, err := ast.ParseIdent(x) 200 - if err != nil || str == x.Name { 201 - break 202 - } 203 - // Either the identifier is valid, in which can be replaced simply 204 - // as here, or it is a complicated identifier and the original 205 - // destination must have been quoted, in which case it is handled 206 - // above. 207 - if ast.IsValidIdent(str) && token.Lookup(str) == token.IDENT { 208 - c.Replace(astutil.CopyMeta(ast.NewIdent(str), n)) 209 - } 210 120 } 211 121 return true 212 122 }, nil)
-28
tools/fix/fix_test.go
··· 44 44 d: __rem(1.0, 1.0) // pass on illegal values. 45 45 `, 46 46 }, { 47 - name: "referenced quoted fields", 48 - in: `package foo 49 - 50 - a: { 51 - fiz: 4 52 - faz: ` + "`fiz`" + ` 53 - 54 - // biz 55 - ` + "`biz`" + `: 5 // biz 56 - buz: ` + "`biz`" + ` 57 - in: 3 58 - ref: ` + "`in`" + ` & x 59 - } 60 - `, 61 - out: `package foo 62 - 63 - a: { 64 - fiz: 4 65 - faz: fiz 66 - 67 - // biz 68 - biz: 5 // biz 69 - buz: biz 70 - X1="in": 3 71 - ref: X1 & x 72 - } 73 - `, 74 - }, { 75 47 in: ` 76 48 y = foo 77 49 `,