github.com/myhau/pulumi/pkg/v3@v3.70.2-0.20221116134521-f2775972e587/codegen/hcl2/model/expression.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 "math/big" 21 "strconv" 22 23 "github.com/hashicorp/hcl/v2" 24 "github.com/hashicorp/hcl/v2/hclsyntax" 25 "github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/syntax" 26 "github.com/pulumi/pulumi/sdk/v3/go/common/util/contract" 27 "github.com/zclconf/go-cty/cty" 28 "github.com/zclconf/go-cty/cty/convert" 29 ) 30 31 // Expression represents a semantically-analyzed HCL2 expression. 32 type Expression interface { 33 printable 34 35 // SyntaxNode returns the hclsyntax.Node associated with the expression. 36 SyntaxNode() hclsyntax.Node 37 // NodeTokens returns the syntax.Tokens associated with the expression. 38 NodeTokens() syntax.NodeTokens 39 40 // SetLeadingTrivia sets the leading trivia associated with the expression. 41 SetLeadingTrivia(syntax.TriviaList) 42 // SetTrailingTrivia sets the trailing trivia associated with the expression. 43 SetTrailingTrivia(syntax.TriviaList) 44 45 // Type returns the type of the expression. 46 Type() Type 47 // Typecheck recomputes the type of the expression, optionally typechecking its operands first. 48 Typecheck(typecheckOperands bool) hcl.Diagnostics 49 50 // Evaluate evaluates the expression. 51 Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) 52 53 isExpression() 54 } 55 56 func identToken(token syntax.Token, ident string) syntax.Token { 57 if string(token.Raw.Bytes) != ident { 58 token.Raw.Bytes = []byte(ident) 59 } 60 return token 61 } 62 63 func exprHasLeadingTrivia(parens syntax.Parentheses, first interface{}) bool { 64 if parens.Any() { 65 return true 66 } 67 switch first := first.(type) { 68 case Expression: 69 return first.HasLeadingTrivia() 70 case bool: 71 return first 72 default: 73 contract.Failf("unexpected value of type %T for first", first) 74 return false 75 } 76 } 77 78 func exprHasTrailingTrivia(parens syntax.Parentheses, last interface{}) bool { 79 if parens.Any() { 80 return true 81 } 82 switch last := last.(type) { 83 case Expression: 84 return last.HasTrailingTrivia() 85 case bool: 86 return last 87 default: 88 contract.Failf("unexpected value of type %T for last", last) 89 return false 90 } 91 } 92 93 func getExprLeadingTrivia(parens syntax.Parentheses, first interface{}) syntax.TriviaList { 94 if parens.Any() { 95 return parens.GetLeadingTrivia() 96 } 97 switch first := first.(type) { 98 case Expression: 99 return first.GetLeadingTrivia() 100 case syntax.Token: 101 return first.LeadingTrivia 102 } 103 return nil 104 } 105 106 func setExprLeadingTrivia(parens syntax.Parentheses, first interface{}, trivia syntax.TriviaList) { 107 if parens.Any() { 108 parens.SetLeadingTrivia(trivia) 109 return 110 } 111 switch first := first.(type) { 112 case Expression: 113 first.SetLeadingTrivia(trivia) 114 case *syntax.Token: 115 first.LeadingTrivia = trivia 116 } 117 } 118 119 func getExprTrailingTrivia(parens syntax.Parentheses, last interface{}) syntax.TriviaList { 120 if parens.Any() { 121 return parens.GetTrailingTrivia() 122 } 123 switch last := last.(type) { 124 case Expression: 125 return last.GetTrailingTrivia() 126 case syntax.Token: 127 return last.TrailingTrivia 128 } 129 return nil 130 } 131 132 func setExprTrailingTrivia(parens syntax.Parentheses, last interface{}, trivia syntax.TriviaList) { 133 if parens.Any() { 134 parens.SetTrailingTrivia(trivia) 135 return 136 } 137 switch last := last.(type) { 138 case Expression: 139 last.SetTrailingTrivia(trivia) 140 case *syntax.Token: 141 last.TrailingTrivia = trivia 142 } 143 } 144 145 type syntaxExpr struct { 146 hclsyntax.LiteralValueExpr 147 148 expr Expression 149 } 150 151 func (x syntaxExpr) Value(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 152 return x.expr.Evaluate(context) 153 } 154 155 type hclExpression struct { 156 x Expression 157 } 158 159 func HCLExpression(x Expression) hcl.Expression { 160 return hclExpression{x: x} 161 } 162 163 func (x hclExpression) Value(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 164 return x.x.Evaluate(context) 165 } 166 167 func (x hclExpression) Variables() []hcl.Traversal { 168 var variables []hcl.Traversal 169 scope := NewRootScope(syntax.None) 170 _, diags := VisitExpression(x.x, func(n Expression) (Expression, hcl.Diagnostics) { 171 switch n := n.(type) { 172 case *AnonymousFunctionExpression: 173 scope = scope.Push(syntax.None) 174 for _, p := range n.Parameters { 175 scope.Define(p.Name, p) 176 } 177 case *ForExpression: 178 scope = scope.Push(syntax.None) 179 if n.KeyVariable != nil { 180 scope.Define(n.KeyVariable.Name, n.KeyVariable) 181 } 182 scope.Define(n.ValueVariable.Name, n.ValueVariable) 183 } 184 return n, nil 185 }, func(n Expression) (Expression, hcl.Diagnostics) { 186 switch n := n.(type) { 187 case *AnonymousFunctionExpression, *ForExpression: 188 scope = scope.Pop() 189 case *ScopeTraversalExpression: 190 if _, isSplatVariable := n.Parts[0].(*SplatVariable); !isSplatVariable { 191 if _, defined := scope.BindReference(n.RootName); !defined { 192 variables = append(variables, n.Traversal.SimpleSplit().Abs) 193 } 194 } 195 } 196 return n, nil 197 }) 198 contract.Assert(len(diags) == 0) 199 return variables 200 } 201 202 func (x hclExpression) Range() hcl.Range { 203 if syntax := x.x.SyntaxNode(); syntax != nil { 204 return syntax.Range() 205 } 206 return hcl.Range{} 207 } 208 209 func (x hclExpression) StartRange() hcl.Range { 210 if syntax := x.x.SyntaxNode(); syntax != nil { 211 return syntax.(hcl.Expression).StartRange() 212 } 213 return hcl.Range{} 214 } 215 216 func operatorPrecedence(op *hclsyntax.Operation) int { 217 switch op { 218 case hclsyntax.OpLogicalOr: 219 return 1 220 case hclsyntax.OpLogicalAnd: 221 return 2 222 case hclsyntax.OpEqual, hclsyntax.OpNotEqual: 223 return 3 224 case hclsyntax.OpGreaterThan, hclsyntax.OpGreaterThanOrEqual, hclsyntax.OpLessThan, hclsyntax.OpLessThanOrEqual: 225 return 4 226 case hclsyntax.OpAdd, hclsyntax.OpSubtract: 227 return 5 228 case hclsyntax.OpMultiply, hclsyntax.OpDivide, hclsyntax.OpModulo: 229 return 6 230 case hclsyntax.OpNegate, hclsyntax.OpLogicalNot: 231 return 7 232 default: 233 return 8 234 } 235 } 236 237 // AnonymousFunctionExpression represents a semantically-analyzed anonymous function expression. 238 // 239 // These expressions are not the result of semantically analyzing syntax nodes. Instead, they may be synthesized by 240 // transforms over the IR for a program (e.g. the Apply transform). 241 type AnonymousFunctionExpression struct { 242 // The signature for the anonymous function. 243 Signature StaticFunctionSignature 244 // The parameter definitions for the anonymous function. 245 Parameters []*Variable 246 247 // The body of the anonymous function. 248 Body Expression 249 } 250 251 // SyntaxNode returns the syntax node associated with the body of the anonymous function. 252 func (x *AnonymousFunctionExpression) SyntaxNode() hclsyntax.Node { 253 return x.Body.SyntaxNode() 254 } 255 256 // NodeTokens returns the tokens associated with the body of the anonymous function. 257 func (x *AnonymousFunctionExpression) NodeTokens() syntax.NodeTokens { 258 return x.Body.NodeTokens() 259 } 260 261 // Type returns the type of the anonymous function expression. 262 // 263 // TODO: currently this returns the any type. Instead, it should return a function type. 264 func (x *AnonymousFunctionExpression) Type() Type { 265 return DynamicType 266 } 267 268 func (x *AnonymousFunctionExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 269 var diagnostics hcl.Diagnostics 270 271 if typecheckOperands { 272 bodyDiags := x.Body.Typecheck(true) 273 diagnostics = append(diagnostics, bodyDiags...) 274 } 275 276 return diagnostics 277 } 278 279 func (x *AnonymousFunctionExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 280 return cty.NilVal, hcl.Diagnostics{cannotEvaluateAnonymousFunctionExpressions()} 281 } 282 283 func (x *AnonymousFunctionExpression) HasLeadingTrivia() bool { 284 return x.Body.HasLeadingTrivia() 285 } 286 287 func (x *AnonymousFunctionExpression) HasTrailingTrivia() bool { 288 return x.Body.HasTrailingTrivia() 289 } 290 291 func (x *AnonymousFunctionExpression) GetLeadingTrivia() syntax.TriviaList { 292 return x.Body.GetLeadingTrivia() 293 } 294 295 func (x *AnonymousFunctionExpression) SetLeadingTrivia(t syntax.TriviaList) { 296 x.Body.SetLeadingTrivia(t) 297 } 298 299 func (x *AnonymousFunctionExpression) GetTrailingTrivia() syntax.TriviaList { 300 return x.Body.GetTrailingTrivia() 301 } 302 303 func (x *AnonymousFunctionExpression) SetTrailingTrivia(t syntax.TriviaList) { 304 x.Body.SetTrailingTrivia(t) 305 } 306 307 func (x *AnonymousFunctionExpression) Format(f fmt.State, c rune) { 308 x.print(f, &printer{}) 309 } 310 311 func (x *AnonymousFunctionExpression) print(w io.Writer, p *printer) { 312 // Print a call to eval. 313 p.fprintf(w, "eval(") 314 315 // Print the parameter names. 316 for _, v := range x.Parameters { 317 p.fprintf(w, "%v, ", v.Name) 318 } 319 320 // Print the body and closing paren. 321 p.fprintf(w, "%v)", x.Body) 322 } 323 324 func (*AnonymousFunctionExpression) isExpression() {} 325 326 // BinaryOpExpression represents a semantically-analyzed binary operation. 327 type BinaryOpExpression struct { 328 // The syntax node associated with the binary operation. 329 Syntax *hclsyntax.BinaryOpExpr 330 // The tokens associated with the expression, if any. 331 Tokens *syntax.BinaryOpTokens 332 333 // The left-hand operand of the operation. 334 LeftOperand Expression 335 // The operation. 336 Operation *hclsyntax.Operation 337 // The right-hand operand of the operation. 338 RightOperand Expression 339 340 leftType Type 341 rightType Type 342 exprType Type 343 } 344 345 // SyntaxNode returns the syntax node associated with the binary operation. 346 func (x *BinaryOpExpression) SyntaxNode() hclsyntax.Node { 347 return x.Syntax 348 } 349 350 // NodeTokens returns the tokens associated with the binary operation. 351 func (x *BinaryOpExpression) NodeTokens() syntax.NodeTokens { 352 return x.Tokens 353 } 354 355 // LeftOperandType returns the desired type for the left operand of the binary operation. 356 func (x *BinaryOpExpression) LeftOperandType() Type { 357 return x.leftType 358 } 359 360 // RightOperandType returns the desired type for the right operand of the binary operation. 361 func (x *BinaryOpExpression) RightOperandType() Type { 362 return x.rightType 363 } 364 365 // Type returns the type of the binary operation. 366 func (x *BinaryOpExpression) Type() Type { 367 return x.exprType 368 } 369 370 func (x *BinaryOpExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 371 var diagnostics hcl.Diagnostics 372 373 var rng hcl.Range 374 if x.Syntax != nil { 375 rng = x.Syntax.Range() 376 } 377 378 if typecheckOperands { 379 leftDiags := x.LeftOperand.Typecheck(true) 380 diagnostics = append(diagnostics, leftDiags...) 381 382 rightDiags := x.RightOperand.Typecheck(true) 383 diagnostics = append(diagnostics, rightDiags...) 384 } 385 386 // Compute the signature for the operator and typecheck the arguments. 387 signature := getOperationSignature(x.Operation) 388 contract.Assert(len(signature.Parameters) == 2) 389 390 x.leftType = signature.Parameters[0].Type 391 x.rightType = signature.Parameters[1].Type 392 393 typecheckDiags := typecheckArgs(rng, signature, x.LeftOperand, x.RightOperand) 394 diagnostics = append(diagnostics, typecheckDiags...) 395 396 x.exprType = liftOperationType(signature.ReturnType, x.LeftOperand, x.RightOperand) 397 return diagnostics 398 } 399 400 func (x *BinaryOpExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 401 syntax := &hclsyntax.BinaryOpExpr{ 402 LHS: &syntaxExpr{expr: x.LeftOperand}, 403 Op: x.Operation, 404 RHS: &syntaxExpr{expr: x.RightOperand}, 405 } 406 return syntax.Value(context) 407 } 408 409 func (x *BinaryOpExpression) HasLeadingTrivia() bool { 410 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.LeftOperand) 411 } 412 413 func (x *BinaryOpExpression) HasTrailingTrivia() bool { 414 return exprHasTrailingTrivia(x.Tokens.GetParentheses(), x.RightOperand) 415 } 416 417 func (x *BinaryOpExpression) GetLeadingTrivia() syntax.TriviaList { 418 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.LeftOperand) 419 } 420 421 func (x *BinaryOpExpression) SetLeadingTrivia(t syntax.TriviaList) { 422 setExprLeadingTrivia(x.Tokens.GetParentheses(), x.LeftOperand, t) 423 } 424 425 func (x *BinaryOpExpression) GetTrailingTrivia() syntax.TriviaList { 426 return getExprTrailingTrivia(x.Tokens.GetParentheses(), x.RightOperand) 427 } 428 429 func (x *BinaryOpExpression) SetTrailingTrivia(t syntax.TriviaList) { 430 if x.Tokens == nil { 431 x.Tokens = syntax.NewBinaryOpTokens(x.Operation) 432 } 433 setExprTrailingTrivia(x.Tokens.GetParentheses(), x.RightOperand, t) 434 } 435 436 func (x *BinaryOpExpression) Format(f fmt.State, c rune) { 437 x.print(f, &printer{}) 438 } 439 440 func (x *BinaryOpExpression) print(w io.Writer, p *printer) { 441 precedence := operatorPrecedence(x.Operation) 442 p.fprintf(w, "%[2](%.[1]*[3]v% [4]v% .[1]*[5]o%[6])", 443 precedence, 444 x.Tokens.GetParentheses(), 445 x.LeftOperand, x.Tokens.GetOperator(x.Operation), x.RightOperand, 446 x.Tokens.GetParentheses()) 447 } 448 449 func (*BinaryOpExpression) isExpression() {} 450 451 // ConditionalExpression represents a semantically-analzed conditional expression (i.e. 452 // <condition> '?' <true> ':' <false>). 453 type ConditionalExpression struct { 454 // The syntax node associated with the conditional expression. 455 Syntax *hclsyntax.ConditionalExpr 456 // The tokens associated with the expression, if any. 457 Tokens syntax.NodeTokens 458 459 // The condition. 460 Condition Expression 461 // The result of the expression if the condition evaluates to true. 462 TrueResult Expression 463 // The result of the expression if the condition evaluates to false. 464 FalseResult Expression 465 466 exprType Type 467 } 468 469 // SyntaxNode returns the syntax node associated with the conditional expression. 470 func (x *ConditionalExpression) SyntaxNode() hclsyntax.Node { 471 return x.Syntax 472 } 473 474 // NodeTokens returns the tokens associated with the conditional expression. 475 func (x *ConditionalExpression) NodeTokens() syntax.NodeTokens { 476 return x.Tokens 477 } 478 479 // Type returns the type of the conditional expression. 480 func (x *ConditionalExpression) Type() Type { 481 return x.exprType 482 } 483 484 func (x *ConditionalExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 485 var diagnostics hcl.Diagnostics 486 487 if typecheckOperands { 488 conditionDiags := x.Condition.Typecheck(true) 489 diagnostics = append(diagnostics, conditionDiags...) 490 491 trueDiags := x.TrueResult.Typecheck(true) 492 diagnostics = append(diagnostics, trueDiags...) 493 494 falseDiags := x.FalseResult.Typecheck(true) 495 diagnostics = append(diagnostics, falseDiags...) 496 } 497 498 // Compute the type of the result. 499 resultType, _ := UnifyTypes(x.TrueResult.Type(), x.FalseResult.Type()) 500 501 // Typecheck the condition expression. 502 if InputType(BoolType).ConversionFrom(x.Condition.Type()) == NoConversion { 503 diagnostics = append(diagnostics, ExprNotConvertible(InputType(BoolType), x.Condition)) 504 } 505 506 x.exprType = liftOperationType(resultType, x.Condition) 507 return diagnostics 508 } 509 510 func (x *ConditionalExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 511 syntax := &hclsyntax.ConditionalExpr{ 512 Condition: &syntaxExpr{expr: x.Condition}, 513 TrueResult: &syntaxExpr{expr: x.TrueResult}, 514 FalseResult: &syntaxExpr{expr: x.FalseResult}, 515 } 516 return syntax.Value(context) 517 } 518 519 func (x *ConditionalExpression) HasLeadingTrivia() bool { 520 switch tokens := x.Tokens.(type) { 521 case *syntax.ConditionalTokens: 522 if tokens.Parentheses.Any() { 523 return true 524 } 525 case *syntax.TemplateConditionalTokens: 526 return len(tokens.OpenIf.LeadingTrivia) != 0 527 } 528 return x.Condition.HasLeadingTrivia() 529 } 530 531 func (x *ConditionalExpression) HasTrailingTrivia() bool { 532 switch tokens := x.Tokens.(type) { 533 case *syntax.ConditionalTokens: 534 if tokens.Parentheses.Any() { 535 return true 536 } 537 case *syntax.TemplateConditionalTokens: 538 return len(tokens.CloseEndif.TrailingTrivia) != 0 539 } 540 return x.FalseResult.HasTrailingTrivia() 541 } 542 543 func (x *ConditionalExpression) GetLeadingTrivia() syntax.TriviaList { 544 switch tokens := x.Tokens.(type) { 545 case *syntax.ConditionalTokens: 546 if tokens.Parentheses.Any() { 547 return tokens.Parentheses.GetLeadingTrivia() 548 } 549 case *syntax.TemplateConditionalTokens: 550 return tokens.OpenIf.LeadingTrivia 551 } 552 return x.Condition.GetLeadingTrivia() 553 } 554 555 func (x *ConditionalExpression) SetLeadingTrivia(t syntax.TriviaList) { 556 switch tokens := x.Tokens.(type) { 557 case *syntax.ConditionalTokens: 558 if tokens.Parentheses.Any() { 559 tokens.Parentheses.SetLeadingTrivia(t) 560 return 561 } 562 case *syntax.TemplateConditionalTokens: 563 tokens.OpenIf.LeadingTrivia = t 564 return 565 } 566 x.Condition.SetLeadingTrivia(t) 567 } 568 569 func (x *ConditionalExpression) GetTrailingTrivia() syntax.TriviaList { 570 switch tokens := x.Tokens.(type) { 571 case *syntax.ConditionalTokens: 572 if tokens.Parentheses.Any() { 573 return tokens.Parentheses.GetTrailingTrivia() 574 } 575 case *syntax.TemplateConditionalTokens: 576 return tokens.CloseEndif.TrailingTrivia 577 } 578 return x.FalseResult.GetTrailingTrivia() 579 } 580 581 func (x *ConditionalExpression) SetTrailingTrivia(t syntax.TriviaList) { 582 if x.Tokens == nil { 583 x.Tokens = syntax.NewConditionalTokens() 584 } 585 switch tokens := x.Tokens.(type) { 586 case *syntax.ConditionalTokens: 587 if tokens.Parentheses.Any() { 588 tokens.Parentheses.SetTrailingTrivia(t) 589 return 590 } 591 case *syntax.TemplateConditionalTokens: 592 tokens.CloseEndif.TrailingTrivia = t 593 return 594 } 595 x.FalseResult.SetTrailingTrivia(t) 596 } 597 598 func (x *ConditionalExpression) Format(f fmt.State, c rune) { 599 x.print(f, &printer{}) 600 } 601 602 func (x *ConditionalExpression) print(w io.Writer, p *printer) { 603 tokens := x.Tokens 604 if tokens == nil { 605 tokens = syntax.NewConditionalTokens() 606 } 607 608 switch tokens := tokens.(type) { 609 case *syntax.ConditionalTokens: 610 p.fprintf(w, "%(%v% v% v% v% v%)", 611 tokens.Parentheses, 612 x.Condition, tokens.QuestionMark, x.TrueResult, tokens.Colon, x.FalseResult, 613 tokens.Parentheses) 614 case *syntax.TemplateConditionalTokens: 615 p.fprintf(w, "%v%v% v%v%v", tokens.OpenIf, tokens.If, x.Condition, tokens.CloseIf, x.TrueResult) 616 if tokens.Else != nil { 617 p.fprintf(w, "%v%v%v%v", tokens.OpenElse, tokens.Else, tokens.CloseElse, x.FalseResult) 618 } 619 p.fprintf(w, "%v%v%v", tokens.OpenEndif, tokens.Endif, tokens.CloseEndif) 620 } 621 } 622 623 func (*ConditionalExpression) isExpression() {} 624 625 // ErrorExpression represents an expression that could not be bound due to an error. 626 type ErrorExpression struct { 627 // The syntax node associated with the error, if any. 628 Syntax hclsyntax.Node 629 // The tokens associated with the error. 630 Tokens syntax.NodeTokens 631 // The message associated with the error. 632 Message string 633 634 exprType Type 635 } 636 637 // SyntaxNode returns the syntax node associated with the error expression. 638 func (x *ErrorExpression) SyntaxNode() hclsyntax.Node { 639 return x.Syntax 640 } 641 642 // NodeTokens returns the tokens associated with the error expression. 643 func (x *ErrorExpression) NodeTokens() syntax.NodeTokens { 644 return x.Tokens 645 } 646 647 // Type returns the type of the error expression. 648 func (x *ErrorExpression) Type() Type { 649 return x.exprType 650 } 651 652 func (x *ErrorExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 653 return nil 654 } 655 656 func (x *ErrorExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 657 return cty.DynamicVal, hcl.Diagnostics{{ 658 Severity: hcl.DiagError, 659 Summary: x.Message, 660 }} 661 } 662 663 func (x *ErrorExpression) HasLeadingTrivia() bool { 664 return false 665 } 666 667 func (x *ErrorExpression) HasTrailingTrivia() bool { 668 return false 669 } 670 671 func (x *ErrorExpression) GetLeadingTrivia() syntax.TriviaList { 672 return nil 673 } 674 675 func (x *ErrorExpression) SetLeadingTrivia(t syntax.TriviaList) { 676 } 677 678 func (x *ErrorExpression) GetTrailingTrivia() syntax.TriviaList { 679 return nil 680 } 681 682 func (x *ErrorExpression) SetTrailingTrivia(t syntax.TriviaList) { 683 } 684 685 func (x *ErrorExpression) Format(f fmt.State, c rune) { 686 x.print(f, &printer{}) 687 } 688 689 func (x *ErrorExpression) print(w io.Writer, p *printer) { 690 p.fprintf(w, "error(%q)", x.Message) 691 } 692 693 func (*ErrorExpression) isExpression() {} 694 695 // ForExpression represents a semantically-analyzed for expression. 696 type ForExpression struct { 697 fmt.Formatter 698 699 // The syntax node associated with the for expression. 700 Syntax *hclsyntax.ForExpr 701 // The tokens associated with the expression, if any. 702 Tokens syntax.NodeTokens 703 704 // The key variable, if any. 705 KeyVariable *Variable 706 // The value variable. 707 ValueVariable *Variable 708 709 // The collection being iterated. 710 Collection Expression 711 // The expression that generates the keys of the result, if any. If this field is non-nil, the result is a map. 712 Key Expression 713 // The expression that generates the values of the result. 714 Value Expression 715 // The condition that filters the items of the result, if any. 716 Condition Expression 717 718 // True if the value expression is being grouped. 719 Group bool 720 721 exprType Type 722 } 723 724 // SyntaxNode returns the syntax node associated with the for expression. 725 func (x *ForExpression) SyntaxNode() hclsyntax.Node { 726 return x.Syntax 727 } 728 729 // NodeTokens returns the tokens associated with the for expression. 730 func (x *ForExpression) NodeTokens() syntax.NodeTokens { 731 return x.Tokens 732 } 733 734 // Type returns the type of the for expression. 735 func (x *ForExpression) Type() Type { 736 return x.exprType 737 } 738 739 func (x *ForExpression) typecheck(typecheckCollection, typecheckOperands bool) hcl.Diagnostics { 740 var diagnostics hcl.Diagnostics 741 742 var rng hcl.Range 743 if x.Syntax != nil { 744 rng = x.Syntax.CollExpr.Range() 745 } 746 747 if typecheckOperands { 748 collectionDiags := x.Collection.Typecheck(true) 749 diagnostics = append(diagnostics, collectionDiags...) 750 } 751 752 if typecheckCollection { 753 // Poke through any eventual and optional types that may wrap the collection type. 754 collectionType := unwrapIterableSourceType(x.Collection.Type()) 755 756 keyType, valueType, kvDiags := GetCollectionTypes(collectionType, rng) 757 diagnostics = append(diagnostics, kvDiags...) 758 759 if x.KeyVariable != nil { 760 x.KeyVariable.VariableType = keyType 761 } 762 x.ValueVariable.VariableType = valueType 763 } 764 765 if typecheckOperands { 766 if x.Key != nil { 767 keyDiags := x.Key.Typecheck(true) 768 diagnostics = append(diagnostics, keyDiags...) 769 } 770 771 valueDiags := x.Value.Typecheck(true) 772 diagnostics = append(diagnostics, valueDiags...) 773 774 if x.Condition != nil { 775 conditionDiags := x.Condition.Typecheck(true) 776 diagnostics = append(diagnostics, conditionDiags...) 777 } 778 } 779 780 if x.Key != nil { 781 // A key expression is only present when producing a map. Key types must therefore be strings. 782 if !InputType(StringType).ConversionFrom(x.Key.Type()).Exists() { 783 diagnostics = append(diagnostics, ExprNotConvertible(InputType(StringType), x.Key)) 784 } 785 } 786 787 if x.Condition != nil { 788 if !InputType(BoolType).ConversionFrom(x.Condition.Type()).Exists() { 789 diagnostics = append(diagnostics, ExprNotConvertible(InputType(BoolType), x.Condition)) 790 } 791 } 792 793 // If there is a key expression, we are producing a map. Otherwise, we are producing an list. In either case, wrap 794 // the result type in the same set of eventuals and optionals present in the collection type. 795 var resultType Type 796 if x.Key != nil { 797 valueType := x.Value.Type() 798 if x.Group { 799 valueType = NewListType(valueType) 800 } 801 resultType = wrapIterableResultType(x.Collection.Type(), NewMapType(valueType)) 802 } else { 803 resultType = wrapIterableResultType(x.Collection.Type(), NewListType(x.Value.Type())) 804 } 805 806 // If either the key expression or the condition expression is eventual, the result is eventual: each of these 807 // values is required to determine which items are present in the result. 808 var liftArgs []Expression 809 if x.Key != nil { 810 liftArgs = append(liftArgs, x.Key) 811 } 812 if x.Condition != nil { 813 liftArgs = append(liftArgs, x.Condition) 814 } 815 816 x.exprType = liftOperationType(resultType, liftArgs...) 817 return diagnostics 818 } 819 820 func (x *ForExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 821 return x.typecheck(true, typecheckOperands) 822 } 823 824 func (x *ForExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 825 syntax := &hclsyntax.ForExpr{ 826 ValVar: x.ValueVariable.Name, 827 CollExpr: &syntaxExpr{expr: x.Collection}, 828 ValExpr: &syntaxExpr{expr: x.Value}, 829 Group: x.Group, 830 } 831 if x.KeyVariable != nil { 832 syntax.KeyVar = x.KeyVariable.Name 833 } 834 if x.Key != nil { 835 syntax.KeyExpr = &syntaxExpr{expr: x.Key} 836 } 837 if x.Condition != nil { 838 syntax.CondExpr = &syntaxExpr{expr: x.Condition} 839 } 840 return syntax.Value(context) 841 } 842 843 func (x *ForExpression) HasLeadingTrivia() bool { 844 return x.Tokens != nil 845 } 846 847 func (x *ForExpression) HasTrailingTrivia() bool { 848 return x.Tokens != nil 849 } 850 851 func (x *ForExpression) GetLeadingTrivia() syntax.TriviaList { 852 switch tokens := x.Tokens.(type) { 853 case *syntax.ForTokens: 854 return getExprLeadingTrivia(tokens.Parentheses, tokens.Open) 855 case *syntax.TemplateForTokens: 856 return tokens.OpenFor.LeadingTrivia 857 default: 858 return nil 859 } 860 } 861 862 func (x *ForExpression) SetLeadingTrivia(t syntax.TriviaList) { 863 if x.Tokens == nil { 864 keyVariable := "" 865 if x.KeyVariable != nil { 866 keyVariable = x.KeyVariable.Name 867 } 868 x.Tokens = syntax.NewForTokens(keyVariable, x.ValueVariable.Name, x.Key != nil, x.Group, x.Condition != nil) 869 } 870 switch tokens := x.Tokens.(type) { 871 case *syntax.ForTokens: 872 setExprLeadingTrivia(tokens.Parentheses, &tokens.Open, t) 873 case *syntax.TemplateForTokens: 874 tokens.OpenFor.LeadingTrivia = t 875 } 876 } 877 878 func (x *ForExpression) GetTrailingTrivia() syntax.TriviaList { 879 switch tokens := x.Tokens.(type) { 880 case *syntax.ForTokens: 881 return getExprTrailingTrivia(tokens.Parentheses, tokens.Close) 882 case *syntax.TemplateForTokens: 883 return tokens.CloseEndfor.TrailingTrivia 884 default: 885 return nil 886 } 887 } 888 889 func (x *ForExpression) SetTrailingTrivia(t syntax.TriviaList) { 890 if x.Tokens == nil { 891 keyVariable := "" 892 if x.KeyVariable != nil { 893 keyVariable = x.KeyVariable.Name 894 } 895 x.Tokens = syntax.NewForTokens(keyVariable, x.ValueVariable.Name, x.Key != nil, x.Group, x.Condition != nil) 896 } 897 switch tokens := x.Tokens.(type) { 898 case *syntax.ForTokens: 899 setExprTrailingTrivia(tokens.Parentheses, &tokens.Close, t) 900 case *syntax.TemplateForTokens: 901 tokens.CloseEndfor.TrailingTrivia = t 902 } 903 } 904 905 func (x *ForExpression) Format(f fmt.State, c rune) { 906 x.print(f, &printer{}) 907 } 908 909 func (x *ForExpression) print(w io.Writer, p *printer) { 910 tokens := x.Tokens 911 if tokens == nil { 912 keyVariable := "" 913 if x.KeyVariable != nil { 914 keyVariable = x.KeyVariable.Name 915 } 916 syntax.NewForTokens(keyVariable, x.ValueVariable.Name, x.Key != nil, x.Group, x.Condition != nil) 917 } 918 919 switch tokens := tokens.(type) { 920 case *syntax.ForTokens: 921 // Print the opening rune and the for token. 922 p.fprintf(w, "%(%v%v", tokens.Parentheses, tokens.Open, tokens.For) 923 924 // Print the key variable, if any. 925 if x.KeyVariable != nil { 926 keyToken := tokens.Key 927 if x.KeyVariable != nil && keyToken == nil { 928 keyToken = &syntax.Token{Raw: hclsyntax.Token{Type: hclsyntax.TokenIdent}} 929 } 930 931 key := identToken(*keyToken, x.KeyVariable.Name) 932 p.fprintf(w, "% v%v", key, tokens.Comma) 933 } 934 935 // Print the value variable, the in token, the collection expression, and the colon. 936 value := identToken(tokens.Value, x.ValueVariable.Name) 937 p.fprintf(w, "% v% v% v%v", value, tokens.In, x.Collection, tokens.Colon) 938 939 // Print the key expression and arrow token, if any. 940 if x.Key != nil { 941 p.fprintf(w, "% v% v", x.Key, tokens.Arrow) 942 } 943 944 // Print the value expression. 945 p.fprintf(w, "% v", x.Value) 946 947 // Print the group token, if any. 948 if x.Group { 949 p.fprintf(w, "%v", tokens.Group) 950 } 951 952 // Print the if token and the condition, if any. 953 if x.Condition != nil { 954 p.fprintf(w, "% v% v", tokens.If, x.Condition) 955 } 956 957 // Print the closing rune. 958 p.fprintf(w, "%v%)", tokens.Close, tokens.Parentheses) 959 case *syntax.TemplateForTokens: 960 // Print the opening sequence. 961 p.fprintf(w, "%v%v", tokens.OpenFor, tokens.For) 962 963 // Print the key variable, if any. 964 if x.KeyVariable != nil { 965 keyToken := tokens.Key 966 if x.KeyVariable != nil && keyToken == nil { 967 keyToken = &syntax.Token{Raw: hclsyntax.Token{Type: hclsyntax.TokenIdent}} 968 } 969 970 key := identToken(*keyToken, x.KeyVariable.Name) 971 p.fprintf(w, "% v%v", key, tokens.Comma) 972 } 973 974 // Print the value variable, the in token, the collection expression, the control sequence terminator, the 975 // value expression, and the closing sequence. 976 p.fprintf(w, "% v% v% v%v%v%v%v%v", 977 identToken(tokens.Value, x.ValueVariable.Name), tokens.In, x.Collection, tokens.CloseFor, 978 x.Value, 979 tokens.OpenEndfor, tokens.Endfor, tokens.CloseEndfor) 980 } 981 } 982 983 func (*ForExpression) isExpression() {} 984 985 // FunctionCallExpression represents a semantically-analyzed function call expression. 986 type FunctionCallExpression struct { 987 // The syntax node associated with the function call expression. 988 Syntax *hclsyntax.FunctionCallExpr 989 // The tokens associated with the expression, if any. 990 Tokens *syntax.FunctionCallTokens 991 992 // The name of the called function. 993 Name string 994 // The signature of the called function. 995 Signature StaticFunctionSignature 996 // The arguments to the function call. 997 Args []Expression 998 // ExpandFinal indicates that the final argument should be a tuple, list, or set whose elements will be passed as 999 // individual arguments to the function. 1000 ExpandFinal bool 1001 } 1002 1003 // SyntaxNode returns the syntax node associated with the function call expression. 1004 func (x *FunctionCallExpression) SyntaxNode() hclsyntax.Node { 1005 return x.Syntax 1006 } 1007 1008 // NodeTokens returns the tokens associated with the function call expression. 1009 func (x *FunctionCallExpression) NodeTokens() syntax.NodeTokens { 1010 return x.Tokens 1011 } 1012 1013 // Type returns the type of the function call expression. 1014 func (x *FunctionCallExpression) Type() Type { 1015 return x.Signature.ReturnType 1016 } 1017 1018 func (x *FunctionCallExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 1019 var diagnostics hcl.Diagnostics 1020 1021 if typecheckOperands { 1022 for _, arg := range x.Args { 1023 argDiagnostics := arg.Typecheck(true) 1024 diagnostics = append(diagnostics, argDiagnostics...) 1025 } 1026 } 1027 1028 var rng hcl.Range 1029 if x.Syntax != nil { 1030 rng = x.Syntax.Range() 1031 } 1032 1033 // Typecheck the function's arguments. 1034 typecheckDiags := typecheckArgs(rng, x.Signature, x.Args...) 1035 diagnostics = append(diagnostics, typecheckDiags...) 1036 1037 // Unless the function is already automatically using an 1038 // Output-returning version, modify the signature to account 1039 // for automatic lifting to Promise or Output. 1040 _, isOutput := x.Signature.ReturnType.(*OutputType) 1041 if !isOutput { 1042 x.Signature.ReturnType = liftOperationType(x.Signature.ReturnType, x.Args...) 1043 } 1044 return diagnostics 1045 } 1046 1047 func (x *FunctionCallExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 1048 syntax := &hclsyntax.FunctionCallExpr{ 1049 Name: x.Name, 1050 Args: make([]hclsyntax.Expression, len(x.Args)), 1051 ExpandFinal: x.ExpandFinal, 1052 } 1053 for i, arg := range x.Args { 1054 syntax.Args[i] = &syntaxExpr{expr: arg} 1055 } 1056 return syntax.Value(context) 1057 } 1058 1059 func (x *FunctionCallExpression) HasLeadingTrivia() bool { 1060 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 1061 } 1062 1063 func (x *FunctionCallExpression) HasTrailingTrivia() bool { 1064 return exprHasTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 1065 } 1066 1067 func (x *FunctionCallExpression) GetLeadingTrivia() syntax.TriviaList { 1068 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetName(x.Name)) 1069 } 1070 1071 func (x *FunctionCallExpression) SetLeadingTrivia(t syntax.TriviaList) { 1072 if x.Tokens == nil { 1073 x.Tokens = syntax.NewFunctionCallTokens(x.Name, len(x.Args)) 1074 } 1075 setExprLeadingTrivia(x.Tokens.Parentheses, &x.Tokens.Name, t) 1076 } 1077 1078 func (x *FunctionCallExpression) GetTrailingTrivia() syntax.TriviaList { 1079 return getExprTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetCloseParen()) 1080 } 1081 1082 func (x *FunctionCallExpression) SetTrailingTrivia(t syntax.TriviaList) { 1083 if x.Tokens == nil { 1084 x.Tokens = syntax.NewFunctionCallTokens(x.Name, len(x.Args)) 1085 } 1086 setExprTrailingTrivia(x.Tokens.Parentheses, &x.Tokens.CloseParen, t) 1087 } 1088 1089 func (x *FunctionCallExpression) Format(f fmt.State, c rune) { 1090 x.print(f, &printer{}) 1091 } 1092 1093 func (x *FunctionCallExpression) print(w io.Writer, p *printer) { 1094 // Print the name and opening parenthesis. 1095 p.fprintf(w, "%(%v%v", x.Tokens.GetParentheses(), x.Tokens.GetName(x.Name), x.Tokens.GetOpenParen()) 1096 1097 // Print each argument and its comma. 1098 commas := x.Tokens.GetCommas(len(x.Args)) 1099 for i, arg := range x.Args { 1100 if i == 0 { 1101 p.fprintf(w, "%v", arg) 1102 } else { 1103 p.fprintf(w, "% v", arg) 1104 } 1105 1106 if i < len(x.Args)-1 { 1107 var comma syntax.Token 1108 if i < len(commas) { 1109 comma = commas[i] 1110 } 1111 p.fprintf(w, "%v", comma) 1112 } 1113 } 1114 1115 // If there were commas left over, print the trivia for each. 1116 if len(x.Args) > 0 && len(x.Args)-1 <= len(commas) { 1117 for _, comma := range commas[len(x.Args)-1:] { 1118 p.fprintf(w, "%v", comma.AllTrivia().CollapseWhitespace()) 1119 } 1120 } 1121 1122 // Print the closing parenthesis. 1123 p.fprintf(w, "%v%)", x.Tokens.GetCloseParen(), x.Tokens.GetParentheses()) 1124 } 1125 1126 func (*FunctionCallExpression) isExpression() {} 1127 1128 // IndexExpression represents a semantically-analyzed index expression. 1129 type IndexExpression struct { 1130 // The syntax node associated with the index expression. 1131 Syntax *hclsyntax.IndexExpr 1132 // The tokens associated with the expression, if any. 1133 Tokens *syntax.IndexTokens 1134 1135 // The collection being indexed. 1136 Collection Expression 1137 // The index key. 1138 Key Expression 1139 1140 keyType Type 1141 exprType Type 1142 } 1143 1144 // SyntaxNode returns the syntax node associated with the index expression. 1145 func (x *IndexExpression) SyntaxNode() hclsyntax.Node { 1146 return x.Syntax 1147 } 1148 1149 // NodeTokens returns the tokens associated with the index expression. 1150 func (x *IndexExpression) NodeTokens() syntax.NodeTokens { 1151 return x.Tokens 1152 } 1153 1154 // KeyType returns the expected type of the index expression's key. 1155 func (x *IndexExpression) KeyType() Type { 1156 return x.keyType 1157 } 1158 1159 // Type returns the type of the index expression. 1160 func (x *IndexExpression) Type() Type { 1161 return x.exprType 1162 } 1163 1164 func (x *IndexExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 1165 var diagnostics hcl.Diagnostics 1166 1167 if typecheckOperands { 1168 collectionDiags := x.Collection.Typecheck(true) 1169 diagnostics = append(diagnostics, collectionDiags...) 1170 1171 keyDiags := x.Key.Typecheck(true) 1172 diagnostics = append(diagnostics, keyDiags...) 1173 } 1174 1175 var rng hcl.Range 1176 if x.Syntax != nil { 1177 rng = x.Syntax.Collection.Range() 1178 } 1179 1180 collectionType := unwrapIterableSourceType(x.Collection.Type()) 1181 keyType, valueType, kvDiags := GetCollectionTypes(collectionType, rng) 1182 diagnostics = append(diagnostics, kvDiags...) 1183 x.keyType = keyType 1184 1185 if lit, ok := x.Key.(*LiteralValueExpression); ok { 1186 traverser := hcl.TraverseIndex{ 1187 Key: lit.Value, 1188 } 1189 valueType, traverseDiags := x.Collection.Type().Traverse(traverser) 1190 if len(traverseDiags) == 0 { 1191 x.exprType = valueType.(Type) 1192 return diagnostics 1193 } 1194 } 1195 1196 if !InputType(keyType).ConversionFrom(x.Key.Type()).Exists() { 1197 diagnostics = append(diagnostics, ExprNotConvertible(InputType(keyType), x.Key)) 1198 } 1199 1200 resultType := wrapIterableResultType(x.Collection.Type(), valueType) 1201 x.exprType = liftOperationType(resultType, x.Key) 1202 return diagnostics 1203 } 1204 1205 func (x *IndexExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 1206 syntax := &hclsyntax.IndexExpr{ 1207 Collection: &syntaxExpr{expr: x.Collection}, 1208 Key: &syntaxExpr{expr: x.Key}, 1209 } 1210 return syntax.Value(context) 1211 } 1212 1213 func (x *IndexExpression) HasLeadingTrivia() bool { 1214 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Collection) 1215 } 1216 1217 func (x *IndexExpression) HasTrailingTrivia() bool { 1218 return exprHasTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 1219 } 1220 1221 func (x *IndexExpression) GetLeadingTrivia() syntax.TriviaList { 1222 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetOpenBracket()) 1223 } 1224 1225 func (x *IndexExpression) SetLeadingTrivia(t syntax.TriviaList) { 1226 if x.Tokens == nil { 1227 x.Tokens = syntax.NewIndexTokens() 1228 } 1229 setExprLeadingTrivia(x.Tokens.Parentheses, x.Collection, t) 1230 } 1231 1232 func (x *IndexExpression) GetTrailingTrivia() syntax.TriviaList { 1233 return getExprTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetCloseBracket()) 1234 } 1235 1236 func (x *IndexExpression) SetTrailingTrivia(t syntax.TriviaList) { 1237 if x.Tokens == nil { 1238 x.Tokens = syntax.NewIndexTokens() 1239 } 1240 setExprTrailingTrivia(x.Tokens.Parentheses, &x.Tokens.CloseBracket, t) 1241 } 1242 1243 func (x *IndexExpression) Format(f fmt.State, c rune) { 1244 x.print(f, &printer{}) 1245 } 1246 1247 func (x *IndexExpression) print(w io.Writer, p *printer) { 1248 p.fprintf(w, "%(%v%v%v%v%)", 1249 x.Tokens.GetParentheses(), 1250 x.Collection, x.Tokens.GetOpenBracket(), x.Key, x.Tokens.GetCloseBracket(), 1251 x.Tokens.GetParentheses()) 1252 } 1253 1254 func (*IndexExpression) isExpression() {} 1255 1256 func literalText(value cty.Value, rawBytes []byte, escaped, quoted bool) string { 1257 if len(rawBytes) > 0 { 1258 parsed, diags := hclsyntax.ParseExpression(rawBytes, "", hcl.Pos{}) 1259 if !diags.HasErrors() { 1260 if lit, ok := parsed.(*hclsyntax.LiteralValueExpr); ok && lit.Val.RawEquals(value) { 1261 return string(rawBytes) 1262 } 1263 } 1264 } 1265 1266 switch value.Type() { 1267 case cty.Bool: 1268 if value.True() { 1269 return "true" 1270 } 1271 return "false" 1272 case cty.Number: 1273 bf := value.AsBigFloat() 1274 i, acc := bf.Int64() 1275 if acc == big.Exact { 1276 return fmt.Sprintf("%v", i) 1277 } 1278 d, _ := bf.Float64() 1279 return fmt.Sprintf("%g", d) 1280 case cty.String: 1281 if !escaped { 1282 return value.AsString() 1283 } 1284 s := strconv.Quote(value.AsString()) 1285 if !quoted { 1286 return s[1 : len(s)-1] 1287 } 1288 return s 1289 default: 1290 panic(fmt.Errorf("unexpected literal type %v", value.Type().FriendlyName())) 1291 } 1292 } 1293 1294 // LiteralValueExpression represents a semantically-analyzed literal value expression. 1295 type LiteralValueExpression struct { 1296 // The syntax node associated with the literal value expression. 1297 Syntax *hclsyntax.LiteralValueExpr 1298 // The tokens associated with the expression, if any. 1299 Tokens *syntax.LiteralValueTokens 1300 1301 // The value of the expression. 1302 Value cty.Value 1303 1304 exprType Type 1305 } 1306 1307 // SyntaxNode returns the syntax node associated with the literal value expression. 1308 func (x *LiteralValueExpression) SyntaxNode() hclsyntax.Node { 1309 return x.Syntax 1310 } 1311 1312 // NodeTokens returns the tokens associated with the literal value expression. 1313 func (x *LiteralValueExpression) NodeTokens() syntax.NodeTokens { 1314 return x.Tokens 1315 } 1316 1317 // Type returns the type of the literal value expression. 1318 func (x *LiteralValueExpression) Type() Type { 1319 if x.exprType == nil { 1320 typ := ctyTypeToType(x.Value.Type(), false) 1321 x.exprType = NewConstType(typ, x.Value) 1322 } 1323 return x.exprType 1324 } 1325 1326 func (x *LiteralValueExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 1327 var diagnostics hcl.Diagnostics 1328 1329 typ := NoneType 1330 if !x.Value.IsNull() { 1331 typ = ctyTypeToType(x.Value.Type(), false) 1332 } 1333 1334 switch { 1335 case typ == NoneType || typ == StringType || typ == IntType || typ == NumberType || typ == BoolType: 1336 // OK 1337 typ = NewConstType(typ, x.Value) 1338 default: 1339 var rng hcl.Range 1340 if x.Syntax != nil { 1341 rng = x.Syntax.Range() 1342 } 1343 typ, diagnostics = DynamicType, hcl.Diagnostics{unsupportedLiteralValue(x.Value, rng)} 1344 } 1345 1346 x.exprType = typ 1347 return diagnostics 1348 } 1349 1350 func (x *LiteralValueExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 1351 syntax := &hclsyntax.LiteralValueExpr{ 1352 Val: x.Value, 1353 } 1354 return syntax.Value(context) 1355 } 1356 1357 func (x *LiteralValueExpression) HasLeadingTrivia() bool { 1358 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 1359 } 1360 1361 func (x *LiteralValueExpression) HasTrailingTrivia() bool { 1362 return exprHasTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 1363 } 1364 1365 func (x *LiteralValueExpression) GetLeadingTrivia() syntax.TriviaList { 1366 if v := x.Tokens.GetValue(x.Value); len(v) > 0 { 1367 return getExprLeadingTrivia(x.Tokens.GetParentheses(), v[0]) 1368 } 1369 return getExprLeadingTrivia(x.Tokens.GetParentheses(), nil) 1370 } 1371 1372 func (x *LiteralValueExpression) SetLeadingTrivia(t syntax.TriviaList) { 1373 if x.Tokens == nil { 1374 x.Tokens = syntax.NewLiteralValueTokens(x.Value) 1375 } 1376 setExprLeadingTrivia(x.Tokens.Parentheses, &x.Tokens.Value[0], t) 1377 } 1378 1379 func (x *LiteralValueExpression) GetTrailingTrivia() syntax.TriviaList { 1380 if v := x.Tokens.GetValue(x.Value); len(v) > 0 { 1381 return getExprTrailingTrivia(x.Tokens.GetParentheses(), v[len(v)-1]) 1382 } 1383 return getExprTrailingTrivia(x.Tokens.GetParentheses(), nil) 1384 } 1385 1386 func (x *LiteralValueExpression) SetTrailingTrivia(t syntax.TriviaList) { 1387 if x.Tokens == nil { 1388 x.Tokens = syntax.NewLiteralValueTokens(x.Value) 1389 } 1390 setExprTrailingTrivia(x.Tokens.Parentheses, &x.Tokens.Value[len(x.Tokens.Value)-1], t) 1391 } 1392 1393 func (x *LiteralValueExpression) Format(f fmt.State, c rune) { 1394 x.print(f, &printer{}) 1395 } 1396 1397 func (x *LiteralValueExpression) printLit(w io.Writer, p *printer, escaped bool) { 1398 // Literals are... odd. They may be composed of multiple tokens, but those tokens should never contain interior 1399 // trivia. 1400 1401 var leading, trailing syntax.TriviaList 1402 var rawBytes []byte 1403 if toks := x.Tokens.GetValue(x.Value); len(toks) > 0 { 1404 leading, trailing = toks[0].LeadingTrivia, toks[len(toks)-1].TrailingTrivia 1405 1406 for _, t := range toks { 1407 rawBytes = append(rawBytes, t.Raw.Bytes...) 1408 } 1409 } 1410 1411 p.fprintf(w, "%(%v%v%v%)", 1412 x.Tokens.GetParentheses(), 1413 leading, literalText(x.Value, rawBytes, escaped, false), trailing, 1414 x.Tokens.GetParentheses()) 1415 } 1416 1417 func (x *LiteralValueExpression) print(w io.Writer, p *printer) { 1418 x.printLit(w, p, false) 1419 } 1420 1421 func (*LiteralValueExpression) isExpression() {} 1422 1423 // ObjectConsItem records a key-value pair that is part of object construction expression. 1424 type ObjectConsItem struct { 1425 // The key. 1426 Key Expression 1427 // The value. 1428 Value Expression 1429 } 1430 1431 // ObjectConsExpression represents a semantically-analyzed object construction expression. 1432 type ObjectConsExpression struct { 1433 // The syntax node associated with the object construction expression. 1434 Syntax *hclsyntax.ObjectConsExpr 1435 // The tokens associated with the expression, if any. 1436 Tokens *syntax.ObjectConsTokens 1437 1438 // The items that comprise the object construction expression. 1439 Items []ObjectConsItem 1440 1441 exprType Type 1442 } 1443 1444 // SyntaxNode returns the syntax node associated with the object construction expression. 1445 func (x *ObjectConsExpression) SyntaxNode() hclsyntax.Node { 1446 return x.Syntax 1447 } 1448 1449 // NodeTokens returns the tokens associated with the object construction expression. 1450 func (x *ObjectConsExpression) NodeTokens() syntax.NodeTokens { 1451 return x.Tokens 1452 } 1453 1454 // Type returns the type of the object construction expression. 1455 func (x *ObjectConsExpression) Type() Type { 1456 return x.exprType 1457 } 1458 1459 func (x *ObjectConsExpression) WithType(updateType func(Type) *ObjectConsExpression) *ObjectConsExpression { 1460 return updateType(x.exprType) 1461 } 1462 1463 func (x *ObjectConsExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 1464 var diagnostics hcl.Diagnostics 1465 1466 var keys []Expression 1467 for _, item := range x.Items { 1468 if typecheckOperands { 1469 keyDiags := item.Key.Typecheck(true) 1470 diagnostics = append(diagnostics, keyDiags...) 1471 1472 valDiags := item.Value.Typecheck(true) 1473 diagnostics = append(diagnostics, valDiags...) 1474 } 1475 1476 keys = append(keys, item.Key) 1477 if !InputType(StringType).ConversionFrom(item.Key.Type()).Exists() { 1478 diagnostics = append(diagnostics, objectKeysMustBeStrings(item.Key)) 1479 } 1480 } 1481 1482 // Attempt to build an object type out of the result. If there are any attribute names that come from variables, 1483 // type the result as map(unify(propertyTypes)). 1484 properties, isMapType, types := map[string]Type{}, false, []Type{} 1485 for _, item := range x.Items { 1486 types = append(types, item.Value.Type()) 1487 1488 key := item.Key 1489 if template, ok := key.(*TemplateExpression); ok && len(template.Parts) == 1 { 1490 key = template.Parts[0] 1491 } 1492 1493 keyLit, ok := key.(*LiteralValueExpression) 1494 if ok { 1495 key, err := convert.Convert(keyLit.Value, cty.String) 1496 if err == nil { 1497 properties[key.AsString()] = item.Value.Type() 1498 continue 1499 } 1500 } 1501 isMapType = true 1502 } 1503 var typ Type 1504 if isMapType { 1505 elementType, _ := UnifyTypes(types...) 1506 typ = NewMapType(elementType) 1507 } else { 1508 typ = NewObjectType(properties) 1509 } 1510 1511 x.exprType = liftOperationType(typ, keys...) 1512 return diagnostics 1513 } 1514 1515 func (x *ObjectConsExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 1516 syntax := &hclsyntax.ObjectConsExpr{ 1517 Items: make([]hclsyntax.ObjectConsItem, len(x.Items)), 1518 } 1519 for i, item := range x.Items { 1520 syntax.Items[i] = hclsyntax.ObjectConsItem{ 1521 KeyExpr: &syntaxExpr{expr: item.Key}, 1522 ValueExpr: &syntaxExpr{expr: item.Value}, 1523 } 1524 } 1525 return syntax.Value(context) 1526 } 1527 1528 func (x *ObjectConsExpression) HasLeadingTrivia() bool { 1529 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 1530 } 1531 1532 func (x *ObjectConsExpression) HasTrailingTrivia() bool { 1533 return exprHasTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 1534 } 1535 1536 func (x *ObjectConsExpression) GetLeadingTrivia() syntax.TriviaList { 1537 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetOpenBrace(len(x.Items))) 1538 } 1539 1540 func (x *ObjectConsExpression) SetLeadingTrivia(t syntax.TriviaList) { 1541 if x.Tokens == nil { 1542 x.Tokens = syntax.NewObjectConsTokens(len(x.Items)) 1543 } 1544 setExprLeadingTrivia(x.Tokens.Parentheses, &x.Tokens.OpenBrace, t) 1545 } 1546 1547 func (x *ObjectConsExpression) GetTrailingTrivia() syntax.TriviaList { 1548 return getExprTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetCloseBrace()) 1549 } 1550 1551 func (x *ObjectConsExpression) SetTrailingTrivia(t syntax.TriviaList) { 1552 if x.Tokens == nil { 1553 x.Tokens = syntax.NewObjectConsTokens(len(x.Items)) 1554 } 1555 setExprTrailingTrivia(x.Tokens.Parentheses, &x.Tokens.CloseBrace, t) 1556 } 1557 1558 func (x *ObjectConsExpression) Format(f fmt.State, c rune) { 1559 x.print(f, &printer{}) 1560 } 1561 1562 func (x *ObjectConsExpression) print(w io.Writer, p *printer) { 1563 // Print the opening brace. 1564 p.fprintf(w, "%(%v", x.Tokens.GetParentheses(), x.Tokens.GetOpenBrace(len(x.Items))) 1565 1566 // Print the items. 1567 isMultiLine, trailingNewline := false, false 1568 p.indented(func() { 1569 items := x.Tokens.GetItems(len(x.Items)) 1570 for i, item := range x.Items { 1571 tokens := syntax.NewObjectConsItemTokens(i == len(x.Items)-1) 1572 if i < len(items) { 1573 tokens = items[i] 1574 } 1575 1576 if item.Key.HasLeadingTrivia() { 1577 if _, i := item.Key.GetLeadingTrivia().Index("\n"); i != -1 { 1578 isMultiLine = true 1579 } 1580 } else if len(items) > 1 { 1581 isMultiLine = true 1582 p.fprintf(w, "\n%s", p.indent) 1583 } 1584 p.fprintf(w, "%v% v% v", item.Key, tokens.Equals, item.Value) 1585 1586 if tokens.Comma != nil { 1587 p.fprintf(w, "%v", tokens.Comma) 1588 } 1589 1590 if isMultiLine && i == len(items)-1 { 1591 trailingTrivia := item.Value.GetTrailingTrivia() 1592 if tokens.Comma != nil { 1593 trailingTrivia = tokens.Comma.TrailingTrivia 1594 } 1595 trailingNewline = trailingTrivia.EndsOnNewLine() 1596 } 1597 } 1598 1599 if len(x.Items) < len(items) { 1600 for _, item := range items[len(x.Items):] { 1601 p.fprintf(w, "%v", item.Equals.AllTrivia().CollapseWhitespace()) 1602 if item.Comma != nil { 1603 p.fprintf(w, "%v", item.Comma.AllTrivia().CollapseWhitespace()) 1604 } 1605 } 1606 } 1607 }) 1608 1609 if x.Tokens != nil { 1610 pre := "" 1611 if isMultiLine && !trailingNewline { 1612 pre = "\n" + p.indent 1613 } 1614 p.fprintf(w, "%s%v%)", pre, x.Tokens.CloseBrace, x.Tokens.Parentheses) 1615 } else { 1616 p.fprintf(w, "\n%s}", p.indent) 1617 } 1618 } 1619 1620 func (*ObjectConsExpression) isExpression() {} 1621 1622 func getTraverserTrivia(tokens syntax.TraverserTokens) (syntax.TriviaList, syntax.TriviaList) { 1623 var leading, trailing syntax.TriviaList 1624 switch tokens := tokens.(type) { 1625 case *syntax.DotTraverserTokens: 1626 leading = getExprLeadingTrivia(tokens.Parentheses, tokens.Dot) 1627 trailing = getExprTrailingTrivia(tokens.Parentheses, tokens.Index) 1628 case *syntax.BracketTraverserTokens: 1629 leading = getExprLeadingTrivia(tokens.Parentheses, tokens.OpenBracket) 1630 trailing = getExprTrailingTrivia(tokens.Parentheses, tokens.CloseBracket) 1631 } 1632 return leading, trailing 1633 } 1634 1635 func setTraverserTrailingTrivia(tokens syntax.TraverserTokens, t syntax.TriviaList) { 1636 switch tokens := tokens.(type) { 1637 case *syntax.DotTraverserTokens: 1638 setExprTrailingTrivia(tokens.Parentheses, &tokens.Index, t) 1639 case *syntax.BracketTraverserTokens: 1640 setExprTrailingTrivia(tokens.Parentheses, &tokens.CloseBracket, t) 1641 default: 1642 panic(fmt.Errorf("unexpected traverser of type %T", tokens)) 1643 } 1644 } 1645 1646 func printTraverser(w io.Writer, p *printer, t hcl.Traverser, tokens syntax.TraverserTokens) { 1647 var index string 1648 switch t := t.(type) { 1649 case hcl.TraverseAttr: 1650 index = t.Name 1651 case hcl.TraverseIndex: 1652 index = literalText(t.Key, nil, true, true) 1653 default: 1654 panic(fmt.Errorf("unexpected traverser of type %T", t)) 1655 } 1656 1657 switch tokens := tokens.(type) { 1658 case *syntax.DotTraverserTokens: 1659 p.fprintf(w, "%(%v%v%)", 1660 tokens.Parentheses, 1661 tokens.Dot, identToken(tokens.Index, index), 1662 tokens.Parentheses) 1663 case *syntax.BracketTraverserTokens: 1664 p.fprintf(w, "%(%v%v%v%)", 1665 tokens.Parentheses, 1666 tokens.OpenBracket, identToken(tokens.Index, index), tokens.CloseBracket, 1667 tokens.Parentheses) 1668 default: 1669 panic(fmt.Errorf("unexpected traverser tokens of type %T", tokens)) 1670 } 1671 } 1672 1673 func printRelativeTraversal(w io.Writer, p *printer, traversal hcl.Traversal, tokens []syntax.TraverserTokens) { 1674 for i, traverser := range traversal { 1675 // Fetch the traversal tokens. 1676 var traverserTokens syntax.TraverserTokens 1677 if i < len(tokens) { 1678 traverserTokens = tokens[i] 1679 } 1680 printTraverser(w, p, traverser, traverserTokens) 1681 } 1682 1683 // Print any remaining trivia. 1684 if len(traversal) < len(tokens) { 1685 for _, tokens := range tokens[len(traversal):] { 1686 var trivia syntax.TriviaList 1687 switch tokens := tokens.(type) { 1688 case *syntax.DotTraverserTokens: 1689 trivia = tokens.Dot.LeadingTrivia 1690 trivia = append(trivia, tokens.Dot.TrailingTrivia...) 1691 trivia = append(trivia, tokens.Index.LeadingTrivia...) 1692 trivia = append(trivia, tokens.Index.TrailingTrivia...) 1693 case *syntax.BracketTraverserTokens: 1694 trivia = tokens.OpenBracket.LeadingTrivia 1695 trivia = append(trivia, tokens.OpenBracket.TrailingTrivia...) 1696 trivia = append(trivia, tokens.Index.LeadingTrivia...) 1697 trivia = append(trivia, tokens.Index.TrailingTrivia...) 1698 trivia = append(trivia, tokens.CloseBracket.LeadingTrivia...) 1699 trivia = append(trivia, tokens.CloseBracket.TrailingTrivia...) 1700 } 1701 p.fprintf(w, "%v", trivia) 1702 } 1703 } 1704 } 1705 1706 // RelativeTraversalExpression represents a semantically-analyzed relative traversal expression. 1707 type RelativeTraversalExpression struct { 1708 // The syntax node associated with the relative traversal expression. 1709 Syntax *hclsyntax.RelativeTraversalExpr 1710 // The tokens associated with the expression, if any. 1711 Tokens *syntax.RelativeTraversalTokens 1712 1713 // The expression that computes the value being traversed. 1714 Source Expression 1715 // The traversal's parts. 1716 Parts []Traversable 1717 1718 // The traversers. 1719 Traversal hcl.Traversal 1720 } 1721 1722 // SyntaxNode returns the syntax node associated with the relative traversal expression. 1723 func (x *RelativeTraversalExpression) SyntaxNode() hclsyntax.Node { 1724 return x.Syntax 1725 } 1726 1727 // NodeTokens returns the tokens associated with the relative traversal expression. 1728 func (x *RelativeTraversalExpression) NodeTokens() syntax.NodeTokens { 1729 return x.Tokens 1730 } 1731 1732 // Type returns the type of the relative traversal expression. 1733 func (x *RelativeTraversalExpression) Type() Type { 1734 return GetTraversableType(x.Parts[len(x.Parts)-1]) 1735 } 1736 1737 func (x *RelativeTraversalExpression) typecheck(typecheckOperands, allowMissingVariables bool) hcl.Diagnostics { 1738 var diagnostics hcl.Diagnostics 1739 1740 if typecheckOperands { 1741 sourceDiags := x.Source.Typecheck(true) 1742 diagnostics = append(diagnostics, sourceDiags...) 1743 } 1744 1745 parts, partDiags := bindTraversalParts(x.Source.Type(), x.Traversal, allowMissingVariables) 1746 diagnostics = append(diagnostics, partDiags...) 1747 1748 x.Parts = parts 1749 return diagnostics 1750 } 1751 1752 func (x *RelativeTraversalExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 1753 return x.typecheck(typecheckOperands, false) 1754 } 1755 1756 func (x *RelativeTraversalExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 1757 syntax := &hclsyntax.RelativeTraversalExpr{ 1758 Source: &syntaxExpr{expr: x.Source}, 1759 Traversal: x.Traversal, 1760 } 1761 return syntax.Value(context) 1762 } 1763 1764 func (x *RelativeTraversalExpression) HasLeadingTrivia() bool { 1765 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Source) 1766 } 1767 1768 func (x *RelativeTraversalExpression) HasTrailingTrivia() bool { 1769 if parens := x.Tokens.GetParentheses(); parens.Any() { 1770 return true 1771 } 1772 if x.Tokens != nil && len(x.Tokens.Traversal) > 0 { 1773 return true 1774 } 1775 return x.Source.HasTrailingTrivia() 1776 } 1777 1778 func (x *RelativeTraversalExpression) GetLeadingTrivia() syntax.TriviaList { 1779 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.Source) 1780 } 1781 1782 func (x *RelativeTraversalExpression) SetLeadingTrivia(t syntax.TriviaList) { 1783 if x.Tokens == nil { 1784 x.Tokens = syntax.NewRelativeTraversalTokens(x.Traversal) 1785 } 1786 setExprLeadingTrivia(x.Tokens.Parentheses, x.Source, t) 1787 } 1788 1789 func (x *RelativeTraversalExpression) GetTrailingTrivia() syntax.TriviaList { 1790 if parens := x.Tokens.GetParentheses(); parens.Any() { 1791 return parens.GetTrailingTrivia() 1792 } 1793 if traversal := x.Tokens.GetTraversal(x.Traversal); len(traversal) > 0 { 1794 _, trailingTrivia := getTraverserTrivia(traversal[len(traversal)-1]) 1795 return trailingTrivia 1796 } 1797 return x.Source.GetTrailingTrivia() 1798 } 1799 1800 func (x *RelativeTraversalExpression) SetTrailingTrivia(t syntax.TriviaList) { 1801 if x.Tokens == nil { 1802 x.Tokens = syntax.NewRelativeTraversalTokens(x.Traversal) 1803 } 1804 if parens := x.Tokens.GetParentheses(); parens.Any() { 1805 parens.SetTrailingTrivia(t) 1806 return 1807 } 1808 if len(x.Tokens.Traversal) > 0 { 1809 setTraverserTrailingTrivia(x.Tokens.Traversal[len(x.Tokens.Traversal)-1], t) 1810 return 1811 } 1812 x.Source.SetTrailingTrivia(t) 1813 } 1814 1815 func (x *RelativeTraversalExpression) Format(f fmt.State, c rune) { 1816 x.print(f, &printer{}) 1817 } 1818 1819 func (x *RelativeTraversalExpression) print(w io.Writer, p *printer) { 1820 // Print the source expression. 1821 p.fprintf(w, "%(%v", x.Tokens.GetParentheses(), x.Source) 1822 1823 // Print the traversal. 1824 printRelativeTraversal(w, p, x.Traversal, x.Tokens.GetTraversal(x.Traversal)) 1825 1826 // Print the closing parentheses, if any. 1827 p.fprintf(w, "%)", x.Tokens.GetParentheses()) 1828 } 1829 1830 func (*RelativeTraversalExpression) isExpression() {} 1831 1832 // ScopeTraversalExpression represents a semantically-analyzed scope traversal expression. 1833 type ScopeTraversalExpression struct { 1834 // The syntax node associated with the scope traversal expression. 1835 Syntax *hclsyntax.ScopeTraversalExpr 1836 // The tokens associated with the expression, if any. 1837 Tokens *syntax.ScopeTraversalTokens 1838 1839 // The traversal's parts. 1840 Parts []Traversable 1841 1842 // The root name. 1843 RootName string 1844 // The traversers. 1845 Traversal hcl.Traversal 1846 } 1847 1848 // SyntaxNode returns the syntax node associated with the scope traversal expression. 1849 func (x *ScopeTraversalExpression) SyntaxNode() hclsyntax.Node { 1850 return x.Syntax 1851 } 1852 1853 // NodeTokens returns the tokens associated with the scope traversal expression. 1854 func (x *ScopeTraversalExpression) NodeTokens() syntax.NodeTokens { 1855 return x.Tokens 1856 } 1857 1858 // Type returns the type of the scope traversal expression. 1859 func (x *ScopeTraversalExpression) Type() Type { 1860 return GetTraversableType(x.Parts[len(x.Parts)-1]) 1861 } 1862 1863 func (x *ScopeTraversalExpression) typecheck(typecheckOperands, allowMissingVariables bool) hcl.Diagnostics { 1864 parts, diagnostics := bindTraversalParts(x.Parts[0], x.Traversal.SimpleSplit().Rel, allowMissingVariables) 1865 x.Parts = parts 1866 1867 return diagnostics 1868 } 1869 1870 func (x *ScopeTraversalExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 1871 return x.typecheck(typecheckOperands, false) 1872 } 1873 1874 func (x *ScopeTraversalExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 1875 var diagnostics hcl.Diagnostics 1876 1877 root, hasValue := x.Parts[0].(ValueTraversable) 1878 if !hasValue { 1879 return cty.UnknownVal(cty.DynamicPseudoType), nil 1880 } 1881 1882 rootValue, diags := root.Value(context) 1883 if diags.HasErrors() { 1884 return cty.NilVal, diags 1885 } 1886 diagnostics = append(diagnostics, diags...) 1887 1888 if len(x.Traversal) == 1 { 1889 return rootValue, diagnostics 1890 } 1891 return x.Traversal[1:].TraverseRel(rootValue) 1892 } 1893 1894 func (x *ScopeTraversalExpression) HasLeadingTrivia() bool { 1895 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 1896 } 1897 1898 func (x *ScopeTraversalExpression) HasTrailingTrivia() bool { 1899 if parens := x.Tokens.GetParentheses(); parens.Any() { 1900 return true 1901 } 1902 if x.Tokens != nil && len(x.Tokens.Traversal) > 0 { 1903 return true 1904 } 1905 return x.Tokens != nil 1906 } 1907 1908 func (x *ScopeTraversalExpression) GetLeadingTrivia() syntax.TriviaList { 1909 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetRoot(x.Traversal)) 1910 } 1911 1912 func (x *ScopeTraversalExpression) SetLeadingTrivia(t syntax.TriviaList) { 1913 if x.Tokens == nil { 1914 x.Tokens = syntax.NewScopeTraversalTokens(x.Traversal) 1915 } 1916 x.Tokens.Root.LeadingTrivia = t 1917 } 1918 1919 func (x *ScopeTraversalExpression) GetTrailingTrivia() syntax.TriviaList { 1920 if parens := x.Tokens.GetParentheses(); parens.Any() { 1921 return parens.GetTrailingTrivia() 1922 } 1923 if traversal := x.Tokens.GetTraversal(x.Traversal); len(traversal) > 0 { 1924 _, trailingTrivia := getTraverserTrivia(traversal[len(traversal)-1]) 1925 return trailingTrivia 1926 } 1927 return x.Tokens.GetRoot(x.Traversal).TrailingTrivia 1928 } 1929 1930 func (x *ScopeTraversalExpression) SetTrailingTrivia(t syntax.TriviaList) { 1931 if x.Tokens == nil { 1932 x.Tokens = syntax.NewScopeTraversalTokens(x.Traversal) 1933 } 1934 if parens := x.Tokens.GetParentheses(); parens.Any() { 1935 parens.SetTrailingTrivia(t) 1936 return 1937 } 1938 if len(x.Tokens.Traversal) > 0 { 1939 setTraverserTrailingTrivia(x.Tokens.Traversal[len(x.Tokens.Traversal)-1], t) 1940 return 1941 } 1942 x.Tokens.Root.TrailingTrivia = t 1943 } 1944 1945 func (x *ScopeTraversalExpression) Format(f fmt.State, c rune) { 1946 x.print(f, &printer{}) 1947 } 1948 1949 func (x *ScopeTraversalExpression) print(w io.Writer, p *printer) { 1950 // Print the root name. 1951 p.fprintf(w, "%(%v", x.Tokens.GetParentheses(), x.Tokens.GetRoot(x.Traversal)) 1952 1953 // Print the traversal. 1954 printRelativeTraversal(w, p, x.Traversal[1:], x.Tokens.GetTraversal(x.Traversal)) 1955 1956 // Print the closing parentheses, if any. 1957 p.fprintf(w, "%)", x.Tokens.GetParentheses()) 1958 } 1959 1960 func (*ScopeTraversalExpression) isExpression() {} 1961 1962 type SplatVariable struct { 1963 Variable 1964 1965 symbol hclsyntax.AnonSymbolExpr 1966 } 1967 1968 func (v *SplatVariable) Value(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 1969 return (&v.symbol).Value(context) 1970 } 1971 1972 // SplatExpression represents a semantically-analyzed splat expression. 1973 type SplatExpression struct { 1974 // The syntax node associated with the splat expression. 1975 Syntax *hclsyntax.SplatExpr 1976 // The tokens associated with the expression, if any. 1977 Tokens *syntax.SplatTokens 1978 1979 // The expression being splatted. 1980 Source Expression 1981 // The expression applied to each element of the splat. 1982 Each Expression 1983 // The local variable definition associated with the current item being processed. This definition is not part of 1984 // a scope, and can only be referenced by an AnonSymbolExpr. 1985 Item *SplatVariable 1986 1987 exprType Type 1988 } 1989 1990 // SyntaxNode returns the syntax node associated with the splat expression. 1991 func (x *SplatExpression) SyntaxNode() hclsyntax.Node { 1992 return x.Syntax 1993 } 1994 1995 // NodeTokens returns the tokens associated with the splat expression. 1996 func (x *SplatExpression) NodeTokens() syntax.NodeTokens { 1997 return x.Tokens 1998 } 1999 2000 // Type returns the type of the splat expression. 2001 func (x *SplatExpression) Type() Type { 2002 return x.exprType 2003 } 2004 2005 func splatItemType(source Expression, splatSyntax *hclsyntax.SplatExpr) (Expression, Type) { 2006 sourceType := unwrapIterableSourceType(source.Type()) 2007 itemType := sourceType 2008 switch sourceType := sourceType.(type) { 2009 case *ListType: 2010 itemType = sourceType.ElementType 2011 case *SetType: 2012 itemType = sourceType.ElementType 2013 case *TupleType: 2014 itemType, _ = UnifyTypes(sourceType.ElementTypes...) 2015 default: 2016 if sourceType != DynamicType { 2017 var tupleSyntax *hclsyntax.TupleConsExpr 2018 if splatSyntax != nil { 2019 tupleSyntax = &hclsyntax.TupleConsExpr{ 2020 Exprs: []hclsyntax.Expression{splatSyntax.Source}, 2021 SrcRange: splatSyntax.Source.Range(), 2022 OpenRange: splatSyntax.Source.StartRange(), 2023 } 2024 } 2025 2026 source = &TupleConsExpression{ 2027 Syntax: tupleSyntax, 2028 Tokens: syntax.NewTupleConsTokens(1), 2029 Expressions: []Expression{source}, 2030 exprType: NewListType(source.Type()), 2031 } 2032 } 2033 } 2034 return source, itemType 2035 } 2036 2037 func (x *SplatExpression) typecheck(retypeItem, typecheckOperands bool) hcl.Diagnostics { 2038 var diagnostics hcl.Diagnostics 2039 2040 if typecheckOperands { 2041 sourceDiags := x.Source.Typecheck(true) 2042 diagnostics = append(diagnostics, sourceDiags...) 2043 } 2044 2045 if retypeItem { 2046 x.Source, x.Item.VariableType = splatItemType(x.Source, x.Syntax) 2047 } 2048 2049 if typecheckOperands { 2050 eachDiags := x.Each.Typecheck(true) 2051 diagnostics = append(diagnostics, eachDiags...) 2052 } 2053 2054 x.exprType = wrapIterableResultType(x.Source.Type(), NewListType(x.Each.Type())) 2055 2056 return diagnostics 2057 } 2058 2059 func (x *SplatExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 2060 return x.typecheck(true, typecheckOperands) 2061 } 2062 2063 func (x *SplatExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 2064 syntax := &hclsyntax.SplatExpr{ 2065 Source: &syntaxExpr{expr: x.Source}, 2066 Each: &syntaxExpr{expr: x.Each}, 2067 Item: &x.Item.symbol, 2068 } 2069 return syntax.Value(context) 2070 } 2071 2072 func (x *SplatExpression) HasLeadingTrivia() bool { 2073 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Source) 2074 } 2075 2076 func (x *SplatExpression) HasTrailingTrivia() bool { 2077 return exprHasTrailingTrivia(x.Tokens.GetParentheses(), x.Each) 2078 } 2079 2080 func (x *SplatExpression) GetLeadingTrivia() syntax.TriviaList { 2081 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.Source) 2082 } 2083 2084 func (x *SplatExpression) SetLeadingTrivia(t syntax.TriviaList) { 2085 if x.Tokens == nil { 2086 x.Tokens = syntax.NewSplatTokens(false) 2087 } 2088 setExprLeadingTrivia(x.Tokens.Parentheses, &x.Tokens.Open, t) 2089 } 2090 2091 func (x *SplatExpression) GetTrailingTrivia() syntax.TriviaList { 2092 if parens := x.Tokens.GetParentheses(); parens.Any() { 2093 return parens.GetTrailingTrivia() 2094 } 2095 if close := x.Tokens.GetClose(); close != nil { 2096 return close.TrailingTrivia 2097 } 2098 return x.Tokens.GetStar().TrailingTrivia 2099 } 2100 2101 func (x *SplatExpression) SetTrailingTrivia(t syntax.TriviaList) { 2102 if x.Tokens == nil { 2103 x.Tokens = syntax.NewSplatTokens(false) 2104 } 2105 if x.Tokens.Parentheses.Any() { 2106 x.Tokens.Parentheses.SetTrailingTrivia(t) 2107 return 2108 } 2109 if x.Tokens.Close == nil { 2110 x.Tokens.Star.TrailingTrivia = t 2111 return 2112 } 2113 x.Tokens.Close.TrailingTrivia = t 2114 } 2115 2116 func (x *SplatExpression) Format(f fmt.State, c rune) { 2117 x.print(f, &printer{}) 2118 } 2119 2120 func (x *SplatExpression) print(w io.Writer, p *printer) { 2121 isDot := x.Tokens.GetClose() == nil 2122 2123 p.fprintf(w, "%(%v%v%v", x.Tokens.GetParentheses(), x.Source, x.Tokens.GetOpen(), x.Tokens.GetStar()) 2124 if !isDot { 2125 p.fprintf(w, "%v", x.Tokens.GetClose()) 2126 } 2127 p.fprintf(w, "%v%)", x.Each, x.Tokens.GetParentheses()) 2128 } 2129 2130 func (*SplatExpression) isExpression() {} 2131 2132 // TemplateExpression represents a semantically-analyzed template expression. 2133 type TemplateExpression struct { 2134 // The syntax node associated with the template expression. 2135 Syntax *hclsyntax.TemplateExpr 2136 // The tokens associated with the expression, if any. 2137 Tokens *syntax.TemplateTokens 2138 2139 // The parts of the template expression. 2140 Parts []Expression 2141 2142 exprType Type 2143 } 2144 2145 // SyntaxNode returns the syntax node associated with the template expression. 2146 func (x *TemplateExpression) SyntaxNode() hclsyntax.Node { 2147 return x.Syntax 2148 } 2149 2150 // NodeTokens returns the tokens associated with the template expression. 2151 func (x *TemplateExpression) NodeTokens() syntax.NodeTokens { 2152 return x.Tokens 2153 } 2154 2155 // Type returns the type of the template expression. 2156 func (x *TemplateExpression) Type() Type { 2157 return x.exprType 2158 } 2159 2160 func (x *TemplateExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 2161 var diagnostics hcl.Diagnostics 2162 2163 if typecheckOperands { 2164 for _, part := range x.Parts { 2165 partDiags := part.Typecheck(true) 2166 diagnostics = append(diagnostics, partDiags...) 2167 } 2168 } 2169 2170 x.exprType = liftOperationType(StringType, x.Parts...) 2171 return diagnostics 2172 } 2173 2174 func (x *TemplateExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 2175 syntax := &hclsyntax.TemplateExpr{ 2176 Parts: make([]hclsyntax.Expression, len(x.Parts)), 2177 } 2178 for i, p := range x.Parts { 2179 syntax.Parts[i] = &syntaxExpr{expr: p} 2180 } 2181 return syntax.Value(context) 2182 } 2183 2184 func (x *TemplateExpression) HasLeadingTrivia() bool { 2185 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 2186 } 2187 2188 func (x *TemplateExpression) HasTrailingTrivia() bool { 2189 return exprHasTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 2190 } 2191 2192 func (x *TemplateExpression) GetLeadingTrivia() syntax.TriviaList { 2193 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetOpen()) 2194 } 2195 2196 func (x *TemplateExpression) SetLeadingTrivia(t syntax.TriviaList) { 2197 if x.Tokens == nil { 2198 x.Tokens = syntax.NewTemplateTokens() 2199 } 2200 setExprLeadingTrivia(x.Tokens.Parentheses, &x.Tokens.Open, t) 2201 } 2202 2203 func (x *TemplateExpression) GetTrailingTrivia() syntax.TriviaList { 2204 return getExprTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetClose()) 2205 } 2206 2207 func (x *TemplateExpression) SetTrailingTrivia(t syntax.TriviaList) { 2208 if x.Tokens == nil { 2209 x.Tokens = syntax.NewTemplateTokens() 2210 } 2211 setExprTrailingTrivia(x.Tokens.Parentheses, &x.Tokens.Close, t) 2212 } 2213 2214 func (x *TemplateExpression) Format(f fmt.State, c rune) { 2215 x.print(f, &printer{}) 2216 } 2217 2218 func (x *TemplateExpression) print(w io.Writer, p *printer) { 2219 // Print the opening quote. 2220 p.fprintf(w, "%(%v", x.Tokens.GetParentheses(), x.Tokens.GetOpen()) 2221 2222 isHeredoc := x.Tokens.GetOpen().Raw.Type == hclsyntax.TokenOHeredoc 2223 2224 // Print the expressions. 2225 for _, part := range x.Parts { 2226 if lit, ok := part.(*LiteralValueExpression); ok && StringType.AssignableFrom(lit.Type()) { 2227 lit.printLit(w, p, !isHeredoc) 2228 } else { 2229 p.fprintf(w, "%v", part) 2230 } 2231 } 2232 2233 // Print the closing quote 2234 p.fprintf(w, "%v%)", x.Tokens.GetClose(), x.Tokens.GetParentheses()) 2235 } 2236 2237 func (*TemplateExpression) isExpression() {} 2238 2239 // TemplateJoinExpression represents a semantically-analyzed template join expression. 2240 type TemplateJoinExpression struct { 2241 // The syntax node associated with the template join expression. 2242 Syntax *hclsyntax.TemplateJoinExpr 2243 2244 // The tuple being joined. 2245 Tuple Expression 2246 2247 exprType Type 2248 } 2249 2250 // SyntaxNode returns the syntax node associated with the template join expression. 2251 func (x *TemplateJoinExpression) SyntaxNode() hclsyntax.Node { 2252 return x.Syntax 2253 } 2254 2255 // NodeTokens returns the tokens associated with the template join expression. 2256 func (x *TemplateJoinExpression) NodeTokens() syntax.NodeTokens { 2257 return nil 2258 } 2259 2260 // Type returns the type of the template join expression. 2261 func (x *TemplateJoinExpression) Type() Type { 2262 return x.exprType 2263 } 2264 2265 func (x *TemplateJoinExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 2266 var diagnostics hcl.Diagnostics 2267 2268 if typecheckOperands { 2269 tupleDiags := x.Tuple.Typecheck(true) 2270 diagnostics = append(diagnostics, tupleDiags...) 2271 } 2272 2273 x.exprType = liftOperationType(StringType, x.Tuple) 2274 return diagnostics 2275 } 2276 2277 func (x *TemplateJoinExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 2278 syntax := &hclsyntax.TemplateJoinExpr{ 2279 Tuple: &syntaxExpr{expr: x.Tuple}, 2280 } 2281 return syntax.Value(context) 2282 } 2283 2284 func (x *TemplateJoinExpression) HasLeadingTrivia() bool { 2285 return x.Tuple.HasLeadingTrivia() 2286 } 2287 2288 func (x *TemplateJoinExpression) HasTrailingTrivia() bool { 2289 return x.Tuple.HasTrailingTrivia() 2290 } 2291 2292 func (x *TemplateJoinExpression) GetLeadingTrivia() syntax.TriviaList { 2293 return x.Tuple.GetLeadingTrivia() 2294 } 2295 2296 func (x *TemplateJoinExpression) SetLeadingTrivia(t syntax.TriviaList) { 2297 x.Tuple.SetLeadingTrivia(t) 2298 } 2299 2300 func (x *TemplateJoinExpression) GetTrailingTrivia() syntax.TriviaList { 2301 return x.Tuple.GetTrailingTrivia() 2302 } 2303 2304 func (x *TemplateJoinExpression) SetTrailingTrivia(t syntax.TriviaList) { 2305 x.Tuple.SetTrailingTrivia(t) 2306 } 2307 2308 func (x *TemplateJoinExpression) Format(f fmt.State, c rune) { 2309 x.print(f, &printer{}) 2310 } 2311 2312 func (x *TemplateJoinExpression) print(w io.Writer, p *printer) { 2313 p.fprintf(w, "%v", x.Tuple) 2314 } 2315 2316 func (*TemplateJoinExpression) isExpression() {} 2317 2318 // TupleConsExpression represents a semantically-analyzed tuple construction expression. 2319 type TupleConsExpression struct { 2320 // The syntax node associated with the tuple construction expression. 2321 Syntax *hclsyntax.TupleConsExpr 2322 // The tokens associated with the expression, if any. 2323 Tokens *syntax.TupleConsTokens 2324 2325 // The elements of the tuple. 2326 Expressions []Expression 2327 2328 exprType Type 2329 } 2330 2331 // SyntaxNode returns the syntax node associated with the tuple construction expression. 2332 func (x *TupleConsExpression) SyntaxNode() hclsyntax.Node { 2333 return x.Syntax 2334 } 2335 2336 // NodeTokens returns the tokens associated with the tuple construction expression. 2337 func (x *TupleConsExpression) NodeTokens() syntax.NodeTokens { 2338 return x.Tokens 2339 } 2340 2341 // Type returns the type of the tuple construction expression. 2342 func (x *TupleConsExpression) Type() Type { 2343 return x.exprType 2344 } 2345 2346 func (x *TupleConsExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 2347 var diagnostics hcl.Diagnostics 2348 2349 elementTypes := make([]Type, len(x.Expressions)) 2350 for i, expr := range x.Expressions { 2351 if typecheckOperands { 2352 exprDiags := expr.Typecheck(true) 2353 diagnostics = append(diagnostics, exprDiags...) 2354 } 2355 2356 elementTypes[i] = expr.Type() 2357 } 2358 2359 x.exprType = NewTupleType(elementTypes...) 2360 return diagnostics 2361 } 2362 2363 func (x *TupleConsExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 2364 syntax := &hclsyntax.TupleConsExpr{ 2365 Exprs: make([]hclsyntax.Expression, len(x.Expressions)), 2366 } 2367 for i, x := range x.Expressions { 2368 syntax.Exprs[i] = &syntaxExpr{expr: x} 2369 } 2370 return syntax.Value(context) 2371 } 2372 2373 func (x *TupleConsExpression) HasLeadingTrivia() bool { 2374 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 2375 } 2376 2377 func (x *TupleConsExpression) HasTrailingTrivia() bool { 2378 return exprHasTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 2379 } 2380 2381 func (x *TupleConsExpression) GetLeadingTrivia() syntax.TriviaList { 2382 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetOpenBracket()) 2383 } 2384 2385 func (x *TupleConsExpression) SetLeadingTrivia(t syntax.TriviaList) { 2386 if x.Tokens == nil { 2387 x.Tokens = syntax.NewTupleConsTokens(len(x.Expressions)) 2388 } 2389 setExprLeadingTrivia(x.Tokens.Parentheses, &x.Tokens.OpenBracket, t) 2390 } 2391 2392 func (x *TupleConsExpression) GetTrailingTrivia() syntax.TriviaList { 2393 return getExprTrailingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetCloseBracket()) 2394 } 2395 2396 func (x *TupleConsExpression) SetTrailingTrivia(t syntax.TriviaList) { 2397 if x.Tokens == nil { 2398 x.Tokens = syntax.NewTupleConsTokens(len(x.Expressions)) 2399 } 2400 setExprTrailingTrivia(x.Tokens.Parentheses, &x.Tokens.CloseBracket, t) 2401 } 2402 2403 func (x *TupleConsExpression) Format(f fmt.State, c rune) { 2404 x.print(f, &printer{}) 2405 } 2406 2407 func (x *TupleConsExpression) print(w io.Writer, p *printer) { 2408 // Print the opening bracket. 2409 p.fprintf(w, "%(%v", x.Tokens.GetParentheses(), x.Tokens.GetOpenBracket()) 2410 2411 // Print each element and its comma. 2412 commas := x.Tokens.GetCommas(len(x.Expressions)) 2413 p.indented(func() { 2414 for i, expr := range x.Expressions { 2415 if !expr.HasLeadingTrivia() { 2416 p.fprintf(w, "\n%s", p.indent) 2417 } 2418 p.fprintf(w, "%v", expr) 2419 2420 if i != len(x.Expressions)-1 { 2421 var comma syntax.Token 2422 if i < len(commas) { 2423 comma = commas[i] 2424 } 2425 p.fprintf(w, "%v", comma) 2426 } 2427 } 2428 2429 // If there were commas left over, print the trivia for each. 2430 // 2431 // TODO(pdg): filter to only comments? 2432 if len(x.Expressions) > 0 && len(x.Expressions)-1 <= len(commas) { 2433 for _, comma := range commas[len(x.Expressions)-1:] { 2434 p.fprintf(w, "%v", comma.AllTrivia().CollapseWhitespace()) 2435 } 2436 } 2437 }) 2438 2439 // Print the closing bracket. 2440 if x.Tokens != nil { 2441 p.fprintf(w, "%v%)", x.Tokens.CloseBracket, x.Tokens.GetParentheses()) 2442 } else { 2443 p.fprintf(w, "\n%s]", p.indent) 2444 } 2445 } 2446 2447 func (*TupleConsExpression) isExpression() {} 2448 2449 // UnaryOpExpression represents a semantically-analyzed unary operation. 2450 type UnaryOpExpression struct { 2451 // The syntax node associated with the unary operation. 2452 Syntax *hclsyntax.UnaryOpExpr 2453 // The tokens associated with the expression, if any. 2454 Tokens *syntax.UnaryOpTokens 2455 2456 // The operation. 2457 Operation *hclsyntax.Operation 2458 // The operand of the operation. 2459 Operand Expression 2460 2461 operandType Type 2462 exprType Type 2463 } 2464 2465 // SyntaxNode returns the syntax node associated with the unary operation. 2466 func (x *UnaryOpExpression) SyntaxNode() hclsyntax.Node { 2467 return x.Syntax 2468 } 2469 2470 // NodeTokens returns the tokens associated with the unary operation. 2471 func (x *UnaryOpExpression) NodeTokens() syntax.NodeTokens { 2472 return x.Tokens 2473 } 2474 2475 // OperandType returns the operand type of the unary operation. 2476 func (x *UnaryOpExpression) OperandType() Type { 2477 return x.operandType 2478 } 2479 2480 // Type returns the type of the unary operation. 2481 func (x *UnaryOpExpression) Type() Type { 2482 return x.exprType 2483 } 2484 2485 func (x *UnaryOpExpression) Typecheck(typecheckOperands bool) hcl.Diagnostics { 2486 var diagnostics hcl.Diagnostics 2487 2488 if typecheckOperands { 2489 operandDiags := x.Operand.Typecheck(true) 2490 diagnostics = append(diagnostics, operandDiags...) 2491 } 2492 2493 // Compute the signature for the operator and typecheck the arguments. 2494 signature := getOperationSignature(x.Operation) 2495 contract.Assert(len(signature.Parameters) == 1) 2496 2497 x.operandType = signature.Parameters[0].Type 2498 2499 var rng hcl.Range 2500 if x.Syntax != nil { 2501 rng = x.Syntax.Range() 2502 } 2503 typecheckDiags := typecheckArgs(rng, signature, x.Operand) 2504 diagnostics = append(diagnostics, typecheckDiags...) 2505 2506 x.exprType = liftOperationType(signature.ReturnType, x.Operand) 2507 return diagnostics 2508 } 2509 2510 func (x *UnaryOpExpression) Evaluate(context *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 2511 syntax := &hclsyntax.UnaryOpExpr{ 2512 Op: x.Operation, 2513 Val: &syntaxExpr{expr: x.Operand}, 2514 } 2515 return syntax.Value(context) 2516 } 2517 2518 func (x *UnaryOpExpression) HasLeadingTrivia() bool { 2519 return exprHasLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens != nil) 2520 } 2521 2522 func (x *UnaryOpExpression) HasTrailingTrivia() bool { 2523 return exprHasTrailingTrivia(x.Tokens.GetParentheses(), x.Operand) 2524 } 2525 2526 func (x *UnaryOpExpression) GetLeadingTrivia() syntax.TriviaList { 2527 return getExprLeadingTrivia(x.Tokens.GetParentheses(), x.Tokens.GetOperator(x.Operation)) 2528 } 2529 2530 func (x *UnaryOpExpression) SetLeadingTrivia(t syntax.TriviaList) { 2531 if x.Tokens == nil { 2532 x.Tokens = syntax.NewUnaryOpTokens(x.Operation) 2533 } 2534 setExprLeadingTrivia(x.Tokens.Parentheses, &x.Tokens.Operator, t) 2535 } 2536 2537 func (x *UnaryOpExpression) GetTrailingTrivia() syntax.TriviaList { 2538 return getExprTrailingTrivia(x.Tokens.GetParentheses(), x.Operand) 2539 } 2540 2541 func (x *UnaryOpExpression) SetTrailingTrivia(t syntax.TriviaList) { 2542 if x.Tokens == nil { 2543 x.Tokens = syntax.NewUnaryOpTokens(x.Operation) 2544 } 2545 setExprTrailingTrivia(x.Tokens.Parentheses, x.Operand, t) 2546 } 2547 2548 func (x *UnaryOpExpression) Format(f fmt.State, c rune) { 2549 x.print(f, &printer{}) 2550 } 2551 2552 func (x *UnaryOpExpression) print(w io.Writer, p *printer) { 2553 precedence := operatorPrecedence(x.Operation) 2554 p.fprintf(w, "%[2](%[3]v%.[1]*[4]v%[5])", 2555 precedence, 2556 x.Tokens.GetParentheses(), 2557 x.Tokens.GetOperator(x.Operation), x.Operand, 2558 x.Tokens.GetParentheses()) 2559 } 2560 2561 func (*UnaryOpExpression) isExpression() {}