Subject: Re: [PATCH] pg_bsd_indent: improve formatting of multiline comments

From: Aleksander Alekseev <[email-masked]>
Date: Mon, 9 Feb 2026 14:19:16 +0300

Hi,

> > Here's a patch for this.  I also changed the #undefs to #defines.
>
> I went ahead and committed this.

Thanks, Nathan. Re-submitting v6 to make it visible by cfbot again and
in order to simplify the work of reviewers a bit.

-- 
Best regards,
Aleksander Alekseev
From ad91fda8a7406f9fd5dbbfe5a895a811230e2eec Mon Sep 17 00:00:00 2001
From: Aleksander Alekseev <[email-masked]>
Date: Fri, 20 Jun 2025 16:31:36 +0300
Subject: [PATCH v6] pgindent: improve formatting of multiline comments

Format multiline comments like this:

/* line 1
 * line 2
 */

... into:

/*
 * line 1
 * line 2
 */

This is more consistent with what we currently have in the tree.

Author: Aleksander Alekseev <[email-masked]>
Reported-by: Michael Paquier <[email-masked]>
Reviewed-by: Arseniy Mukhin <[email-masked]>
Reviewed-by: Nathan Bossart <[email-masked]>
Discussion: https://postgr.es/m/CAJ7c6TPQ0kkHQG-AqeAJ3PV_YtmDzcc7s%2B_V4%3Dt%2BxgSnZm1cFw%40mail.gmail.com
---
 src/tools/pgindent/pgindent | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/src/tools/pgindent/pgindent b/src/tools/pgindent/pgindent
index b7d71808924..4db12cb1d92 100755
--- a/src/tools/pgindent/pgindent
+++ b/src/tools/pgindent/pgindent
@@ -281,6 +281,9 @@ sub post_indent
 	# Fix run-together comments to have a tab between them
 	$source =~ s!\*/(/\*.*\*/)$!*/\t$1!gm;
 
+	# Postprocess multiline comments except for /**... and /*-... ones
+	$source =~ s!^(/\*[^\*\-].*?\*/)!postprocess_multiline_comment($1)!mgse;
+
 	## Functions
 
 	# Use a single space before '*' in function return types
@@ -289,6 +292,39 @@ sub post_indent
 	return $source;
 }
 
