Repository: nix-community/nixpkgs-fmt (rust)

Issue:
No inner indentation inside multiline comments
Multiline `/* */` comments are being aggressively reindented, to the point of losing any inner indentation. Examples were taken from https://github.com/NixOS/nixpkgs/blob/e1ff5c3d8c4ca7101f2c820f85d8290303deaa53/lib/strings.nix#L178-L185 and https://github.com/AluisioASG/nixexprs/blob/4b5399b1f065b1ba2703e84ac96827ab9b47c5e7/lib/attrsets.nix#L37-L42.

## Input
```nix
{
  /* Construct a binary search path (such as $PATH) containing the
     binaries for a set of packages.
     Example:
       makeBinPath ["/root" "/usr" "/usr/local"]
       => "/root/bin:/usr/bin:/usr/local/bin"
  */
  makeBinPath = makeSearchPathOutput "bin" "bin";

  /* concatMapAttrsToList :: (string -> any -> [any]) -> set -> [any]
   *
   * Like mapAttrsToList, but allows multiple values to be returned
   * from the mapping function as a list.
   */
  concatMapAttrsToList = mapper: attrs: concatLists (mapAttrsToList mapper attrs);
}
```

## Output
```nix
{
  /* Construct a binary search path (such as $PATH) containing the
    binaries for a set of packages.
    Example:
    makeBinPath ["/root" "/usr" "/usr/local"]
    => "/root/bin:/usr/bin:/usr/local/bin"
  */
  makeBinPath = makeSearchPathOutput "bin" "bin";

  /* concatMapAttrsToList :: (string -> any -> [any]) -> set -> [any]
    *
    * Like mapAttrsToList, but allows multiple values to be returned
    * from the mapping function as a list.
  */
  concatMapAttrsToList = mapper: attrs: concatLists (mapAttrsToList mapper attrs);
}

```

## Desired output

Same as the input. Ideally text would be aligned to the text in the first line and not to the space preceding it, and decorations would be preserved, but I suspect both could be achieved by simple preserving relative indentation inside the comment.

Pull request:
fix multiline comment
This PR fix #243 

Patch:
diff --git a/src/engine/fixes.rs b/src/engine/fixes.rs
index 047e4a8..b699530 100644
--- a/src/engine/fixes.rs
+++ b/src/engine/fixes.rs
@@ -5,6 +5,7 @@ use rnix::{
     SyntaxKind::{NODE_STRING, TOKEN_COMMENT, TOKEN_STRING_CONTENT, TOKEN_WHITESPACE},
     SyntaxNode, SyntaxToken, TextRange, TextSize,
 };
