Repository: smithy-lang/smithy (java)

Issue:
IDL Model serializer ignores trailing whitespace in documentation
If you parse this model:

```smithy
namespace test

@documentation("foo 
bar")
string Demo
```

_**very important:** there's a space after foo, before the newline._

then the value of the `documentation` trait is: `"foo \nbar"`, which I think is correct.

If you serialize that with the `SmithyIdlModelSerializer`, it gets turned into:

```smithy
$version: "2.0"
namespace test

/// foo
/// bar
string Demo
```

and the trailing space is gone. As a result, if you parse that again, you no longer have the same documentation trait value (it's `foo\nbar` instead), which causes the following problems for my team:

1. model merging considers these shapes different (because of the trait change), which fails to assemble.

2. Name uniqueness checks start to consider the shape different from its original counterpart (for a specific reason, we have an identical shape in another namespace, but it's used verbatim instead of being parsed + serialized, so it still has the trailing space).

---

I think this is an inconsistency in the serializer - as much as I love to remove trailing whitespace, it clearly can cause subtle bugs.

Full example, a scala-cli script:

```scala
//> using dep "software.amazon.smithy:smithy-model:1.43.0"
//> using option "-Wunused:all"
import software.amazon.smithy.model.shapes.SmithyIdlModelSerializer

import software.amazon.smithy.model.traits.DocumentationTrait
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.model.Model
import scala.jdk.CollectionConverters._

val input =
  s"""
     |namespace test
     |
     |@documentation("foo${" " /* this ensures we have trailing whitespace no matter what editor config you use */}
     |bar")
     |string Demo
     |""".stripMargin
val m1 = Model
  .assembler()
  .addUnparsedModel(
    "test.smithy",
    input
  )
  .assemble()
  .unwrap()

val docValue = m1
  .expectShape(ShapeId.from("test#Demo"))
  .getTrait(classOf[DocumentationTrait])
  .get
  .getValue

println(docValue == "foo \nbar") //true

val serialized = SmithyIdlModelSerializer
  .builder()
  .build()
  .serialize(m1)
  .asScala
  .head
  ._2

val m2 = Model
  .assembler()
  .addUnparsedModel(
    "test.smithy",
    serialized
  )
  .assemble()
  .unwrap()

val docValue2 = m2
  .expectShape(ShapeId.from("test#Demo"))
  .getTrait(classOf[DocumentationTrait])
  .get
  .getValue

println(docValue2 == "foo\nbar") //true
```

Edit: this is also inconsistent with the `ModelSerializer` which encodes as a `Node` - that one keeps the whitespace.

Pull request description:
Keep trailing doc comment spaces in IDL serializer
Closes #2115

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-model/src/main/java/software/amazon/smithy/model/shapes/SmithyIdlModelSerializer.java b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/SmithyIdlModelSerializer.java
index ec6283390..a48cce531 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/shapes/SmithyIdlModelSerializer.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/shapes/SmithyIdlModelSerializer.java
@@ -532,9 +532,13 @@ public final class SmithyIdlModelSerializer {
 
         private void serializeDocumentation(String documentation) {
             // The documentation trait has a special syntax, which we always want to use.
-            codeWriter.setNewlinePrefix("/// ")
+            codeWriter
+                    .pushState()
+                    // See https://github.com/smithy-lang/smithy/issues/2115
+                    .trimTrailingSpaces(false)
+                    .setNewlinePrefix("/// ")
                     .write(documentation.replace("$", "$$"))
-                    .setNewlinePrefix("");
+                    .popState();
         }
 
         private void serializeTrait(Trait trait) {


Test patch:
diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/shapes/idl-serialization/cases/trailing-space-in-docs.smithy b/smithy-model/src/test/resources/software/amazon/smithy/model/shapes/idl-serialization/cases/trailing-space-in-docs.smithy
new file mode 100644
index 000000000..3fbaf72c2
--- /dev/null
+++ b/smithy-model/src/test/resources/software/amazon/smithy/model/shapes/idl-serialization/cases/trailing-space-in-docs.smithy
@@ -0,0 +1,9 @@
+$version: "2.0"
+
+namespace com.example
+
+/// This line has trailing spaces  
+/// This line does not have trailing spaces
+/// This line has one trailing space 
+/// Addresses https://github.com/smithy-lang/smithy/issues/2115
+string TestString