+sub postprocess_multiline_comment
+{
+    my $source = shift;
+    my @lines = split "\n", $source;
+
+    # Only format comments that match the expected format,
+    # or at least that could have been the author's intent.
+    if (($lines[0] ne "/*" && $lines[-1] ne " */") or ($lines[1] !~ m!^ \*!))
+    {
+        return $source;
+    }
+
+    # Check each line except for the first and the last one
+    for my $i ( 1 .. scalar @lines - 2 )
+    {
+        $lines[$i] = " *".$lines[$i] if $lines[$i] !~ /^ \*/;
+    }
+
+    # Keep /* === and /* --- lines as is
+    if ($lines[0] !~ m!^/\* [=-]+!) {
+        $lines[0] =~ s!/\*(.+)!/\*\n *$1!;
+    }
+
+    # Keep === */ and --- */ lines as is
+    if ($lines[-1] !~ m![=-]+ \*/$!) {
+        $lines[-1] =~ s!(.+) \*/!$1\n \*/!;
+    }
+
+    $source = join "\n", @lines;
+
+    return $source;
+}
+
 sub run_indent
 {
 	my $source = shift;
-- 
2.43.0

---

From: Tom Lane <[email-masked]>
Date: Mon, 04 May 2026 12:40:19 -0400

> in order to simplify the work of reviewers a bit.

I tested the v6 patch by running it on current HEAD.  Pretty nearly all
the changes it makes are improvements, but it seems like there's still
some work to be done.  In particular, in src/port/inet_aton.c it
produces this diff:

--- a/src/port/inet_aton.c
+++ b/src/port/inet_aton.c
@@ -36,7 +37,8 @@
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.  */
+ * SUCH DAMAGE. 
+ */
 
 #include "c.h"

in which not all the trailing whitespace has been removed from the
first line, causing "git diff --check" to complain:

$ git diff --check
src/port/inet_aton.c:40: trailing whitespace.
+ * SUCH DAMAGE. 

In this case the problem is that the cleanup pattern only accounts for
one trailing space.  But a variant of this, which I think affects many
of the steps in the patch, is that there could be tab(s) there.  You
should fix the patterns to allow any number of spaces/tabs at the
spots where they currently expect just one space.  This might result
in finding cleanups they miss now.

Another amusing diff I noticed:

--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -5713,7 +5713,7 @@ check_parent_values_in_new_partitions(Relation parent,
  * 3. In case new partitions don't contain the DEFAULT partition and the
  *	  partitioned table does not have the DEFAULT partition, the following
  *	  should be true: the sum of the bounds of new partitions should be equal
- &	  to the bound of the split partition.
+ * &	  to the bound of the split partition.
  *
  * parent:			partitioned table
  * splitPartOid:	split partition Oid

Clearly, this is somebody's off-by-one-key typo, and the correct
fix is s/&/*/.  I suspect that fixing that manually is the most
expedient answer, rather than trying to make pg_bsd_indent smart
enough to DTRT.

One other nitpick is that the patch itself needs to be run through
pgperltidy (which has different opinions than your editor about
tabs vs spaces, apparently).

			regards, tom lane

---

From: Nathan Bossart <[email-masked]>
Date: Mon, 4 May 2026 12:11:23 -0500

> expedient answer, rather than trying to make pg_bsd_indent smart

+1.  This patch has been rather good at finding small mistakes like this,
which I've been manually fixing along the way.

-- 
nathan

---

From: Aleksander Alekseev <[email-masked]>
Date: Tue, 5 May 2026 16:06:21 +0300

Hi Tom,

Thanks for your feedback.

> in finding cleanups they miss now.

Fair point. Fixed.

> [...]

Agree.

> tabs vs spaces, apparently).

Fixed in v7.

-- 
Best regards,
Aleksander Alekseev
From 7c3abf671bafaf3a5425994e9cfedf5dafaf9895 Mon Sep 17 00:00:00 2001
From: Aleksander Alekseev <[email-masked]>
Date: Fri, 20 Jun 2025 16:31:36 +0300
Subject: [PATCH v7] pgindent: improve formatting of multiline comments

/* line 1
 * line 2
 */

... into:

/*
 * line 1
 * line 2
 */

Author: Aleksander Alekseev <[email-masked]>
Reported-by: Michael Paquier <[email-masked]>
Reviewed-by: Arseniy Mukhin <[email-masked]>
Reviewed-by: Nathan Bossart <[email-masked]>
Reviewed-by: Tom Lane <[email-masked]>
Discussion: https://postgr.es/m/CAJ7c6TPQ0kkHQG-AqeAJ3PV_YtmDzcc7s%2B_V4%3Dt%2BxgSnZm1cFw%40mail.gmail.com
---
 src/tools/pgindent/pgindent | 40 +++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/src/tools/pgindent/pgindent b/src/tools/pgindent/pgindent
index b2ec5e2914b..f4be74fc3a4 100755
--- a/src/tools/pgindent/pgindent
+++ b/src/tools/pgindent/pgindent
@@ -285,6 +285,9 @@ sub post_indent
 	# Fix run-together comments to have a tab between them
 	$source =~ s!\*/(/\*.*\*/)$!*/\t$1!gm;

 	# Use a single space before '*' in function return types
@@ -293,6 +296,43 @@ sub post_indent
 	return $source;
 }
 
+sub postprocess_multiline_comment
+{
+	my $source = shift;
+	my @lines = split "\n", $source;
+
+	# Only format comments that match the expected format,
+	# or at least that could have been the author's intent.
+	if (   ($lines[0] ne "/*" && $lines[-1] ne " */")
+		or ($lines[1] !~ m!^\s+\*!))
+	{
+		return $source;
+	}
+
+	# Check each line except for the first and the last one
+	for my $i (1 .. scalar @lines - 2)
+	{
+		$lines[$i] = " *" . $lines[$i] if $lines[$i] !~ /^\s+\*/;
+	}
+
+	# Keep /* === and /* --- lines as is
+	if ($lines[0] !~ m!^/\*\s+[=-]+!)
+	{
+		$lines[0] =~ s!/\*(.+)!/\*\n *$1!;
+	}
+
+	# Keep === */ and --- */ lines as is
+	if ($lines[-1] !~ m![=-]+\s+\*/$!)
+	{
+		# also remove trailing whitespaces
+		$lines[-1] =~ s!(.+?)\s+\*/!$1\n \*/!;
+	}
+
+	$source = join "\n", @lines;
+
+	return $source;
+}
+
 sub run_indent
 {
 	my $source = shift;
-- 
2.43.0