+use smol_str::SmolStr;
 
 use super::indentation::single_line_comment_indent;
 use crate::{
@@ -121,23 +122,21 @@ fn fix_comment_indentation(
             first = false;
             continue;
         }
-        let last_line_only_end_block = line.ends_with("*/") && line.trim_start() == "*/";
+        let last_line_only_end_block = line.ends_with("*/") || line.trim_start() == "*/";
+        let start_with_asterisk = line.trim_start().starts_with("*");
+        let current_indent = IndentLevel::get_whitespace_block(line);
         if let Some(ws_end) = line.find(|it| it != ' ') {
-            if !last_line_only_end_block {
+            let delete =
+                TextRange::at(offset, TextSize::try_from(ws_end).expect("woah big number"));
+            if last_line_only_end_block || start_with_asterisk {
                 model.raw_edit(AtomEdit {
-                    delete: TextRange::at(
-                        offset,
-                        TextSize::try_from(ws_end).expect("woah big number"),
-                    ),
-                    insert: content_indent.into(),
+                    delete,
+                    insert: comment_indent.add_alignment(current_indent).into(),
                 })
             } else {
                 model.raw_edit(AtomEdit {
-                    delete: TextRange::at(
-                        offset,
-                        TextSize::try_from(ws_end).expect("woah big number"),
-                    ),
-                    insert: comment_indent.into(),
+                    delete,
+                    insert: content_indent.adjust_alignment(current_indent).into(),
                 })
             }
         }
diff --git a/src/engine/indentation.rs b/src/engine/indentation.rs
index 40e1a05..2eda9da 100644
--- a/src/engine/indentation.rs
+++ b/src/engine/indentation.rs
@@ -4,6 +4,7 @@ use std::{
 };
 
 use rnix::{SyntaxElement, SyntaxKind::*, SyntaxNode, SyntaxToken, TextSize};
+use serde_json::from_str;
 use smol_str::SmolStr;
 
 use crate::{
@@ -88,6 +89,29 @@ impl IndentLevel {
         IndentLevel { level: len / INDENT_SIZE, alignment: len % INDENT_SIZE }
     }
 
+    /// adjust `IndentLevel` based on whitespace provided
+    pub(super) fn adjust_alignment(self, new_indent: IndentLevel) -> IndentLevel {
+        if new_indent.len() > TextSize::from(5) {
+            return new_indent;
+        }
+        IndentLevel { level: self.level, alignment: new_indent.alignment }
+    }
+
+    /// adding alignment for multiline comment
+    pub(super) fn add_alignment(self, new_indent: IndentLevel) -> IndentLevel {
+        if self.level < new_indent.level {
+            return new_indent;
+        }
+        IndentLevel { level: self.level, alignment: new_indent.alignment }
+    }
+
+    pub(super) fn get_whitespace_block(s: &str) -> IndentLevel {
+        match s.find(|c: char| !c.is_whitespace()) {
+            None => IndentLevel::default(),
+            Some(idx) => IndentLevel::from_str(&s[..idx]),
+        }
+    }
+
     pub(super) fn from_whitespace_block(s: &str) -> IndentLevel {
         match s.rfind('\n') {
             None => IndentLevel::default(),


Test patch:
diff --git a/test_data/reindents_block_comments.bad.nix b/test_data/reindents_block_comments.bad.nix
index 63259cd..eeb6e48 100644
--- a/test_data/reindents_block_comments.bad.nix
+++ b/test_data/reindents_block_comments.bad.nix
@@ -1,17 +1,30 @@
 {
 /* 
-decoreted
-block
-comment
+  decorated
+  block
+  comment
 */
 foo = 92;
-    /* the closing block comment
-       should not in the newline */
+  /* the closing block comment
+     should not in the newline */
   toPretty = {
-    /* the closing block comment
-       should be aligned with the opening block comment
+      /* the closing block comment
+       * should be aligned with the opening block comment
        */
       allowPrettyValues ? false
     }@args:
     let a = 0; in a;
-}
+  /* Construct a binary search path (such as $PATH) containing the
+     binaries for a set of packages.
+     Example:
+       makeBinPath ["/root" "/usr" "/usr/local"]
+       => "/root/bin:/usr/bin:/usr/local/bin"
+  */
+makeBinPath = makeSearchPathOutput "bin" "bin";
+/* concatMapAttrsToList :: (string -> any -> [any]) -> set -> [any]
+ *
+ * Like mapAttrsToList, but allows multiple values to be returned
+ * from the mapping function as a list.
+ */
+concatMapAttrsToList = mapper: attrs: concatLists (mapAttrsToList mapper attrs);
+}
\ No newline at end of file
diff --git a/test_data/reindents_block_comments.good.nix b/test_data/reindents_block_comments.good.nix
index 325299f..e3aee94 100644
--- a/test_data/reindents_block_comments.good.nix
+++ b/test_data/reindents_block_comments.good.nix
@@ -1,18 +1,31 @@
 {
   /* 
-    decoreted
+    decorated
     block
     comment
   */
   foo = 92;
   /* the closing block comment
-    should not in the newline */
+     should not in the newline */
   toPretty =
     {
       /* the closing block comment
-        should be aligned with the opening block comment
-      */
+       * should be aligned with the opening block comment
+       */
       allowPrettyValues ? false
     }@args:
     let a = 0; in a;
+  /* Construct a binary search path (such as $PATH) containing the
+     binaries for a set of packages.
+     Example:
+       makeBinPath ["/root" "/usr" "/usr/local"]
+       => "/root/bin:/usr/bin:/usr/local/bin"
+  */
+  makeBinPath = makeSearchPathOutput "bin" "bin";
+  /* concatMapAttrsToList :: (string -> any -> [any]) -> set -> [any]
+   *
+   * Like mapAttrsToList, but allows multiple values to be returned
+   * from the mapping function as a list.
+   */
+  concatMapAttrsToList = mapper: attrs: concatLists (mapAttrsToList mapper attrs);
 }