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  }