Repository: smithy-lang/smithy (java)

Issue:
How to get smithy-format to keep resource identifiers and properties on separate lines
I have a smithy file like this:

```smithy
resource PackageVersionTag {
    identifiers: {
        name: PackageName
        tag: Tag
    }
    properties: {
        version: Version
    }
    put: PutPackageVersionTag
    read: GetPackageVersionTag
}
```

When I run `smithy format`, it condenses identifiers and properties like this:
```smithy
resource PackageVersionTag {
    identifiers: {name: PackageName, tag: Tag}
    properties: {version: Version}
    put: PutPackageVersionTag
    read: GetPackageVersionTag
}
```

Is there a way to configure the formatter to avoid compressing these sections? I find it more readable to have the original code with line-breaks in it

Pull request:
Put the KVPs of identifiers and properties fields of resource shapes on their own lines
### Background
#### What do these changes do? 
Updates the formatting logic to put the key-value pairs of the `identifiers` and `properties` fields of `resource` shapes on individual lines instead of combining them onto a single line

#### Why are they important?
While the existing formatting works for simple single-identifier resources, resources with multiple identifiers quickly become unwieldy due to their identifiers being forced onto a single line.

For identifiers this is only an annoyance because most resources only have 1 or 2 identifiers.  For properties, this can easily get out of hand because resources will generally have many resources.  

For example, this is the current formatted version of a resource within a service I'm currently developing: 
```
resource FooBar {
    identifiers: { fooId: FooId, FooBarId: FooBarId }
    properties: { previousFooBarId: FooBarId, fizz: String, buzz: String, baz: BazId, createdAt: Timestamp }
    create: CreateFooBar
    read: GetFooBar
    list: ListFooBar
}
```

My argument here is that the following format is more easy to parse as a reviewer:
```
resource FooBar {
    identifiers: {
        fooId: FooId
        FooBarId: FooBarId
    }
    properties: { 
        previousFooBarId: FooBarId
        fizz: String
        buzz: String
        baz: BazId
        createdAt: Timestamp 
    }
    create: CreateFooBar
    read: GetFooBar
    list: ListFooBar
}
```

### Alternatives
An alternative I'm willing to look into implementing is updating the logic that currently forces all of the items of key-value pairs inside of objects into being smarter about when to place the items on a single line.  A reasonable behavior in my opinion would be for it to keep values to a single line if there's only a single item, switching to the multi-line behavior when there's more than a single item.

### Testing
* Updated and improved corpus tests for the formatter to verify the updated behavior works as expected

### Links
* Resolves #2104 

---
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.


Patch:
diff --git a/smithy-syntax/src/main/java/software/amazon/smithy/syntax/FormatVisitor.java b/smithy-syntax/src/main/java/software/amazon/smithy/syntax/FormatVisitor.java
index 2f8eadfe4..8136c25f6 100644
--- a/smithy-syntax/src/main/java/software/amazon/smithy/syntax/FormatVisitor.java
+++ b/smithy-syntax/src/main/java/software/amazon/smithy/syntax/FormatVisitor.java
@@ -769,6 +769,8 @@ final class FormatVisitor {
                 case "collectionOperations":
                 case "errors":
                     return formatNodeObjectKvp(c, FormatVisitor.this::visit, hardLineList);
+                case "identifiers":
+                case "properties":
                 case "rename":
                     return formatNodeObjectKvp(c, FormatVisitor.this::visit, hardLineObject);
                 default:


Test patch:
diff --git a/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes-line-break.formatted.smithy b/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes-line-break.formatted.smithy
index 76a25c8f7..5c700c0e3 100644
--- a/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes-line-break.formatted.smithy
+++ b/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes-line-break.formatted.smithy
@@ -30,7 +30,16 @@ operation GetTime2 {
 
 @http(method: "X", uri: "/foo", code: 200)
 resource Sprocket2 {
-    identifiers: { username: String, id: String, otherId: String }
+    identifiers: {
+        username: String
+        id: String
+        otherId: String
+    }
+    properties: {
+        foo: String
+        bar: Integer
+        fizz: String
+    }
 }
 
 @error("client")
diff --git a/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes-line-break.smithy b/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes-line-break.smithy
index 314544851..3f6389fff 100644
--- a/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes-line-break.smithy
+++ b/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes-line-break.smithy
@@ -24,7 +24,10 @@ operation GetTime2 {
 
 @http(method: "X", uri: "/foo", code: 200)
 resource Sprocket2 {
-    identifiers: {username: String, id: String, otherId: String}
+    identifiers: {username: String, id: String
+                  otherId: String}
+    properties: {foo: String,bar: Integer
+                 fizz: String }
 }
 
 @error("client")
diff --git a/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes.smithy b/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes.smithy
index ce49d2b3a..4a7610247 100644
--- a/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes.smithy
+++ b/smithy-syntax/src/test/resources/software/amazon/smithy/syntax/formatter/entity-shapes.smithy
@@ -33,12 +33,22 @@ operation GetTime2 {
 }
 
 resource Sprocket1 {
-    identifiers: { username: String }
+    identifiers: {
+        username: String
+    }
+    properties: {
+        foo: String
+        bar: Integer
+    }
 }
 
 @http(method: "X", uri: "/foo", code: 200)
 resource Sprocket2 {
-    identifiers: { username: String, id: String, otherId: String }
+    identifiers: {
+        username: String
+        id: String
+        otherId: String
+    }
     collectionOperations: [
         SomeOperation
     ]
@@ -54,7 +64,13 @@ structure SomeOperationFoo {}
 
 @http(method: "X", uri: "/foo3", code: 200)
 resource Sprocket3 {
-    identifiers: { username: String, id: String, otherId: String }
+    identifiers: {
+        username: String
+        id: String
+        otherId: String
+    }
+    // It's empty, so on a single line.
+    properties: {}
     // It's empty, so on a single line.
     collectionOperations: []
 }