tools/fix: eliminate x & _ and unnecessary parens
Change-Id: I4612a0578703d7b13328d052ad6bae85c46cf69c
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8302
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/tools/fix/fix.go b/tools/fix/fix.go
index b464270..1e814fb 100644
--- a/tools/fix/fix.go
+++ b/tools/fix/fix.go
@@ -31,7 +31,8 @@
type Option func(*options)
type options struct {
- simplify bool
+ simplify bool
+ deprecated bool
}
// Simplify enables fixes that simplify the code, but are not strictly
@@ -265,38 +266,9 @@
// return true
// }, nil).(*ast.File)
- if !options.simplify {
- return f
+ if options.simplify {
+ f = simplify(f)
}
- // Rewrite disjunctions with _ to _.
- f = astutil.Apply(f, func(c astutil.Cursor) bool {
- if x := findTop(c.Node()); x != nil {
- c.Replace(x)
- }
- return true
- }, nil).(*ast.File)
-
return f
}
-
-func findTop(x ast.Node) ast.Expr {
- switch x := x.(type) {
- case *ast.BinaryExpr:
- if x.Op != token.OR {
- break
- }
- if v := findTop(x.X); v != nil {
- return v
- }
- if v := findTop(x.Y); v != nil {
- return v
- }
-
- case *ast.Ident:
- if x.Name == "_" {
- return x
- }
- }
- return nil
-}
diff --git a/tools/fix/fix_test.go b/tools/fix/fix_test.go
index 63f7f99..3f251ac 100644
--- a/tools/fix/fix_test.go
+++ b/tools/fix/fix_test.go
@@ -89,9 +89,19 @@
}, {
simplify: true,
in: `
- y: _ | {[string]: int}
+ x1: 3 & _
+ x2: _ | {[string]: int}
+ x3: 4 & (9 | _)
+ x4: (_ | 9) & 4
+ x5: (_ & 9) & 4
+ x6: 4 & (_ & 9)
`,
- out: `y: _
+ out: `x1: 3
+x2: _
+x3: 4
+x4: 4
+x5: 9 & 4
+x6: 4 & 9
`,
// }, {
diff --git a/tools/fix/simplify.go b/tools/fix/simplify.go
new file mode 100644
index 0000000..623d5c3
--- /dev/null
+++ b/tools/fix/simplify.go
@@ -0,0 +1,73 @@
+// Copyright 2021 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package fix
+
+import (
+ "cuelang.org/go/cue/ast"
+ "cuelang.org/go/cue/ast/astutil"
+ "cuelang.org/go/cue/token"
+)
+
+func simplify(f *ast.File) *ast.File {
+ // Rewrite disjunctions with _ to _.
+ f = astutil.Apply(f, nil, func(c astutil.Cursor) bool {
+ if x, ok := c.Node().(ast.Expr); ok {
+ if y := elideTop(x); x != y {
+ c.Replace(y)
+ }
+ }
+ return true
+ }).(*ast.File)
+
+ return f
+}
+
+func elideTop(x ast.Expr) ast.Expr {
+ switch x := x.(type) {
+ case *ast.BinaryExpr:
+ switch x.Op {
+ case token.OR:
+ if isTop(x.X) {
+ return x.X
+ }
+ if isTop(x.Y) {
+ ast.SetRelPos(x.Y, token.NoRelPos)
+ return x.Y
+ }
+
+ case token.AND:
+ if isTop(x.X) {
+ ast.SetRelPos(x.Y, token.NoRelPos)
+ return x.Y
+ }
+ if isTop(x.Y) {
+ return x.X
+ }
+ }
+
+ case *ast.ParenExpr:
+ switch x.X.(type) {
+ case *ast.BinaryExpr, *ast.UnaryExpr:
+ default:
+ return x.X
+ }
+ }
+ return x
+}
+
+func isTop(x ast.Expr) bool {
+ v, ok := x.(*ast.Ident)
+ return ok && v.Name == "_"
+}