github.com/myhau/pulumi/pkg/v3@v3.70.2-0.20221116134521-f2775972e587/codegen/hcl2/model/printer.go (about) 1 // Copyright 2016-2020, Pulumi Corporation. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package model 16 17 import ( 18 "fmt" 19 "io" 20 21 "github.com/hashicorp/hcl/v2/hclsyntax" 22 23 "github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/syntax" 24 ) 25 26 type printable interface { 27 print(w io.Writer, p *printer) 28 29 // HasLeadingTrivia returns true if the value has associated leading trivia. 30 HasLeadingTrivia() bool 31 // HasTrailingTrivia returns true if the value has associated trailing trivia. 32 HasTrailingTrivia() bool 33 // GetLeadingTrivia returns the leading trivia for this value, if any. 34 GetLeadingTrivia() syntax.TriviaList 35 // GetTrailingTrivia returns the trailing trivia for this value, if any. 36 GetTrailingTrivia() syntax.TriviaList 37 } 38 39 type printer struct { 40 indent string 41 } 42 43 type formatter func(f fmt.State, c rune) 44 45 func (fn formatter) Format(f fmt.State, c rune) { 46 fn(f, c) 47 } 48 49 func (p *printer) indented(f func()) { 50 p.indent += " " 51 f() 52 p.indent = p.indent[:len(p.indent)-4] 53 } 54 55 func (p *printer) format(f fmt.State, c rune, pp printable) { 56 if f.Flag(' ') && !pp.HasLeadingTrivia() { 57 switch pp.(type) { 58 case BodyItem: 59 p.fprintf(f, "%s", p.indent) 60 case Expression: 61 p.fprintf(f, " ") 62 } 63 } 64 65 parentPrecedence, hasPrecedence := f.Precision() 66 if !hasPrecedence { 67 pp.print(f, p) 68 return 69 } 70 71 var operator *hclsyntax.Operation 72 switch pp := pp.(type) { 73 case *BinaryOpExpression: 74 operator = pp.Operation 75 case *UnaryOpExpression: 76 operator = pp.Operation 77 } 78 79 precedence := operatorPrecedence(operator) 80 switch { 81 case precedence < parentPrecedence || (precedence == parentPrecedence && c == 'o'): 82 p.fprintf(f, "(") 83 pp.print(f, p) 84 p.fprintf(f, ")") 85 default: 86 pp.print(f, p) 87 } 88 } 89 90 func (p *printer) fprintf(w io.Writer, f string, v ...interface{}) { 91 for i, e := range v { 92 if printable, ok := e.(printable); ok { 93 v[i] = formatter(func(f fmt.State, c rune) { 94 p.format(f, c, printable) 95 }) 96 } 97 } 98 99 if _, err := fmt.Fprintf(w, f, v...); err != nil { 100 panic(err) 101 } 102 }