mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-12-26 23:10:22 +00:00
5a66991bb3
updating the kubernetes release to the latest in main go.mod Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
310 lines
6.4 KiB
Go
310 lines
6.4 KiB
Go
// Copyright 2018 Google LLC
|
|
//
|
|
// 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 debug provides tools to print a parsed expression graph and
|
|
// adorn each expression element with additional metadata.
|
|
package debug
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/google/cel-go/common/ast"
|
|
"github.com/google/cel-go/common/types"
|
|
"github.com/google/cel-go/common/types/ref"
|
|
)
|
|
|
|
// Adorner returns debug metadata that will be tacked on to the string
|
|
// representation of an expression.
|
|
type Adorner interface {
|
|
// GetMetadata for the input context.
|
|
GetMetadata(ctx any) string
|
|
}
|
|
|
|
// Writer manages writing expressions to an internal string.
|
|
type Writer interface {
|
|
fmt.Stringer
|
|
|
|
// Buffer pushes an expression into an internal queue of expressions to
|
|
// write to a string.
|
|
Buffer(e ast.Expr)
|
|
}
|
|
|
|
type emptyDebugAdorner struct {
|
|
}
|
|
|
|
var emptyAdorner Adorner = &emptyDebugAdorner{}
|
|
|
|
func (a *emptyDebugAdorner) GetMetadata(e any) string {
|
|
return ""
|
|
}
|
|
|
|
// ToDebugString gives the unadorned string representation of the Expr.
|
|
func ToDebugString(e ast.Expr) string {
|
|
return ToAdornedDebugString(e, emptyAdorner)
|
|
}
|
|
|
|
// ToAdornedDebugString gives the adorned string representation of the Expr.
|
|
func ToAdornedDebugString(e ast.Expr, adorner Adorner) string {
|
|
w := newDebugWriter(adorner)
|
|
w.Buffer(e)
|
|
return w.String()
|
|
}
|
|
|
|
// debugWriter is used to print out pretty-printed debug strings.
|
|
type debugWriter struct {
|
|
adorner Adorner
|
|
buffer bytes.Buffer
|
|
indent int
|
|
lineStart bool
|
|
}
|
|
|
|
func newDebugWriter(a Adorner) *debugWriter {
|
|
return &debugWriter{
|
|
adorner: a,
|
|
indent: 0,
|
|
lineStart: true,
|
|
}
|
|
}
|
|
|
|
func (w *debugWriter) Buffer(e ast.Expr) {
|
|
if e == nil {
|
|
return
|
|
}
|
|
switch e.Kind() {
|
|
case ast.LiteralKind:
|
|
w.append(formatLiteral(e.AsLiteral()))
|
|
case ast.IdentKind:
|
|
w.append(e.AsIdent())
|
|
case ast.SelectKind:
|
|
w.appendSelect(e.AsSelect())
|
|
case ast.CallKind:
|
|
w.appendCall(e.AsCall())
|
|
case ast.ListKind:
|
|
w.appendList(e.AsList())
|
|
case ast.MapKind:
|
|
w.appendMap(e.AsMap())
|
|
case ast.StructKind:
|
|
w.appendStruct(e.AsStruct())
|
|
case ast.ComprehensionKind:
|
|
w.appendComprehension(e.AsComprehension())
|
|
}
|
|
w.adorn(e)
|
|
}
|
|
|
|
func (w *debugWriter) appendSelect(sel ast.SelectExpr) {
|
|
w.Buffer(sel.Operand())
|
|
w.append(".")
|
|
w.append(sel.FieldName())
|
|
if sel.IsTestOnly() {
|
|
w.append("~test-only~")
|
|
}
|
|
}
|
|
|
|
func (w *debugWriter) appendCall(call ast.CallExpr) {
|
|
if call.IsMemberFunction() {
|
|
w.Buffer(call.Target())
|
|
w.append(".")
|
|
}
|
|
w.append(call.FunctionName())
|
|
w.append("(")
|
|
if len(call.Args()) > 0 {
|
|
w.addIndent()
|
|
w.appendLine()
|
|
for i, arg := range call.Args() {
|
|
if i > 0 {
|
|
w.append(",")
|
|
w.appendLine()
|
|
}
|
|
w.Buffer(arg)
|
|
}
|
|
w.removeIndent()
|
|
w.appendLine()
|
|
}
|
|
w.append(")")
|
|
}
|
|
|
|
func (w *debugWriter) appendList(list ast.ListExpr) {
|
|
w.append("[")
|
|
if len(list.Elements()) > 0 {
|
|
w.appendLine()
|
|
w.addIndent()
|
|
for i, elem := range list.Elements() {
|
|
if i > 0 {
|
|
w.append(",")
|
|
w.appendLine()
|
|
}
|
|
w.Buffer(elem)
|
|
}
|
|
w.removeIndent()
|
|
w.appendLine()
|
|
}
|
|
w.append("]")
|
|
}
|
|
|
|
func (w *debugWriter) appendStruct(obj ast.StructExpr) {
|
|
w.append(obj.TypeName())
|
|
w.append("{")
|
|
if len(obj.Fields()) > 0 {
|
|
w.appendLine()
|
|
w.addIndent()
|
|
for i, f := range obj.Fields() {
|
|
field := f.AsStructField()
|
|
if i > 0 {
|
|
w.append(",")
|
|
w.appendLine()
|
|
}
|
|
if field.IsOptional() {
|
|
w.append("?")
|
|
}
|
|
w.append(field.Name())
|
|
w.append(":")
|
|
w.Buffer(field.Value())
|
|
w.adorn(f)
|
|
}
|
|
w.removeIndent()
|
|
w.appendLine()
|
|
}
|
|
w.append("}")
|
|
}
|
|
|
|
func (w *debugWriter) appendMap(m ast.MapExpr) {
|
|
w.append("{")
|
|
if m.Size() > 0 {
|
|
w.appendLine()
|
|
w.addIndent()
|
|
for i, e := range m.Entries() {
|
|
entry := e.AsMapEntry()
|
|
if i > 0 {
|
|
w.append(",")
|
|
w.appendLine()
|
|
}
|
|
if entry.IsOptional() {
|
|
w.append("?")
|
|
}
|
|
w.Buffer(entry.Key())
|
|
w.append(":")
|
|
w.Buffer(entry.Value())
|
|
w.adorn(e)
|
|
}
|
|
w.removeIndent()
|
|
w.appendLine()
|
|
}
|
|
w.append("}")
|
|
}
|
|
|
|
func (w *debugWriter) appendComprehension(comprehension ast.ComprehensionExpr) {
|
|
w.append("__comprehension__(")
|
|
w.addIndent()
|
|
w.appendLine()
|
|
w.append("// Variable")
|
|
w.appendLine()
|
|
w.append(comprehension.IterVar())
|
|
w.append(",")
|
|
w.appendLine()
|
|
w.append("// Target")
|
|
w.appendLine()
|
|
w.Buffer(comprehension.IterRange())
|
|
w.append(",")
|
|
w.appendLine()
|
|
w.append("// Accumulator")
|
|
w.appendLine()
|
|
w.append(comprehension.AccuVar())
|
|
w.append(",")
|
|
w.appendLine()
|
|
w.append("// Init")
|
|
w.appendLine()
|
|
w.Buffer(comprehension.AccuInit())
|
|
w.append(",")
|
|
w.appendLine()
|
|
w.append("// LoopCondition")
|
|
w.appendLine()
|
|
w.Buffer(comprehension.LoopCondition())
|
|
w.append(",")
|
|
w.appendLine()
|
|
w.append("// LoopStep")
|
|
w.appendLine()
|
|
w.Buffer(comprehension.LoopStep())
|
|
w.append(",")
|
|
w.appendLine()
|
|
w.append("// Result")
|
|
w.appendLine()
|
|
w.Buffer(comprehension.Result())
|
|
w.append(")")
|
|
w.removeIndent()
|
|
}
|
|
|
|
func formatLiteral(c ref.Val) string {
|
|
switch v := c.(type) {
|
|
case types.Bool:
|
|
return fmt.Sprintf("%t", v)
|
|
case types.Bytes:
|
|
return fmt.Sprintf("b\"%s\"", string(v))
|
|
case types.Double:
|
|
return fmt.Sprintf("%v", float64(v))
|
|
case types.Int:
|
|
return fmt.Sprintf("%d", int64(v))
|
|
case types.String:
|
|
return strconv.Quote(string(v))
|
|
case types.Uint:
|
|
return fmt.Sprintf("%du", uint64(v))
|
|
case types.Null:
|
|
return "null"
|
|
default:
|
|
panic("Unknown constant type")
|
|
}
|
|
}
|
|
|
|
func (w *debugWriter) append(s string) {
|
|
w.doIndent()
|
|
w.buffer.WriteString(s)
|
|
}
|
|
|
|
func (w *debugWriter) appendFormat(f string, args ...any) {
|
|
w.append(fmt.Sprintf(f, args...))
|
|
}
|
|
|
|
func (w *debugWriter) doIndent() {
|
|
if w.lineStart {
|
|
w.lineStart = false
|
|
w.buffer.WriteString(strings.Repeat(" ", w.indent))
|
|
}
|
|
}
|
|
|
|
func (w *debugWriter) adorn(e any) {
|
|
w.append(w.adorner.GetMetadata(e))
|
|
}
|
|
|
|
func (w *debugWriter) appendLine() {
|
|
w.buffer.WriteString("\n")
|
|
w.lineStart = true
|
|
}
|
|
|
|
func (w *debugWriter) addIndent() {
|
|
w.indent++
|
|
}
|
|
|
|
func (w *debugWriter) removeIndent() {
|
|
w.indent--
|
|
if w.indent < 0 {
|
|
panic("negative indent")
|
|
}
|
|
}
|
|
|
|
func (w *debugWriter) String() string {
|
|
return w.buffer.String()
|
|
}
|