Repository: aws-cloudformation/rain
Pull request #222 (2023-12-11 23:35:33)

Fix format bug with greater than in multi-line string


Patch:
diff --git a/cft/format/format.go b/cft/format/format.go
index 3174335f..4b045ef9 100644
--- a/cft/format/format.go
+++ b/cft/format/format.go
@@ -78,7 +78,7 @@ func String(t cft.Template, opt Options) string {
 			}
 		}
 		trimmedRight := strings.TrimRight(part, " ")
-		if CheckMultilineBegin(trimmedRight) {
+		if !isMultiline && CheckMultilineBegin(trimmedRight) {
 			startMultilineIndent = indent
 		}
 


Test patch:
diff --git a/cft/format/format_test.go b/cft/format/format_test.go
index f887d21d..649f1ec2 100644
--- a/cft/format/format_test.go
+++ b/cft/format/format_test.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/aws-cloudformation/rain/cft/format"
 	"github.com/aws-cloudformation/rain/cft/parse"
+	"github.com/aws-cloudformation/rain/internal/config"
 	"github.com/google/go-cmp/cmp"
 )
 
@@ -453,3 +454,184 @@ func TestFormatDefault(t *testing.T) {
 	checkMultilineBlockHeaders(t, correctMultilineBlockHeaders, true)
 	checkMultilineBlockHeaders(t, wrongMultilineBlockHeaders, false)
 }
+
+func TestFindInMap(t *testing.T) {
+	yaml := `
+AWSTemplateFormatVersion: '2010-09-09'
+
+Description: Reproduce "semantic difference after formatting" error
+
+Parameters:
+  EnvironmentParam:
+    Default: dev
+    Type: String
+    AllowedValues:
+      - dev
+      - prod
+
+Mappings:
+  EnvironmentMap:
+    MappedParam:
+      dev: my-dev-topic
+      prod: my-prod-topic
+
+Resources:
+  Topic:
+    Type: AWS::SNS::Topic
+    Properties: 
+      TopicName: !FindInMap [EnvironmentMap, MappedParam, !Ref EnvironmentParam]
+`
+
+	expect := `AWSTemplateFormatVersion: "2010-09-09"
+
+Description: Reproduce "semantic difference after formatting" error
+
+Parameters:
+  EnvironmentParam:
+    Default: dev
+    Type: String
+    AllowedValues:
+      - dev
+      - prod
+
+Mappings:
+  EnvironmentMap:
+    MappedParam:
+      dev: my-dev-topic
+      prod: my-prod-topic
+
+Resources:
+  Topic:
+    Type: AWS::SNS::Topic
+    Properties:
+      TopicName: !FindInMap [EnvironmentMap, MappedParam, !Ref EnvironmentParam]
+`
+
+	template, err := parse.String(yaml)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	actual := format.String(template, format.Options{
+		Unsorted: true,
+	})
+
+	if d := cmp.Diff(expect, actual); d != "" {
+		t.Fatalf(d)
+	}
+}
+
+func TestZipLines(t *testing.T) {
+	yaml := `
+  AWSTemplateFormatVersion: "2010-09-09"
+
+  Description: Example AWS CloudFormation template snippet.
+  
+  Resources:
+    Test:
+      Type: AWS::Lambda::Function
+      Properties:
+        Role: arn:aws:iam::755952356119:role/lambda-basic
+        Runtime: python3.7
+        Handler: index.handler
+        Code:
+          ZipFile: |
+            import boto3
+  
+            def handler: 
+  
+              """Example."""
+  
+              print('hello')
+   
+  `
+
+	expect := `AWSTemplateFormatVersion: "2010-09-09"
+
+Description: Example AWS CloudFormation template snippet.
+
+Resources:
+  Test:
+    Type: AWS::Lambda::Function
+    Properties:
+      Role: arn:aws:iam::755952356119:role/lambda-basic
+      Runtime: python3.7
+      Handler: index.handler
+      Code:
+        ZipFile: "import boto3\n\ndef handler: \n\n  \"\"\"Example.\"\"\"\n\n  print('hello')\n"
+`
+
+	template, err := parse.String(yaml)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	actual := format.String(template, format.Options{
+		Unsorted: true,
+	})
+
+	if d := cmp.Diff(expect, actual); d != "" {
+		t.Fatalf(d)
+	}
+}
+
+func TestMultiWithGT(t *testing.T) {
+	yaml := `
+AWSTemplateFormatVersion: "2010-09-09"
+
+Description: Example AWS CloudFormation template snippet.
+
+Resources:
+  Test:
+    Type: AWS::Lambda::Function
+    Properties:
+      Code:
+        ZipFile: |
+          """Example."""
+
+          import boto3
+
+          breaks = """
+          >
+          """
+
+          TEST = 1
+  `
+
+	expect := `AWSTemplateFormatVersion: "2010-09-09"
+
+Description: Example AWS CloudFormation template snippet.
+
+Resources:
+  Test:
+    Type: AWS::Lambda::Function
+    Properties:
+      Code:
+        ZipFile: |
+          """Example."""
+
+          import boto3
+
+          breaks = """
+          >
+          """
+
+          TEST = 1
+`
+
+	template, err := parse.String(yaml)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	actual := format.String(template, format.Options{
+		Unsorted: true,
+	})
+
+	config.Debug = true
+	config.Debugf(actual)
+
+	if d := cmp.Diff(expect, actual); d != "" {
+		t.Fatalf(d)
+	}
+}
diff --git a/test/templates/fmtmultiwithgt.yaml b/test/templates/fmtmultiwithgt.yaml
new file mode 100644
index 00000000..ac5338be
--- /dev/null
+++ b/test/templates/fmtmultiwithgt.yaml
@@ -0,0 +1,19 @@
+AWSTemplateFormatVersion: "2010-09-09"
+
+Description: Example AWS CloudFormation template snippet.
+
+Resources:
+  Test:
+    Type: AWS::Lambda::Function
+    Properties:
+      Code:
+        ZipFile: |
+          """Example."""
+
+          import boto3
+
+          breaks = """
+          >
+          """
+
+          TEST = 1
\ No newline at end of file