blob: 6c2eb7bf655b8067858fc8d55ba619fc0e5b1760 [file]
// Copyright 2017-2026 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Test cases in this file should be *insensitive* to wrapping penalties.
// Penalty-sensitive tests belong in formatter-tuning_test.cc.
#include <sstream>
#include <string_view>
#include "gtest/gtest.h"
#include "verible/common/formatting/align.h"
#include "verible/common/formatting/basic-format-style.h"
#include "verible/common/util/logging.h"
#include "verible/verilog/formatting/format-style.h"
#include "verible/verilog/formatting/formatter-test-utils.h"
#include "verible/verilog/formatting/formatter.h"
namespace verilog {
namespace formatter {
namespace {
using verible::AlignmentPolicy;
static constexpr FormatterTestCase kAlignFormatterTestCases[] = {
// module instantiation named ports tabular alignment
//{// module instantiation with no port, only comments
// "module m;\n"
// "foo bar(\n"
// "\t//comment1\n"
// "//comment2\n"
// ");\n"
// "endmodule\n",
// "module m;\n"
// " foo bar (\n"
// " //comment1\n"
// " //comment2\n"
// " );\n"
// "endmodule\n"
//},
{// all named ports
"module m;\n"
"foo bar(.a(a), .aa(aa), .aaa(aaa));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .aa (aa),\n"
" .aaa(aaa)\n"
" );\n"
"endmodule\n"},
{// named ports left unconnected
"module m;\n"
"foo bar(.a(), .aa(), .aaa());\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (),\n"
" .aa (),\n"
" .aaa()\n"
" );\n"
"endmodule\n"},
{// multiple named ports groups separated by blank line
"module m;\n"
"foo bar(.a(a), .aaa(aaa),\n\n .b(b), .bbbbbb(bbbbb));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .aaa(aaa),\n"
"\n"
" .b (b),\n"
" .bbbbbb(bbbbb)\n"
" );\n"
"endmodule\n"},
{// named ports with concatenation
"module m;\n"
"foo bar(.a(a), .aaa({a,b,c}));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .aaa({a, b, c})\n"
" );\n"
"endmodule\n"},
{// name ports with slices
"module m;\n"
"foo bar(.a(a), .aaa(q[r:s]));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .aaa(q[r:s])\n"
" );\n"
"endmodule\n"},
{// named ports with pre-proc directives
"module m;\n"
"foo bar(.a(a), `ifdef MACRO .aa(aa), `endif .aaa(aaa));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
"`ifdef MACRO\n"
" .aa (aa),\n"
"`endif\n"
" .aaa(aaa)\n"
" );\n"
"endmodule\n"},
{// named ports with macros
"module m;\n"
"foo bar(.a(a), .aa(aa[`RANGE]), .aaa(aaa));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .aa (aa[`RANGE]),\n"
" .aaa(aaa)\n"
" );\n"
"endmodule\n"},
{"module m;\n"
"foo bar(.a(a), .AA, .aaa(aaa));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .AA,\n"
" .aaa(aaa)\n"
" );\n"
"endmodule\n"},
{// name ports with comments
"module m;\n"
"foo bar(.a(a), .aa(aa)/*comment*/, .aaa(aaa));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .aa (aa) /*comment*/,\n"
" .aaa(aaa)\n"
" );\n"
"endmodule\n"},
{"module m;\n"
"foo bar(.a(a),//comment1\n .aaa(aaa)//comment2\n);\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a), //comment1\n"
" .aaa(aaa) //comment2\n"
" );\n"
"endmodule\n"},
{"module m;\n"
"foo bar(.a(a),\n"
" //.aa(aa),\n"
".aaa(aaa));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" //.aa(aa),\n"
" .aaa(aaa)\n"
" );\n"
"endmodule\n"},
{"module m;\n"
"foo bar(\n"
".a(a) //comment1\n"
", .aaa(aaa) //comment2\n"
") //comment3\n"
";\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a) //comment1\n"
" , .aaa(aaa) //comment2\n"
" ) //comment3\n"
" ;\n"
"endmodule\n"},
{// module instantiation with all implicit connections
"module m;\n"
"foo bar(.a, .aa, .aaaaa);\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a,\n"
" .aa,\n"
" .aaaaa\n"
" );\n"
"endmodule\n"},
{// named ports corssed with implicit connections
"module m;\n"
"foo bar(.a(a), .aa, .aaaaa(aaaaa));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .aa,\n"
" .aaaaa(aaaaa)\n"
" );\n"
"endmodule\n"},
{// named ports corssed with wildcard connections
"module m;\n"
"foo bar(.a(a), .aaa(aaa), .*);\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .aaa(aaa),\n"
" .*\n"
" );\n"
"endmodule\n"},
{"module m;\n"
"foo bar(.a(a), .aa(aa), .* , .aaa(aaa));\n"
"endmodule\n",
"module m;\n"
" foo bar (\n"
" .a (a),\n"
" .aa (aa),\n"
" .*,\n"
" .aaa(aaa)\n"
" );\n"
"endmodule\n"},
// Parameterized data types, declarations inside #() tabular alignment
{// parameterized module with 'list_of_param_assignments'
"module foo #(A = 2, AA = 22, AAA = 222);\n"
"endmodule\n",
"module foo #(\n"
" A = 2,\n"
" AA = 22,\n"
" AAA = 222\n"
");\n"
"endmodule\n"},
{// parameterized module with 'parameter_declaration'
"module foo #(parameter int a = 2, parameter int aa = 22);\n"
"endmodule\n",
"module foo #(\n"
" parameter int a = 2,\n"
" parameter int aa = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'parameter_declaration' and comments
"module foo #(//comment\nparameter int a = 2, parameter int aa = 22);\n"
"endmodule\n",
"module foo #( //comment\n"
" parameter int a = 2,\n"
" parameter int aa = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'parameter_declaration' and trailing comments
"module foo #(parameter int a = 2,//comment\n parameter int aa = 22);\n"
"endmodule\n",
"module foo #(\n"
" parameter int a = 2, //comment\n"
" parameter int aa = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'parameter_declaration' and pre-proc
"module foo #(parameter int a = 2,\n"
"`ifdef MACRO parameter int aa = 22, `endif\n"
"parameter int aaa = 222);\n"
"endmodule\n",
"module foo #(\n"
" parameter int a = 2,\n"
"`ifdef MACRO\n"
" parameter int aa = 22,\n"
"`endif\n"
" parameter int aaa = 222\n"
");\n"
"endmodule\n"},
{// parameterized module with 'parameter_declaration' and packed dimensions
"module foo #(parameter logic [3:0] a = 2, parameter logic [30:0] aa = "
"22);\n"
"endmodule\n",
"module foo #(\n"
" parameter logic [ 3:0] a = 2,\n"
" parameter logic [30:0] aa = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'parameter_declaration' and unpacked
// dimensions
"module foo #(parameter logic a[3:0] = 2, parameter logic aa [30:0] = "
"22);\n"
"endmodule\n",
"module foo #(\n"
" parameter logic a [ 3:0] = 2,\n"
" parameter logic aa[30:0] = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'local_parameter_declaration'
"module foo #(localparam int a = 2, localparam int aa = 22);\n"
"endmodule\n",
"module foo #(\n"
" localparam int a = 2,\n"
" localparam int aa = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'local_parameter_declaration' and comments
"module foo #(//comment\nlocalparam int a = 2, localparam int aa = 22);\n"
"endmodule\n",
"module foo #( //comment\n"
" localparam int a = 2,\n"
" localparam int aa = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'local_parameter_declaration' and trailing
// comments
"module foo #(localparam int a = 2,//comment\n localparam int aa = 22);\n"
"endmodule\n",
"module foo #(\n"
" localparam int a = 2, //comment\n"
" localparam int aa = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'local_parameter_declaration' and pre-proc
"module foo #(localparam int a = 2,\n"
"`ifdef MACRO localparam int aa = 22, `endif\n"
"localparam int aaa = 222);\n"
"endmodule\n",
"module foo #(\n"
" localparam int a = 2,\n"
"`ifdef MACRO\n"
" localparam int aa = 22,\n"
"`endif\n"
" localparam int aaa = 222\n"
");\n"
"endmodule\n"},
{// parameterized module with 'local_parameter_declaration' and packed
// dimensions
"module foo #(localparam logic [3:0] a = 2, localparam logic [30:0] aa = "
"22);\n"
"endmodule\n",
"module foo #(\n"
" localparam logic [ 3:0] a = 2,\n"
" localparam logic [30:0] aa = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'local_parameter_declaration' and unpacked
// dimensions
"module foo #(localparam logic a[3:0] = 2, localparam logic aa [30:0] = "
"22);\n"
"endmodule\n",
"module foo #(\n"
" localparam logic a [ 3:0] = 2,\n"
" localparam logic aa[30:0] = 22\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments'
"module foo #( int a = 2, real aa = 22, longint aaa = 222);\n"
"endmodule\n",
"module foo #(\n"
" int a = 2,\n"
" real aa = 22,\n"
" longint aaa = 222\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and
// comments
"module foo #(//comment\nint a = 2, shortreal aa = 22, longint aaa = "
"222);\n"
"endmodule\n",
"module foo #( //comment\n"
" int a = 2,\n"
" shortreal aa = 22,\n"
" longint aaa = 222\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and
// trailing comments
"module foo #(int a = 2, shortreal aa = 22,//comment\n longint aaa = "
"222);\n"
"endmodule\n",
"module foo #(\n"
" int a = 2,\n"
" shortreal aa = 22, //comment\n"
" longint aaa = 222\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and
// pre-proc
"module foo #(int a = 2,\n"
"`ifdef MACRO shortreal aa = 22, `endif\n"
" longint aaa = 222);\n"
"endmodule\n",
"module foo #(\n"
" int a = 2,\n"
"`ifdef MACRO\n"
" shortreal aa = 22,\n"
"`endif\n"
" longint aaa = 222\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and
// packed dimensions
"module foo #(bit [1:0] a = 2, reg [12:0] aa = 22, logic [123:0] aaa = "
"222);\n"
"endmodule\n",
"module foo #(\n"
" bit [ 1:0] a = 2,\n"
" reg [ 12:0] aa = 22,\n"
" logic [123:0] aaa = 222\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and
// unpacked dimensions
"module foo #(bit a[1:0] = 2, reg aa[12:0] = 22, logic aaa [123:0] = "
"222);\n"
"endmodule\n",
"module foo #(\n"
" bit a [ 1:0] = 2,\n"
" reg aa [ 12:0] = 22,\n"
" logic aaa[123:0] = 222\n"
");\n"
"endmodule\n"},
{// parameterized module with 'type list_of_type_assignments'
"module foo #(type T = int, type TT = bit, type TTT= C#(logic) );\n"
"endmodule\n",
"module foo #(\n"
" type T = int,\n"
" type TT = bit,\n"
" type TTT = C#(logic)\n"
");\n"
"endmodule\n"},
{// parameterized module with 'type list_of_type_assignments' and comments
"module foo #(//comment\ntype T = int, type TT = bit, type TTT= C#(logic) "
");\n"
"endmodule\n",
"module foo #( //comment\n"
" type T = int,\n"
" type TT = bit,\n"
" type TTT = C#(logic)\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and
// trailing comments
"module foo #(type T = int, type TT = bit, //comment\n type TTT= "
"C#(logic) );\n"
"endmodule\n",
"module foo #(\n"
" type T = int,\n"
" type TT = bit, //comment\n"
" type TTT = C#(logic)\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and
// pre-proc
"module foo #(type T = int,\n"
"`ifdef MACRO type TT = bit, `endif\n"
" type TTT= C#(logic));\n"
"endmodule\n",
"module foo #(\n"
" type T = int,\n"
"`ifdef MACRO\n"
" type TT = bit,\n"
"`endif\n"
" type TTT = C#(logic)\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and
// packed dimensions
"module foo #(type T = int [3:0], type TT = bit [250:0]);\n"
"endmodule\n",
"module foo #(\n"
" type T = int [ 3:0],\n"
" type TT = bit [250:0]\n"
");\n"
"endmodule\n"},
{"module foo #(type T = int, "
"A = 2, int AA = 22, parameter AAA = 222, parameter longint AAAA = 2222, "
"localparam AAAAA = 22222, localparam real AAAAAA = 222222"
");\n"
"endmodule\n",
"module foo #(\n"
" type T = int,\n"
" A = 2,\n"
" int AA = 22,\n"
" parameter AAA = 222,\n"
" parameter longint AAAA = 2222,\n"
" localparam AAAAA = 22222,\n"
" localparam real AAAAAA = 222222\n"
");\n"
"endmodule\n"},
{// parameterized module with built-in data type
"module foo #(int a = 2, real abc = 2234);\n"
"endmodule\n",
"module foo #(\n"
" int a = 2,\n"
" real abc = 2234\n"
");\n"
"endmodule\n"},
{// parameterized module with type
"module foo #(type TYPE1 = int, type TYPE2 = boo);\n"
"endmodule\n",
"module foo #(\n"
" type TYPE1 = int,\n"
" type TYPE2 = boo\n"
");\n"
"endmodule\n"},
{"module foo#(localparam type TYPE1 = int, type TYPE22 = bool, parameter "
" type TYPE333 = real);\n"
"endmodule\n",
"module foo #(\n"
" localparam type TYPE1 = int,\n"
" type TYPE22 = bool,\n"
" parameter type TYPE333 = real\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and 1D
// packed dimensions
"module foo #(parameter type T = int [3:0], type TT = bit [123:0]);\n"
"endmodule\n",
"module foo #(\n"
" parameter type T = int [ 3:0],\n"
" type TT = bit [123:0]\n"
");\n"
"endmodule\n"},
{// parameterized module with 'data_type list_of_param_assignments' and 2D
// packed dimensions
"module foo #(type T = int [3:0][123:0], type TT = bit [123:0][1:0]);\n"
"endmodule\n",
"module foo #(\n"
" type T = int [ 3:0][123:0],\n"
" type TT = bit [123:0][ 1:0]\n"
");\n"
"endmodule\n"},
{// parametrized module with user defined data types
"module foo #(type T = my_type1_t, type TT = my_pkg::my_type2_t);\n"
"endmodule\n",
"module foo #(\n"
" type T = my_type1_t,\n"
" type TT = my_pkg::my_type2_t\n"
");\n"
"endmodule\n"},
{// parameterized class with 'list_of_param_assignments'
"class foo #(A = 2, AA = 22, AAA = 222);\n"
"endclass\n",
"class foo #(\n"
" A = 2,\n"
" AA = 22,\n"
" AAA = 222\n"
");\n"
"endclass\n"},
{// parameterized class with 'parameter_declaration'
"class foo #(parameter int a = 2, parameter int aa = 22);\n"
"endclass\n",
"class foo #(\n"
" parameter int a = 2,\n"
" parameter int aa = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'parameter_declaration' and comments
"class foo #(//comment\nparameter int a = 2, parameter int aa = 22);\n"
"endclass\n",
"class foo #( //comment\n"
" parameter int a = 2,\n"
" parameter int aa = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'parameter_declaration' and trailing comments
"class foo #(parameter int a = 2,//comment\n parameter int aa = 22);\n"
"endclass\n",
"class foo #(\n"
" parameter int a = 2, //comment\n"
" parameter int aa = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'parameter_declaration' and pre-proc
"class foo #(parameter int a = 2,\n"
"`ifdef MACRO parameter int aa = 22, `endif\n"
"parameter int aaa = 222);\n"
"endclass\n",
"class foo #(\n"
" parameter int a = 2,\n"
"`ifdef MACRO\n"
" parameter int aa = 22,\n"
"`endif\n"
" parameter int aaa = 222\n"
");\n"
"endclass\n"},
{// parameterized class with 'parameter_declaration' and packed dimensions
"class foo #(parameter logic [3:0] a = 2, parameter logic [30:0] aa = "
"22);\n"
"endclass\n",
"class foo #(\n"
" parameter logic [ 3:0] a = 2,\n"
" parameter logic [30:0] aa = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'parameter_declaration' and unpacked dimensions
"class foo #(parameter logic a[3:0] = 2, parameter logic aa [30:0] = "
"22);\n"
"endclass\n",
"class foo #(\n"
" parameter logic a [ 3:0] = 2,\n"
" parameter logic aa[30:0] = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'local_parameter_declaration'
"class foo #(localparam int a = 2, localparam int aa = 22);\n"
"endclass\n",
"class foo #(\n"
" localparam int a = 2,\n"
" localparam int aa = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'local_parameter_declaration' and comments
"class foo #(//comment\nlocalparam int a = 2, localparam int aa = 22);\n"
"endclass\n",
"class foo #( //comment\n"
" localparam int a = 2,\n"
" localparam int aa = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'local_parameter_declaration' and trailing
// comments
"class foo #(localparam int a = 2,//comment\n localparam int aa = 22);\n"
"endclass\n",
"class foo #(\n"
" localparam int a = 2, //comment\n"
" localparam int aa = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'local_parameter_declaration' and pre-proc
"class foo #(localparam int a = 2,\n"
"`ifdef MACRO localparam int aa = 22, `endif\n"
"localparam int aaa = 222);\n"
"endclass\n",
"class foo #(\n"
" localparam int a = 2,\n"
"`ifdef MACRO\n"
" localparam int aa = 22,\n"
"`endif\n"
" localparam int aaa = 222\n"
");\n"
"endclass\n"},
{// parameterized class with 'local_parameter_declaration' and packed
// dimensions
"class foo #(localparam logic [3:0] a = 2, localparam logic [30:0] aa = "
"22);\n"
"endclass\n",
"class foo #(\n"
" localparam logic [ 3:0] a = 2,\n"
" localparam logic [30:0] aa = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'local_parameter_declaration' and unpacked
// dimensions
"class foo #(localparam logic a[3:0] = 2, localparam logic aa [30:0] = "
"22);\n"
"endclass\n",
"class foo #(\n"
" localparam logic a [ 3:0] = 2,\n"
" localparam logic aa[30:0] = 22\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments'
"class foo #( int a = 2, real aa = 22, longint aaa = 222);\n"
"endclass\n",
"class foo #(\n"
" int a = 2,\n"
" real aa = 22,\n"
" longint aaa = 222\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and
// comments
"class foo #(//comment\nint a = 2, shortreal aa = 22, longint aaa = "
"222);\n"
"endclass\n",
"class foo #( //comment\n"
" int a = 2,\n"
" shortreal aa = 22,\n"
" longint aaa = 222\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and
// trailing comments
"class foo #(int a = 2, shortreal aa = 22,//comment\n longint aaa = "
"222);\n"
"endclass\n",
"class foo #(\n"
" int a = 2,\n"
" shortreal aa = 22, //comment\n"
" longint aaa = 222\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and
// pre-proc
"class foo #(int a = 2,\n"
"`ifdef MACRO shortreal aa = 22, `endif\n"
" longint aaa = 222);\n"
"endclass\n",
"class foo #(\n"
" int a = 2,\n"
"`ifdef MACRO\n"
" shortreal aa = 22,\n"
"`endif\n"
" longint aaa = 222\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and
// packed dimensions
"class foo #(bit [1:0] a = 2, reg [12:0] aa = 22, logic [123:0] aaa = "
"222);\n"
"endclass\n",
"class foo #(\n"
" bit [ 1:0] a = 2,\n"
" reg [ 12:0] aa = 22,\n"
" logic [123:0] aaa = 222\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and
// unpacked dimensions
"class foo #(bit a[1:0] = 2, reg aa[12:0] = 22, logic aaa [123:0] = "
"222);\n"
"endclass\n",
"class foo #(\n"
" bit a [ 1:0] = 2,\n"
" reg aa [ 12:0] = 22,\n"
" logic aaa[123:0] = 222\n"
");\n"
"endclass\n"},
{// parameterized class with 'type list_of_type_assignments'
"class foo #(type T = int, type TT = bit, type TTT= C#(logic) );\n"
"endclass\n",
"class foo #(\n"
" type T = int,\n"
" type TT = bit,\n"
" type TTT = C#(logic)\n"
");\n"
"endclass\n"},
{// parameterized class with 'type list_of_type_assignments' and comments
"class foo #(//comment\ntype T = int, type TT = bit, type TTT= C#(logic) "
");\n"
"endclass\n",
"class foo #( //comment\n"
" type T = int,\n"
" type TT = bit,\n"
" type TTT = C#(logic)\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and
// trailing comments
"class foo #(type T = int, type TT = bit, //comment\n type TTT= C#(logic) "
");\n"
"endclass\n",
"class foo #(\n"
" type T = int,\n"
" type TT = bit, //comment\n"
" type TTT = C#(logic)\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and
// pre-proc
"class foo #(type T = int,\n"
"`ifdef MACRO type TT = bit, `endif\n"
" type TTT= C#(logic));\n"
"endclass\n",
"class foo #(\n"
" type T = int,\n"
"`ifdef MACRO\n"
" type TT = bit,\n"
"`endif\n"
" type TTT = C#(logic)\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and
// packed dimensions
"class foo #(type T = int [3:0], type TT = bit [250:0]);\n"
"endclass\n",
"class foo #(\n"
" type T = int [ 3:0],\n"
" type TT = bit [250:0]\n"
");\n"
"endclass\n"},
{"class foo #(type T = int, "
"A = 2, int AA = 22, parameter AAA = 222, parameter longint AAAA = 2222, "
"localparam AAAAA = 22222, localparam real AAAAAA = 222222"
");\n"
"endclass\n",
"class foo #(\n"
" type T = int,\n"
" A = 2,\n"
" int AA = 22,\n"
" parameter AAA = 222,\n"
" parameter longint AAAA = 2222,\n"
" localparam AAAAA = 22222,\n"
" localparam real AAAAAA = 222222\n"
");\n"
"endclass\n"},
{// parameterized class with built-in data type
"class foo #(int a = 2, real abc = 2234);\n"
"endclass\n",
"class foo #(\n"
" int a = 2,\n"
" real abc = 2234\n"
");\n"
"endclass\n"},
{// parameterized class with type
"class foo #(type TYPE1 = int, type TYPE2 = boo);\n"
"endclass\n",
"class foo #(\n"
" type TYPE1 = int,\n"
" type TYPE2 = boo\n"
");\n"
"endclass\n"},
{"class foo#(localparam type TYPE1 = int, type TYPE22 = bool, parameter "
"type TYPE333 = real);\n"
"endclass\n",
"class foo #(\n"
" localparam type TYPE1 = int,\n"
" type TYPE22 = bool,\n"
" parameter type TYPE333 = real\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and 1D
// packed dimensions
"class foo #(parameter type T = int [3:0], type TT = bit [123:0]);\n"
"endclass\n",
"class foo #(\n"
" parameter type T = int [ 3:0],\n"
" type TT = bit [123:0]\n"
");\n"
"endclass\n"},
{// parameterized class with 'data_type list_of_param_assignments' and 2D
// packed dimensions
"class foo #(type T = int [3:0][123:0], type TT = bit [123:0][1:0]);\n"
"endclass\n",
"class foo #(\n"
" type T = int [ 3:0][123:0],\n"
" type TT = bit [123:0][ 1:0]\n"
");\n"
"endclass\n"},
{// parametrized class with user defined data types
"class foo #(type T = my_type1_t, type TT = my_pkg::my_type2_t);\n"
"endclass\n",
"class foo #(\n"
" type T = my_type1_t,\n"
" type TT = my_pkg::my_type2_t\n"
");\n"
"endclass\n"},
{// parameterized interface with 'local_parameter_declaration'
"interface foo #(localparam int a = 2, localparam int aa = 22);\n"
"endinterface\n",
"interface foo #(\n"
" localparam int a = 2,\n"
" localparam int aa = 22\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'local_parameter_declaration' and comments
"interface foo #(//comment\nlocalparam int a = 2, localparam int aa = "
"22);\n"
"endinterface\n",
"interface foo #( //comment\n"
" localparam int a = 2,\n"
" localparam int aa = 22\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'local_parameter_declaration' and trailing
// comments
"interface foo #(localparam int a = 2,//comment\n localparam int aa = "
"22);\n"
"endinterface\n",
"interface foo #(\n"
" localparam int a = 2, //comment\n"
" localparam int aa = 22\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'local_parameter_declaration' and pre-proc
"interface foo #(localparam int a = 2,\n"
"`ifdef MACRO localparam int aa = 22, `endif\n"
"localparam int aaa = 222);\n"
"endinterface\n",
"interface foo #(\n"
" localparam int a = 2,\n"
"`ifdef MACRO\n"
" localparam int aa = 22,\n"
"`endif\n"
" localparam int aaa = 222\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'local_parameter_declaration' and packed
// dimensions
"interface foo #(localparam logic [3:0] a = 2, localparam logic [30:0] aa "
"= 22);\n"
"endinterface\n",
"interface foo #(\n"
" localparam logic [ 3:0] a = 2,\n"
" localparam logic [30:0] aa = 22\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'local_parameter_declaration' and unpacked
// dimensions
"interface foo #(localparam logic a[3:0] = 2, localparam logic aa [30:0] "
"= 22);\n"
"endinterface\n",
"interface foo #(\n"
" localparam logic a [ 3:0] = 2,\n"
" localparam logic aa[30:0] = 22\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments'
"interface foo #( int a = 2, real aa = 22, longint aaa = 222);\n"
"endinterface\n",
"interface foo #(\n"
" int a = 2,\n"
" real aa = 22,\n"
" longint aaa = 222\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// comments
"interface foo #(//comment\nint a = 2, shortreal aa = 22, longint aaa = "
"222);\n"
"endinterface\n",
"interface foo #( //comment\n"
" int a = 2,\n"
" shortreal aa = 22,\n"
" longint aaa = 222\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// trailing comments
"interface foo #(int a = 2, shortreal aa = 22,//comment\n longint aaa = "
"222);\n"
"endinterface\n",
"interface foo #(\n"
" int a = 2,\n"
" shortreal aa = 22, //comment\n"
" longint aaa = 222\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// pre-proc
"interface foo #(int a = 2,\n"
"`ifdef MACRO shortreal aa = 22, `endif\n"
" longint aaa = 222);\n"
"endinterface\n",
"interface foo #(\n"
" int a = 2,\n"
"`ifdef MACRO\n"
" shortreal aa = 22,\n"
"`endif\n"
" longint aaa = 222\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// packed dimensions
"interface foo #(bit [1:0] a = 2, reg [12:0] aa = 22, logic [123:0] aaa "
"= 222);\n"
"endinterface\n",
"interface foo #(\n"
" bit [ 1:0] a = 2,\n"
" reg [ 12:0] aa = 22,\n"
" logic [123:0] aaa = 222\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// unpacked dimensions
"interface foo #(bit a[1:0] = 2, reg aa[12:0] = 22, logic aaa [123:0] "
"= 222);\n"
"endinterface\n",
"interface foo #(\n"
" bit a [ 1:0] = 2,\n"
" reg aa [ 12:0] = 22,\n"
" logic aaa[123:0] = 222\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'type list_of_type_assignments'
"interface foo #(type T = int, type TT = bit, type TTT= C#(logic) );\n"
"endinterface\n",
"interface foo #(\n"
" type T = int,\n"
" type TT = bit,\n"
" type TTT = C#(logic)\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'type list_of_type_assignments' and
// comments
"interface foo #(//comment\ntype T = int, type TT = bit, type TTT= "
"C#(logic) );\n"
"endinterface\n",
"interface foo #( //comment\n"
" type T = int,\n"
" type TT = bit,\n"
" type TTT = C#(logic)\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// trailing comments
"interface foo #(type T = int, type TT = bit, //comment\n type TTT= "
"C#(logic) );\n"
"endinterface\n",
"interface foo #(\n"
" type T = int,\n"
" type TT = bit, //comment\n"
" type TTT = C#(logic)\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// pre-proc
"interface foo #(type T = int,\n"
"`ifdef MACRO type TT = bit, `endif\n"
" type TTT= C#(logic));\n"
"endinterface\n",
"interface foo #(\n"
" type T = int,\n"
"`ifdef MACRO\n"
" type TT = bit,\n"
"`endif\n"
" type TTT = C#(logic)\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// packed dimensions
"interface foo #(type T = int [3:0], type TT = bit [250:0]);\n"
"endinterface\n",
"interface foo #(\n"
" type T = int [ 3:0],\n"
" type TT = bit [250:0]\n"
");\n"
"endinterface\n"},
{"interface foo #(type T = int, "
"A = 2, int AA = 22, parameter AAA = 222, parameter longint AAAA = 2222, "
"localparam AAAAA = 22222, localparam real AAAAAA = 222222"
");\n"
"endinterface\n",
"interface foo #(\n"
" type T = int,\n"
" A = 2,\n"
" int AA = 22,\n"
" parameter AAA = 222,\n"
" parameter longint AAAA = 2222,\n"
" localparam AAAAA = 22222,\n"
" localparam real AAAAAA = 222222\n"
");\n"
"endinterface\n"},
{// parameterized interface with built-in data type
"interface foo #(int a = 2, real abc = 2234);\n"
"endinterface\n",
"interface foo #(\n"
" int a = 2,\n"
" real abc = 2234\n"
");\n"
"endinterface\n"},
{// parameterized interface with type
"interface foo #(type TYPE1 = int, type TYPE2 = boo);\n"
"endinterface\n",
"interface foo #(\n"
" type TYPE1 = int,\n"
" type TYPE2 = boo\n"
");\n"
"endinterface\n"},
{"interface foo#(localparam type TYPE1 = int, type TYPE22 = bool, "
"parameter type TYPE333 = real);\n"
"endinterface\n",
"interface foo #(\n"
" localparam type TYPE1 = int,\n"
" type TYPE22 = bool,\n"
" parameter type TYPE333 = real\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// 1D packed dimensions
"interface foo #(parameter type T = int [3:0], type TT = bit [123:0]);\n"
"endinterface\n",
"interface foo #(\n"
" parameter type T = int [ 3:0],\n"
" type TT = bit [123:0]\n"
");\n"
"endinterface\n"},
{// parameterized interface with 'data_type list_of_param_assignments' and
// 2D packed dimensions
"interface foo #(type T = int [3:0][123:0], type TT = bit [123:0][1:0]);\n"
"endinterface\n",
"interface foo #(\n"
" type T = int [ 3:0][123:0],\n"
" type TT = bit [123:0][ 1:0]\n"
");\n"
"endinterface\n"},
{// parametrized interface with user defined data types
"interface foo #(type T = my_type1_t, type TT = my_pkg::my_type2_t);\n"
"endinterface\n",
"interface foo #(\n"
" type T = my_type1_t,\n"
" type TT = my_pkg::my_type2_t\n"
");\n"
"endinterface\n"},
{// wildcard import package at module header
"module foo import bar::*; (baz); endmodule\n",
"module foo\n"
" import bar::*;\n"
"(\n"
" baz\n"
");\n"
"endmodule\n"},
{// import package at module header
"module foo import bar::baz; (qux); endmodule\n",
"module foo\n"
" import bar::baz;\n"
"(\n"
" qux\n"
");\n"
"endmodule\n"},
{// wildcard import multiple packages at module header
"module foo import bar::*,baz::*; (qux); endmodule\n",
"module foo\n"
" import bar::*, baz::*;\n"
"(\n"
" qux\n"
");\n"
"endmodule\n"},
{// separate package import declarations in module header
"module foo import bar::*,baz::*; import q_pkg::qux; (qux); endmodule\n",
"module foo\n"
" import bar::*, baz::*;\n"
" import q_pkg::qux;\n"
"(\n"
" qux\n"
");\n"
"endmodule\n"},
{// import package at module header
"module foo import bar::baz; #(int p = 3)(qux); endmodule\n",
"module foo\n"
" import bar::baz;\n"
"#(\n"
" int p = 3\n"
") (\n"
" qux\n"
");\n"
"endmodule\n"},
// Space between return keyword and return value
{"function int foo(logic [31:0] data); return{<<8{data}}; endfunction",
"function int foo(logic [31:0] data);\n"
" return {<<8{data}};\n"
"endfunction\n"},
{"function int f;return(1);endfunction",
"function int f;\n"
" return (1);\n"
"endfunction\n"},
{"function int f;return-1;endfunction",
"function int f;\n"
" return -1;\n"
"endfunction\n"},
{"function int f ;return ! x\n;endfunction",
"function int f;\n"
" return !x;\n"
"endfunction\n"},
{"function int f ;return ~ x\n;endfunction",
"function int f;\n"
" return ~x;\n"
"endfunction\n"},
{"function int f ;return $x\n;endfunction",
"function int f;\n"
" return $x;\n"
"endfunction\n"},
// String initializers
{"string a[] = {\n\"a\"\n};\n", "string a[] = {\"a\"};\n"},
{"string abc[] = {\n\"a\",\n\"b\",\n\"c\"\n};\n",
"string abc[] = {\"a\", \"b\", \"c\"};\n"},
{"string abc[] = {\n"
"\"a\",//\n"
"\"b\", \"c\"\n"
"};\n",
"string abc[] = {\"a\", //\n"
" \"b\",\n"
" \"c\"};\n"},
{"string abc[] = {//\n"
"\"a\", \"b\", \"c\""
"};\n",
"string abc[] = { //\n"
" \"a\",\n"
" \"b\",\n"
" \"c\"\n"
"};\n"},
{"string abc[] = {\n"
"\"a\", \"b\", \"c\"//\n"
"};\n",
"string abc[] = {\"a\",\n"
" \"b\",\n"
" \"c\" //\n"
" };\n"},
{"string abc[] = {//\n"
"\"a\",//\n"
"\"b\", \"c\"//\n"
"};\n",
"string abc[] = { //\n"
" \"a\", //\n"
" \"b\",\n"
" \"c\" //\n"
"};\n"},
{"string abc[] = {\n"
"\"a\",\n"
"// comment\n"
"// comment\n"
"\"b\",\n"
"\"c\"\n"
"};\n",
"string abc[] = {\"a\",\n"
" // comment\n"
" // comment\n"
" \"b\",\n"
" \"c\"};\n"},
{"string numbers[] = {\"one\", \"two\", \"three\", \"four\"};\n",
"string numbers[] = {\"one\",\n"
" \"two\",\n"
" \"three\",\n"
" \"four\"};\n"},
{"string numbers[] = {\"one\", \"two\", THREE, \"four\"};\n",
"string numbers[] = {\n"
" \"one\", \"two\", THREE, \"four\"\n"
"};\n"},
{"string numbers[] = {\"one\", {\"two\", \"three\"}, \"four\"};\n",
"string numbers[] = {\n"
" \"one\", {\"two\", \"three\"}, \"four\"\n"
"};\n"},
{"string numbers[] = {\"one\", {\"two\", //\n"
"\"three\"}, \"four\"};\n",
"string numbers[] = {\n"
" \"one\",\n"
" {\n"
" \"two\", //\n"
" \"three\"\n"
" },\n"
" \"four\"\n"
"};\n"},
{"string years[] = {\"two_thousand_nineteen\", \"two_thousand_twenty\",\n"
"\"two_thousand_twenty_one\"};\n",
// line with 3rd string would exceed column limit in unwrapped style
"string years[] = {\n"
" \"two_thousand_nineteen\",\n"
" \"two_thousand_twenty\",\n"
" \"two_thousand_twenty_one\"\n"
"};\n"},
{"class class_name;\n"
"var_type var_name = new(\"the_string\");\n"
"endclass\n",
"class class_name;\n"
" var_type var_name = new(\"the_string\");\n"
"endclass\n"},
//{ // parameterized class with 'parameter_declaration' and MACRO
// "class foo #(parameter int a = 2,\n"
// "parameter int aaa = `MACRO);\n"
// "endclass\n",
// "class foo #(\n"
// " parameter int a = 2,\n"
// " parameter int aaa = `MACRO\n"
// ");\n"
// "endclass\n"
//},
// Struct/Union alignment
{"typedef struct {\n"
"bit [3:0] first; bit [31:0] second; generic_type_name_t third;\n"
"} type_t;",
"typedef struct {\n"
" bit [3:0] first;\n"
" bit [31:0] second;\n"
" generic_type_name_t third;\n"
"} type_t;\n"},
{"typedef union soft packed {\n"
"bit [3:0] first; bit [31:0] second; generic_type_name_t third;\n"
"} type_t;",
"typedef union soft packed {\n"
" bit [3:0] first;\n"
" bit [31:0] second;\n"
" generic_type_name_t third;\n"
"} type_t;\n"},
{"typedef union soft {\n"
"bit [3:0] first; bit [31:0] second; generic_type_name_t third;\n"
"} type_t;",
"typedef union soft {\n"
" bit [3:0] first;\n"
" bit [31:0] second;\n"
" generic_type_name_t third;\n"
"} type_t;\n"},
{"typedef struct {\n"
"// comment\n"
"bit [3:0] first; bit [31:0] second; generic_type_name_t third;\n"
"} type_t;",
"typedef struct {\n"
" // comment\n"
" bit [3:0] first;\n"
" bit [31:0] second;\n"
" generic_type_name_t third;\n"
"} type_t;\n"},
{"typedef struct {\n"
"// comment 0\n"
"bit [31:0] first; // a\n"
"bit [31:0] second; // b\n"
"bit third; // c\n"
"uint fourth; // d\n"
"\n"
"// comment 1\n"
"int fifth;\n"
"// comment 2.1\n"
"// comment 2.2\n"
"uint sixth;\n"
"} timing_cfg_t;",
"typedef struct {\n"
" // comment 0\n"
" bit [31:0] first; // a\n"
" bit [31:0] second; // b\n"
" bit third; // c\n"
" uint fourth; // d\n"
"\n"
" // comment 1\n"
" int fifth;\n"
" // comment 2.1\n"
" // comment 2.2\n"
" uint sixth;\n"
"} timing_cfg_t;\n"},
{"typedef struct {\n"
"// comment\n"
"rand int r;\n"
"int a;\n"
"int aa = 0;\n"
"int aaa = 1; // comment\n"
"foo#(bar) z;\n"
"int [x:y] zz; // comment\n"
"int zzz[a:b];\n"
"} type_t;",
"typedef struct {\n"
" // comment\n"
" rand int r;\n"
" int a;\n"
" int aa = 0;\n"
" int aaa = 1; // comment\n"
" foo #(bar) z;\n"
" int [x:y] zz; // comment\n"
" int zzz[a:b];\n"
"} type_t;\n"},
{"typedef struct packed {\n"
"struct packed { bit q; logic qq; logic qqq; } a_few_qs;\n"
"struct packed {\n"
"logic [1:0] q;\n"
"} one_q;\n"
"int q;\n"
"uint qq;\n"
"} nested_qs_t;",
"typedef struct packed {\n"
" struct packed {\n"
" bit q;\n"
" logic qq;\n"
" logic qqq;\n"
" } a_few_qs;\n"
" struct packed {logic [1:0] q;} one_q;\n"
" int q;\n"
" uint qq;\n"
"} nested_qs_t;\n"},
{"typedef struct packed {\n"
"struct packed { bit q; logic qq; logic qqq; } a_few_qs;\n"
"struct packed {\n"
"// comment\n"
"logic [1:0] q;\n"
"} one_q;\n"
"int q;\n"
"uint qq;\n"
"} nested_qs_t;",
"typedef struct packed {\n"
" struct packed {\n"
" bit q;\n"
" logic qq;\n"
" logic qqq;\n"
" } a_few_qs;\n"
" struct packed {\n"
" // comment\n"
" logic [1:0] q;\n"
" } one_q;\n"
" int q;\n"
" uint qq;\n"
"} nested_qs_t;\n"},
{"typedef struct {bit [3:0] first;\n"
"`ifdef MACRO\n"
"bit [31:0] second; generic_type_name_t third;\n"
"`endif\n"
"} type_t;\n",
"typedef struct {\n"
" bit [3:0] first;\n"
"`ifdef MACRO\n"
" bit [31:0] second;\n"
" generic_type_name_t third;\n"
"`endif\n"
"} type_t;\n"},
{"typedef struct {\n"
"bit [3:0] first // c\n"
"; bit [31:0] second"
"// c\n"
"; generic_type_name_t third // c\n"
";} type_t;\n",
"typedef struct {\n"
" bit [3:0] first // c\n"
";\n"
" bit [31:0] second // c\n"
";\n"
" generic_type_name_t third // c\n"
";\n"
"} type_t;\n"},
{"struct {logic test1; // c\n"
"logic test2;} test3;\n",
"struct {\n"
" logic test1; // c\n"
" logic test2;\n"
"} test3;\n"},
{"struct {\n"
" /* t */ logic test1; /* t */\n"
"/* t */ logic test2; }test3;\n",
"struct {\n"
" /* t */ logic test1; /* t */\n"
" /* t */ logic test2;\n"
"} test3;\n"},
// Continuation comment alignment
{"`define BAR 1 // A\n"
"module foo(); // B\n"
"wire baz; // C\n"
"endmodule:foo // D\n",
"`define BAR 1 // A\n"
"module foo (); // B\n"
" wire baz; // C\n"
"endmodule : foo // D\n"},
{"`define BAR 1 // A\n"
"module foo(); // B\n"
" // B.1\n"
" // B.2\n"
"wire baz; // C\n"
" // C.1\n"
" // C.2\n"
"endmodule:foo // D\n"
" // D.1\n"
" // D.2\n",
"`define BAR 1 // A\n"
"module foo (); // B\n"
" // B.1\n"
" // B.2\n"
" wire baz; // C\n"
" // C.1\n"
" // C.2\n"
"endmodule : foo // D\n"
" // D.1\n"
" // D.2\n"},
{"// W\n"
"`define BAR 1 // A\n"
" // X\n"
"module foo(); // B\n"
" // B.1\n"
" // B.2\n"
" // Y\n"
"wire baz; // C\n"
" // C.1\n"
" // C.2\n"
" // Z\n"
"endmodule:foo // D\n"
" // D.1\n"
" // D.2\n",
"// W\n"
"`define BAR 1 // A\n"
"// X\n"
"module foo (); // B\n"
" // B.1\n"
" // B.2\n"
" // Y\n"
" wire baz; // C\n"
" // C.1\n"
" // C.2\n"
" // Z\n"
"endmodule : foo // D\n"
" // D.1\n"
" // D.2\n"},
{"module foo( // A\n"
" // A.1\n"
"// X\n"
"input wire i1 [a:b], // B\n"
" // B.1\n"
"input [c:d] i2, // C\n"
" // C.1\n"
"\n"
"// Y\n"
"output reg o1 // D\n"
" // D.1\n"
");endmodule:foo\n",
"module foo ( // A\n"
" // A.1\n"
" // X\n"
" input wire i1[a:b], // B\n"
" // B.1\n"
" input [c:d] i2, // C\n"
" // C.1\n"
"\n"
" // Y\n"
" output reg o1 // D\n"
" // D.1\n"
");\n"
"endmodule : foo\n"},
// user defined type alignment
{
"module foo();\n"
" logic [5:0][5:0] net_c;\n"
" messy_type_name [1:0] net_e;\n"
"endmodule\n",
"module foo ();\n"
" logic [5:0][5:0] net_c;\n"
" messy_type_name [1:0] net_e;\n"
"endmodule\n",
},
// Continuation comment's original starting column is allowed to differ from
// starting comment's original starting column at most by 1.
// Starting column of comments B and C will change after formatting.
// TODO: refine the column alignment depending on current vs previous line.
// https://github.com/chipsalliance/verible/pull/858#discussion_r672844015
{"module foo (); // A\n" // Starting comment; already on correct column
" // A.1\n" // A's column + 1
" // A.2\n" // A's column - 1
"wire baz; // B\n" // Starting comment; will be moved left
" // B.1\n" // B's column - 1
" // B.2\n" // B's column + 1
" // B.3\n" // B's column
"endmodule:foo // C\n" // Starting comment; will be moved right
" // C.1\n" // C's column + 1
" // C.2\n", // C's column - 1
"module foo (); // A\n"
" // A.1\n"
" // A.2\n"
" wire baz; // B\n"
" // B.1\n"
" // B.2\n"
" // B.3\n"
"endmodule : foo // C\n"
" // C.1\n"
" // C.2\n"},
{"module foo\n"
"#(\n"
" parameter type baz_t = struct packed { `BAZ(); }\n"
")\n"
"();\n"
"endmodule\n",
"module foo #(\n"
" parameter type\n"
" baz_t = struct packed {\n"
" `BAZ();\n"
" }\n"
") ();\n"
"endmodule\n"},
// The same as the previous test case, but without a semicolon at the macro
// call
{"module foo\n"
"#(\n"
" parameter type baz_t = struct packed { `BAZ() }\n"
")\n"
"();\n"
"endmodule\n",
"module foo #(\n"
" parameter type\n"
" baz_t = struct packed {\n"
" `BAZ()\n"
" }\n"
") ();\n"
"endmodule\n"},
// Check that comments with too large starting column difference are not
// aligned as continuation comments.
// Check that starting comments are not linked with a comment in
// comment-only line above them, even when the starting column is the same.
// All comments in this test case are aligned independently, i.e. none are
// "continuation comments".
{" // comment1\n" // A's column, but is above it
"module foo (); // A\n"
" // comment2\n" // A's column + 2
" // comment3\n" // A's column - 2
"wire baz; // B\n"
" // comment4\n" // B's column - 2
" // comment5\n" // B's column + 2
" // comment6\n" // B's column, but not directly under B
"endmodule:foo // C\n"
" // comment7\n" // C's column + 2
" // comment8\n", // C's column, but not directly under B
"// comment1\n"
"module foo (); // A\n"
" // comment2\n"
" // comment3\n"
" wire baz; // B\n"
" // comment4\n"
" // comment5\n"
" // comment6\n"
"endmodule : foo // C\n"
"// comment7\n"
"// comment8\n"},
// Continuation comment alignment when a line with the starting comment is
// wrapped.
{"module foo(output logic very_very_very_very_long_name // A\n"
" // A.1\n"
"); endmodule\n",
"module foo (\n"
" output logic\n"
" very_very_very_very_long_name // A\n"
" // A.1\n"
");\n"
"endmodule\n"},
// Attachment of ',' to elements in enum list (with and without comments)
{"typedef enum {\n"
" first , // c1\n"
" second\n"
"} e;\n",
"typedef enum {\n"
" first, // c1\n"
" second\n"
"} e;\n"},
{"typedef enum {\n"
" first ,\n"
" // c1\n"
" second\n"
"} e;\n",
"typedef enum {\n"
" first,\n"
" // c1\n"
" second\n"
"} e;\n"},
{"typedef enum {\n"
" first // c1\n"
" , second\n"
"} e;\n",
"typedef enum {\n"
" first // c1\n"
" , second\n"
"} e;\n"},
{"typedef enum {\n"
" first\n"
" // c1\n"
" , second\n"
"} e;\n",
"typedef enum {\n"
" first\n"
" // c1\n"
" , second\n"
"} e;\n"},
{"typedef enum {\n"
" first // c1\n"
" , // c2\n"
" second\n"
"} e;\n",
"typedef enum {\n"
" first // c1\n"
" , // c2\n"
" second\n"
"} e;\n"},
{"typedef enum {\n"
" first\n"
" // c1\n"
" ,\n"
" // c2\n"
" second\n"
"} e;\n",
"typedef enum {\n"
" first\n"
" // c1\n"
" , // c2\n"
" second\n"
"} e;\n"},
{"typedef enum {\n"
" first\n"
" // c1\n"
" , // c2\n"
" // c3\n"
" second\n"
"} e;\n",
"typedef enum {\n"
" first\n"
" // c1\n"
" , // c2\n"
" // c3\n"
" second\n"
"} e;\n"},
{"typedef enum {\n"
" // c1\n"
" first\n"
" // c2\n"
" , // c3\n"
" // c4\n"
" second\n"
" // c5\n"
"} e;\n",
"typedef enum {\n"
" // c1\n"
" first\n"
" // c2\n"
" , // c3\n"
" // c4\n"
" second\n"
" // c5\n"
"} e;\n"},
{"typedef enum {\n"
" // c1\n"
" // c1+\n"
" first // c2\n"
" // c2+\n"
" , // c3\n"
" // c3+\n"
" // c4\n"
" // c4+\n"
" second // c5\n"
" // c5+\n"
"} e;\n",
"typedef enum {\n"
" // c1\n"
" // c1+\n"
" first // c2\n"
" // c2+\n"
" , // c3\n"
" // c3+\n"
" // c4\n"
" // c4+\n"
" second // c5\n"
" // c5+\n"
"} e;\n"},
{"typedef enum {\n"
" first , /* c1 */\n"
" second\n"
"} e;\n",
"typedef enum {\n"
" first, /* c1 */\n"
" second\n"
"} e;\n"},
{"typedef enum {\n"
" first ,\n"
" /* c1 */\n"
" second\n"
"} e;\n",
"typedef enum {\n"
" first,\n"
" /* c1 */\n"
" second\n"
"} e;\n"},
{"typedef enum {\n"
" first /* c1 */\n"
" , second\n"
"} e;\n",
"typedef enum {\n"
" first /* c1 */\n"
" , second\n"
"} e;\n"},
{"typedef enum {\n"
" first\n"
" /* c1 */\n"
" , second\n"
"} e;\n",
"typedef enum {\n"
" first\n"
" /* c1 */\n"
" , second\n"
"} e;\n"},
{"typedef enum {\n"
" first /* c1 */\n"
" , /* c2 */\n"
" second\n"
"} e;\n",
"typedef enum {\n"
" first /* c1 */\n"
" , /* c2 */\n"
" second\n"
"} e;\n"},
{"typedef enum {\n"
" first\n"
" /* c1 */\n"
" ,\n"
" /* c2 */\n"
" second\n"
"} e;\n",
"typedef enum {\n"
" first\n"
" /* c1 */\n"
" ,\n"
" /* c2 */\n"
" second\n"
"} e;\n"},
{"typedef enum {\n"
" /* c1 */\n"
" first\n"
" /* c2 */\n"
" , /* c3 */\n"
" /* c4 */\n"
" second\n"
" /* c5 */\n"
"} e;\n",
"typedef enum {\n"
" /* c1 */\n"
" first\n"
" /* c2 */\n"
" , /* c3 */\n"
" /* c4 */\n"
" second\n"
" /* c5 */\n"
"} e;\n"},
{"typedef enum {\n"
" /* c1 */\n"
" /* c1+ */\n"
" first /* c2 */\n"
" /* c2+ */\n"
" , /* c3 */\n"
" /* c3+ */\n"
" /* c4 */\n"
" /* c4+ */\n"
" second /* c5 */\n"
" /* c5+ */\n"
"} e;\n",
"typedef enum {\n"
" /* c1 */\n"
" /* c1+ */\n"
" first /* c2 */\n"
" /* c2+ */\n"
" , /* c3 */\n"
" /* c3+ */\n"
" /* c4 */\n"
" /* c4+ */\n"
" second /* c5 */\n"
" /* c5+ */\n"
"} e;\n"},
{"module m;\n"
"typedef enum {\n"
" first,\n"
" second\n"
"} // c\n"
"e;\n"
"endmodule\n",
"module m;\n"
" typedef enum {\n"
" first,\n"
" second\n"
" } // c\n"
" e;\n"
"endmodule\n"},
// Attachment of ';' preceded by EOL comment
{"module m;\n"
"typedef enum {\n"
" first,\n"
" second\n"
"} e // c\n"
";\n"
"endmodule\n",
"module m;\n"
" typedef enum {\n"
" first,\n"
" second\n"
" } e // c\n"
" ;\n"
"endmodule\n"},
{"module m;\n"
"typedef enum {\n"
" first,\n"
" second\n"
"} // c1\n"
"e // c2\n"
";\n"
"endmodule\n",
"module m;\n"
" typedef enum {\n"
" first,\n"
" second\n"
" } // c1\n"
" e // c2\n"
" ;\n"
"endmodule\n"},
{"assign foo = bar\n"
"// comment\n"
";\n",
"assign foo = bar\n"
" // comment\n"
" ;\n"},
{"assign foo = bar // comment\n"
";\n",
"assign foo = bar // comment\n"
";\n"},
// Attachment of ',' to elements in PortActualList (with and without
// comments)
{"module foo;\n"
" bar foobar(\n"
" .first(1) // c1\n"
" ,\n"
" .second(2) // c2\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1) // c1\n"
" , .second(2) // c2\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1) // c1\n"
" , .second(2) // c2\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1) // c1\n"
" , .second(2) // c2\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1)\n"
" // c1\n"
" ,\n"
" .second(2)\n"
" // c2\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1)\n"
" // c1\n"
" , .second(2)\n"
" // c2\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1)\n"
" // c1\n"
" , .second(2)\n"
" // c2\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1)\n"
" // c1\n"
" , .second(2)\n"
" // c2\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1)\n"
" // c1\n"
" , // c2\n"
" .second(2)\n"
" // c3\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1)\n"
" // c1\n"
" , // c2\n"
" .second(2)\n"
" // c3\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" // c1\n"
" // c1+\n"
" .first(1) // c2\n"
" // c2+\n"
" , // c3\n"
" // c3+\n"
" .second(2) // c4\n"
" // c4+\n"
" // c5\n"
" // c5+\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" // c1\n"
" // c1+\n"
" .first (1) // c2\n"
" // c2+\n"
" , // c3\n"
" // c3+\n"
" .second(2) // c4\n"
" // c4+\n"
" // c5\n"
" // c5+\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1) /* c1 */\n"
" ,\n"
" .second(2) /* c2 */\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1) /* c1 */\n"
" , .second(2) /* c2 */\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" /* c1 */ .first(1),\n"
" /* c2 */ .second(2)\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" /* c1 */.first (1),\n"
" /* c2 */.second(2)\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1) /* c1 */\n"
" , .second(2) /* c2 */\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1) /* c1 */\n"
" , .second(2) /* c2 */\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" /* c1 */.first(1)\n"
" /* c2 */, .second(2)\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" /* c1 */ .first (1)\n"
" /* c2 */, .second(2)\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1)\n"
" /* c1 */\n"
" ,\n"
" .second(2)\n"
" /* c2 */\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1)\n"
" /* c1 */\n"
" , .second(2)\n"
" /* c2 */\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1)\n"
" /* c1 */\n"
" , .second(2)\n"
" /* c2 */\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1)\n"
" /* c1 */\n"
" , .second(2)\n"
" /* c2 */\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1)\n"
" /* c1 */\n"
" , /* c2 */\n"
" .second(2)\n"
" /* c3 */\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1)\n"
" /* c1 */\n"
" , /* c2 */\n"
" .second(2)\n"
" /* c3 */\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" .first(1)\n"
" /* c1 */\n"
" , /* c2 */\n"
" .second(2)\n"
" /* c3 */\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" .first (1)\n"
" /* c1 */\n"
" , /* c2 */\n"
" .second(2)\n"
" /* c3 */\n"
" );\n"
"endmodule\n"},
{"module foo;\n"
" bar foobar(\n"
" /* c1 */\n"
" /* c1+ */\n"
" .first(1) /* c2 */\n"
" /* c2+ */\n"
" , /* c3 */\n"
" /* c3+ */\n"
" .second(2) /* c4 */\n"
" /* c4+ */\n"
" /* c5 */\n"
" /* c5+ */\n"
" );\n"
"endmodule\n",
"module foo;\n"
" bar foobar (\n"
" /* c1 */\n"
" /* c1+ */\n"
" .first (1) /* c2 */\n"
" /* c2+ */\n"
" , /* c3 */\n"
" /* c3+ */\n"
" .second(2) /* c4 */\n"
" /* c4+ */\n"
" /* c5 */\n"
" /* c5+ */\n"
" );\n"
"endmodule\n"},
// Attachment of ',' to elements in ActualNamedParameterList (with and
// without comments)
{"module foo;\n"
" bar#(\n"
" .first(1) // c1\n"
" ,\n"
" .second(2) // c2\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1) // c1\n"
" , .second(2) // c2\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1) // c1\n"
" , .second(2) // c2\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1) // c1\n"
" , .second(2) // c2\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1)\n"
" // c1\n"
" ,\n"
" .second(2)\n"
" // c2\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1)\n"
" // c1\n"
" , .second(2)\n"
" // c2\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1)\n"
" // c1\n"
" , .second(2)\n"
" // c2\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1)\n"
" // c1\n"
" , .second(2)\n"
" // c2\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1)\n"
" // c1\n"
" , // c2\n"
" .second(2)\n"
" // c3\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1)\n"
" // c1\n"
" , // c2\n"
" .second(2)\n"
" // c3\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" // c1\n"
" // c1+\n"
" .first(1) // c2\n"
" // c2+\n"
" , // c3\n"
" // c3+\n"
" .second(2) // c4\n"
" // c4+\n"
" // c5\n"
" // c5+\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" // c1\n"
" // c1+\n"
" .first (1) // c2\n"
" // c2+\n"
" , // c3\n"
" // c3+\n"
" .second(2) // c4\n"
" // c4+\n"
" // c5\n"
" // c5+\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1) /* c1 */\n"
" ,\n"
" .second(2) /* c2 */\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1) /* c1 */\n"
" , .second(2) /* c2 */\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" /* c1 */ .first(1),\n"
" /* c2 */ .second(2)\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" /* c1 */.first (1),\n"
" /* c2 */.second(2)\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1) /* c1 */\n"
" , .second(2) /* c2 */\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1) /* c1 */\n"
" , .second(2) /* c2 */\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" /* c1 */.first(1)\n"
" /* c2 */, .second(2)\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" /* c1 */ .first (1)\n"
" /* c2 */, .second(2)\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1)\n"
" /* c1 */\n"
" ,\n"
" .second(2)\n"
" /* c2 */\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1)\n"
" /* c1 */\n"
" , .second(2)\n"
" /* c2 */\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1)\n"
" /* c1 */\n"
" , .second(2)\n"
" /* c2 */\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1)\n"
" /* c1 */\n"
" , .second(2)\n"
" /* c2 */\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1)\n"
" /* c1 */\n"
" , /* c2 */\n"
" .second(2)\n"
" /* c3 */\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1)\n"
" /* c1 */\n"
" , /* c2 */\n"
" .second(2)\n"
" /* c3 */\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" .first(1)\n"
" /* c1 */\n"
" , /* c2 */\n"
" .second(2)\n"
" /* c3 */\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" .first (1)\n"
" /* c1 */\n"
" , /* c2 */\n"
" .second(2)\n"
" /* c3 */\n"
" ) baz ();\n"
"endmodule\n"},
{"module foo;\n"
" bar#(\n"
" /* c1 */\n"
" /* c1+ */\n"
" .first(1) /* c2 */\n"
" /* c2+ */\n"
" , /* c3 */\n"
" /* c3+ */\n"
" .second(2) /* c4 */\n"
" /* c4+ */\n"
" /* c5 */\n"
" /* c5+ */\n"
" ) baz ();\n"
"endmodule\n",
"module foo;\n"
" bar #(\n"
" /* c1 */\n"
" /* c1+ */\n"
" .first (1) /* c2 */\n"
" /* c2+ */\n"
" , /* c3 */\n"
" /* c3+ */\n"
" .second(2) /* c4 */\n"
" /* c4+ */\n"
" /* c5 */\n"
" /* c5+ */\n"
" ) baz ();\n"
"endmodule\n"},
// ":" and "'{" in a single line
{"assign foo[2] =\n"
"'{\n"
"bar: 1'b1, // c\n"
"baz: 1'b0, // c\n"
"foobar: CONSTANT,\n"
"qux:\n"
"{\n"
"a, // c\n"
"b\n"
"}\n"
"};\n",
"assign foo[2] = '{\n"
" bar: 1'b1, // c\n"
" baz: 1'b0, // c\n"
" foobar: CONSTANT,\n"
" qux: {\n"
" a, // c\n"
" b\n"
" }\n"
" };\n"},
{"assign a = (b) ? '{c: d[e], f: '1} : g;\n",
"assign a = (b) ?\n"
" '{c: d[e], f: '1}\n"
" : g;\n"},
// -----------------------------------------------------------------
// Comments around `else`.
// Check whether `else` partition is found correctly and that actual code is
// not appended to EOL comments.
// generate if
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"else if (r) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" else if (r) assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"// eol-c\n"
"else if (r) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" // eol-c\n"
" else if (r) assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"else // eol-c\n"
"if (r) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" else // eol-c\n"
" if (r) assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"else\n"
"// eol-c\n"
"if (r) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" else\n"
" // eol-c\n"
" if (r)\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"else // eol-c\n"
"if (r) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" else // eol-c\n"
" if (r) assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"else // eol-c\n"
"// eol-c\n"
"if (r) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" else // eol-c\n"
" // eol-c\n"
" if (r)\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"if (r) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" if (r)\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"if\n"
"// eol-c\n"
"(r) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" if\n"
" // eol-c\n"
" (r)\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"// eol-c\n"
"if\n"
"// eol-c\n"
"// eol-c\n"
"(r) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" // eol-c\n"
" if\n"
" // eol-c\n"
" // eol-c\n"
" (r)\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
// generate if with function call
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"else if (foo(x) == bar(1, 2)) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" else if (foo(x) == bar(1, 2))\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"// eol-c\n"
"else if (foo(x) == bar(1, 2)) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" // eol-c\n"
" else if (foo(x) == bar(1, 2))\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"else // eol-c\n"
"if (foo(x) == bar(1, 2)) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" else // eol-c\n"
" if (foo(x) == bar(1, 2)) assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"else\n"
"// eol-c\n"
"if (foo(x) == bar(1, 2)) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" else\n"
" // eol-c\n"
" if (foo(\n"
" x\n"
" ) == bar(\n"
" 1, 2\n"
" ))\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"else // eol-c\n"
"if (foo(x) == bar(1, 2)) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" else // eol-c\n"
" if (foo(x) == bar(1, 2)) assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"else // eol-c\n"
"// eol-c\n"
"if (foo(x) == bar(1, 2)) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" else // eol-c\n"
" // eol-c\n"
" if (foo(\n"
" x\n"
" ) == bar(\n"
" 1, 2\n"
" ))\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"if (foo(x) == bar(1, 2)) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" if (foo(\n"
" x\n"
" ) == bar(\n"
" 1, 2\n"
" ))\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"if\n"
"// eol-c\n"
"(foo(x) == bar(1, 2)) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" if\n"
" // eol-c\n"
" (foo(\n"
" x\n"
" ) == bar(\n"
" 1, 2\n"
" ))\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
{"module zx;\n"
"if (x) assign z=y;\n"
"// eol-c\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"// eol-c\n"
"if\n"
"// eol-c\n"
"// eol-c\n"
"(foo(x) == bar(1, 2)) assign z=w;\n"
"else assign x=y;\n"
"endmodule\n",
"module zx;\n"
" if (x) assign z = y;\n"
" // eol-c\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" // eol-c\n"
" if\n"
" // eol-c\n"
" // eol-c\n"
" (foo(\n"
" x\n"
" ) == bar(\n"
" 1, 2\n"
" ))\n"
" assign z = w;\n"
" else assign x = y;\n"
"endmodule\n"},
// else begin
{"module zx;\n"
"always begin\n"
"if (a) b<=1;\n"
"// eol-c\n"
"else begin b<=2;\n"
"end\n"
"end\n"
"endmodule\n",
"module zx;\n"
" always begin\n"
" if (a) b <= 1;\n"
" // eol-c\n"
" else begin\n"
" b <= 2;\n"
" end\n"
" end\n"
"endmodule\n"},
{"module zx;\n"
"always begin\n"
"if (a) b<=1;\n"
"// eol-c\n"
"// eol-c\n"
"else begin b<=2;\n"
"end\n"
"end\n"
"endmodule\n",
"module zx;\n"
" always begin\n"
" if (a) b <= 1;\n"
" // eol-c\n"
" // eol-c\n"
" else begin\n"
" b <= 2;\n"
" end\n"
" end\n"
"endmodule\n"},
{"module zx;\n"
"always begin\n"
"if (a) b<=1;\n"
"else // eol-c\n"
"begin b<=2;\n"
"end\n"
"end\n"
"endmodule\n",
"module zx;\n"
" always begin\n"
" if (a) b <= 1;\n"
" else // eol-c\n"
" begin\n"
" b <= 2;\n"
" end\n"
" end\n"
"endmodule\n"},
{"module zx;\n"
"always begin\n"
"if (a) b<=1;\n"
"else\n"
"// eol-c\n"
"begin b<=2;\n"
"end\n"
"end\n"
"endmodule\n",
"module zx;\n"
" always begin\n"
" if (a) b <= 1;\n"
" else\n"
" // eol-c\n"
" begin\n"
" b <= 2;\n"
" end\n"
" end\n"
"endmodule\n"},
{"module zx;\n"
"always begin\n"
"if (a) b<=1;\n"
"// eol-c\n"
"else // eol-c\n"
"begin b<=2;\n"
"end\n"
"end\n"
"endmodule\n",
"module zx;\n"
" always begin\n"
" if (a) b <= 1;\n"
" // eol-c\n"
" else // eol-c\n"
" begin\n"
" b <= 2;\n"
" end\n"
" end\n"
"endmodule\n"},
{"module zx;\n"
"always begin\n"
"if (a) b<=1;\n"
"else // eol-c\n"
"// eol-c\n"
"begin b<=2;\n"
"end\n"
"end\n"
"endmodule\n",
"module zx;\n"
" always begin\n"
" if (a) b <= 1;\n"
" else // eol-c\n"
" // eol-c\n"
" begin\n"
" b <= 2;\n"
" end\n"
" end\n"
"endmodule\n"},
// else if
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"else if (set) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" else if (set) assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"// eol-c\n"
"else if (set) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" // eol-c\n"
" else if (set) assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"else // eol-c\n"
"if (set) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" else // eol-c\n"
" if (set) assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"else\n"
"// eol-c\n"
"if (set) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" else\n"
" // eol-c\n"
" if (set)\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"else // eol-c\n"
"if (set) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" else // eol-c\n"
" if (set) assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"else // eol-c\n"
"// eol-c\n"
"if (set) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" else // eol-c\n"
" // eol-c\n"
" if (set)\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"if (set) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" if (set)\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"if\n"
"// eol-c\n"
"(set) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" if\n"
" // eol-c\n"
" (set)\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"// eol-c\n"
"if\n"
"// eol-c\n"
"// eol-c\n"
"(set) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" // eol-c\n"
" if\n"
" // eol-c\n"
" // eol-c\n"
" (set)\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
// else if with function call
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"else if (foo(clr, set, 1)) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" else if (foo(clr, set, 1))\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"// eol-c\n"
"else if (foo(clr, set, 1)) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" // eol-c\n"
" else if (foo(clr, set, 1))\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"else // eol-c\n"
"if (foo(clr, set, 1)) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" else // eol-c\n"
" if (foo(clr, set, 1)) assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"else\n"
"// eol-c\n"
"if (foo(clr, set, 1)) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" else\n"
" // eol-c\n"
" if (foo(\n"
" clr, set, 1\n"
" ))\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"else // eol-c\n"
"if (foo(clr, set, 1)) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" else // eol-c\n"
" if (foo(clr, set, 1)) assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"else // eol-c\n"
"// eol-c\n"
"if (foo(clr, set, 1)) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" else // eol-c\n"
" // eol-c\n"
" if (foo(\n"
" clr, set, 1\n"
" ))\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"if (foo(clr, set, 1)) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" if (foo(\n"
" clr, set, 1\n"
" ))\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"if\n"
"// eol-c\n"
"(foo(clr, set, 1)) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" if\n"
" // eol-c\n"
" (foo(\n"
" clr, set, 1\n"
" ))\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
{"module zx;\n"
"always @(clr or set)\n"
"if (clr) assign q=0;\n"
"// eol-c\n"
"// eol-c\n"
"else // eol-c\n"
"// eol-c\n"
"// eol-c\n"
"if\n"
"// eol-c\n"
"// eol-c\n"
"(foo(clr, set, 1)) assign q=1;\n"
"else deassign q;\n"
"endmodule\n",
"module zx;\n"
" always @(clr or set)\n"
" if (clr) assign q = 0;\n"
" // eol-c\n"
" // eol-c\n"
" else // eol-c\n"
" // eol-c\n"
" // eol-c\n"
" if\n"
" // eol-c\n"
" // eol-c\n"
" (foo(\n"
" clr, set, 1\n"
" ))\n"
" assign q = 1;\n"
" else deassign q;\n"
"endmodule\n"},
// -----------------------------------------------------------------
// Comments around and inside macro calls.
};
TEST(FormatterEndToEndTest, AlignFormatterTestCases) {
RunFormatterTestCases40(kAlignFormatterTestCases);
}
TEST(FormatterEndToEndTest, AlignmentGroupBoundaryNone) {
// Default behavior: separator comments and blank lines do NOT break groups.
static constexpr FormatterTestCase kTestCases[] = {
{// Separator comment does not break alignment group
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"// ============\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" // ============\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.alignment_group_boundary = AlignmentGroupBoundary::kNone;
style.assignment_statement_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
TEST(FormatterEndToEndTest, AlignmentGroupBoundarySeparatorComments) {
static constexpr FormatterTestCase kTestCases[] = {
{// Separator comment breaks alignment group
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"// ============\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" // ============\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Dashes separator also breaks
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"// ------------\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" // ------------\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Captioned divider (text between separator runs) also breaks
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"// ------ section heading ------\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" // ------ section heading ------\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Leading-only divider run with trailing caption text
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"// ==== Registers\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" // ==== Registers\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// No space after // also works
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"//============\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" //============\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Slash separator (/////) also works
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"//////////\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" //////////\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Regular comment does NOT break alignment
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"// Title text\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" // Title text\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Multi-line comment block with separators
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"// ============\n"
"// Title\n"
"// ============\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" // ============\n"
" // Title\n"
" // ============\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Short repeated body (3 chars) does NOT break
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"// ---\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" // ---\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Declarations also respect separator comments
"module m;\n"
"logic a;\n"
"logic [7:0] b;\n"
"// ============\n"
"logic c_long_name;\n"
"logic d;\n"
"endmodule\n",
"module m;\n"
" logic a;\n"
" logic [7:0] b;\n"
" // ============\n"
" logic c_long_name;\n"
" logic d;\n"
"endmodule\n"},
{// Statements in always blocks
"module m;\n"
"always_comb begin\n"
"aaaaa = b;\n"
"c = 1'b0;\n"
"// ============\n"
"dd = eee;\n"
"ffffff = g;\n"
"end\n"
"endmodule\n",
"module m;\n"
" always_comb begin\n"
" aaaaa = b;\n"
" c = 1'b0;\n"
" // ============\n"
" dd = eee;\n"
" ffffff = g;\n"
" end\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.alignment_group_boundary = AlignmentGroupBoundary::kSeparatorComments;
style.assignment_statement_alignment = AlignmentPolicy::kAlign;
style.module_net_variable_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
TEST(FormatterEndToEndTest, AlignmentGroupBoundaryBlankLines) {
static constexpr FormatterTestCase kTestCases[] = {
{// Blank line breaks alignment group
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
"\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// No blank line: single alignment group
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Single item before blank line (not enough for alignment)
"module m;\n"
"assign foo = 1'b1;\n"
"\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
"\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
{// Separator comment does NOT break (only blank lines)
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"// ============\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
" // ============\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.alignment_group_boundary = AlignmentGroupBoundary::kBlankLines;
style.assignment_statement_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
TEST(FormatterEndToEndTest,
AlignmentGroupBoundaryBlankLinesAndSeparatorComments) {
static constexpr FormatterTestCase kTestCases[] = {
{// Both blank line and separator break groups
"module m;\n"
"assign foo = 1'b1;\n"
"assign baar = 1'b0;\n"
"\n"
"assign baaaaz = 1'b1;\n"
"assign c = 1'b0;\n"
"// ============\n"
"assign dd = 1'b1;\n"
"assign eee = 1'b0;\n"
"endmodule\n",
"module m;\n"
" assign foo = 1'b1;\n"
" assign baar = 1'b0;\n"
"\n"
" assign baaaaz = 1'b1;\n"
" assign c = 1'b0;\n"
" // ============\n"
" assign dd = 1'b1;\n"
" assign eee = 1'b0;\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.alignment_group_boundary =
AlignmentGroupBoundary::kBlankLinesAndSeparatorComments;
style.assignment_statement_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify kAlign behavior for body-level param/localparam declarations
// in module and package bodies.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentBasics) {
static constexpr FormatterTestCase kTestCases[] = {
{// localparam alignment in module body
"module m;\n"
"localparam foo = 4'b0000;\n"
"localparam barr = 4'b0010;\n"
"localparam baaaaz = 4'b0111;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 4'b0000;\n"
" localparam barr = 4'b0010;\n"
" localparam baaaaz = 4'b0111;\n"
"endmodule\n"},
{// localparam alignment in package body
"package p;\n"
"localparam foo = 4'b0000;\n"
"localparam barr = 4'b0010;\n"
"localparam baaaaz = 4'b0111;\n"
"endpackage\n",
"package p;\n"
" localparam foo = 4'b0000;\n"
" localparam barr = 4'b0010;\n"
" localparam baaaaz = 4'b0111;\n"
"endpackage\n"},
{// parameter alignment in module body
"module m;\n"
"parameter int foo = 1;\n"
"parameter int barr = 2;\n"
"endmodule\n",
"module m;\n"
" parameter int foo = 1;\n"
" parameter int barr = 2;\n"
"endmodule\n"},
{// parameter alignment in package body
"package p;\n"
"parameter int foo = 1;\n"
"parameter int barrrr = 2;\n"
"endpackage\n",
"package p;\n"
" parameter int foo = 1;\n"
" parameter int barrrr = 2;\n"
"endpackage\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify kFlushLeft behavior: body-level param/localparam declarations
// are not aligned.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentFlushLeft) {
static constexpr FormatterTestCase kTestCases[] = {
{// module body: parameters are not aligned
"module m;\n"
"localparam foo = 4'b0000;\n"
"localparam barr = 4'b0010;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 4'b0000;\n"
" localparam barr = 4'b0010;\n"
"endmodule\n"},
{// package context: flush-left
"package p;\n"
"localparam foo = 4'b0000;\n"
"localparam barr = 4'b0010;\n"
"endpackage\n",
"package p;\n"
" localparam foo = 4'b0000;\n"
" localparam barr = 4'b0010;\n"
"endpackage\n"},
{// generate context: flush-left
"module m;\n"
"generate\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"endgenerate\n"
"endmodule\n",
"module m;\n"
" generate\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" endgenerate\n"
"endmodule\n"},
{// parameter in module body: flush-left
"module m;\n"
"parameter int W = 8;\n"
"parameter int HHHH = 2;\n"
"endmodule\n",
"module m;\n"
" parameter int W = 8;\n"
" parameter int HHHH = 2;\n"
"endmodule\n"},
{// mixed parameter and localparam: flush-left, no alignment
"module m;\n"
"parameter int W = 8;\n"
"localparam L = 4;\n"
"parameter int H = 2;\n"
"endmodule\n",
"module m;\n"
" parameter int W = 8;\n"
" localparam L = 4;\n"
" parameter int H = 2;\n"
"endmodule\n"},
{// interface context: flush-left
"interface my_if;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"endinterface\n",
"interface my_if;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"endinterface\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kFlushLeft;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify kPreserve behavior: body-level param/localparam declarations
// maintain their existing spacing.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentPreserve) {
static constexpr FormatterTestCase kTestCases[] = {
{// module body: existing spacing is kept
"module m;\n"
"localparam foo = 4'b0000;\n"
"localparam barr = 4'b0010;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 4'b0000;\n"
" localparam barr = 4'b0010;\n"
"endmodule\n"},
{// package: existing flush-left spacing preserved
"package p;\n"
"localparam foo = 4'b0000;\n"
"localparam barr = 4'b0010;\n"
"endpackage\n",
"package p;\n"
" localparam foo = 4'b0000;\n"
" localparam barr = 4'b0010;\n"
"endpackage\n"},
{// generate: existing aligned spacing preserved
"module m;\n"
"generate\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"endgenerate\n"
"endmodule\n",
"module m;\n"
" generate\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" endgenerate\n"
"endmodule\n"},
{// parameter flush-left preserved
"module m;\n"
"parameter int W = 8;\n"
"parameter int HHHH = 2;\n"
"endmodule\n",
"module m;\n"
" parameter int W = 8;\n"
" parameter int HHHH = 2;\n"
"endmodule\n"},
{// parameter pre-aligned preserved
"module m;\n"
"parameter int W = 8;\n"
"parameter int HHHH = 2;\n"
"endmodule\n",
"module m;\n"
" parameter int W = 8;\n"
" parameter int HHHH = 2;\n"
"endmodule\n"},
{// interface pre-aligned preserved
"interface my_if;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"endinterface\n",
"interface my_if;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"endinterface\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kPreserve;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify kAlign behavior for param/localparam declarations across
// interface, generate, and module body contexts, including mixed
// param/localparam and packed dimension alignment.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentContexts) {
static constexpr FormatterTestCase kTestCases[] = {
{// interface body localparam alignment
"interface my_if;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"endinterface\n",
"interface my_if;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"endinterface\n"},
{// interface body parameter alignment
"interface my_if;\n"
"parameter int X = 1;\n"
"parameter int Y_LONG = 2;\n"
"endinterface\n",
"interface my_if;\n"
" parameter int X = 1;\n"
" parameter int Y_LONG = 2;\n"
"endinterface\n"},
{// generate block localparam alignment
"module m;\n"
"generate\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"endgenerate\n"
"endmodule\n",
"module m;\n"
" generate\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" endgenerate\n"
"endmodule\n"},
{// generate block parameter alignment
"module m;\n"
"generate\n"
"parameter int A = 1;\n"
"parameter int BB = 2;\n"
"endgenerate\n"
"endmodule\n",
"module m;\n"
" generate\n"
" parameter int A = 1;\n"
" parameter int BB = 2;\n"
" endgenerate\n"
"endmodule\n"},
{// mixed param and net declarations form separate alignment groups
"module m;\n"
"localparam X = 1;\n"
"localparam YYY = 2;\n"
"logic clk;\n"
"logic rst_n;\n"
"localparam ZZ = 3;\n"
"endmodule\n",
"module m;\n"
" localparam X = 1;\n"
" localparam YYY = 2;\n"
" logic clk;\n"
" logic rst_n;\n"
" localparam ZZ = 3;\n"
"endmodule\n"},
{// mixed parameter and localparam in same block
"module m;\n"
"parameter int W = 8;\n"
"localparam L = 4;\n"
"parameter int H = 2;\n"
"endmodule\n",
"module m;\n"
" parameter int W = 8;\n"
" localparam L = 4;\n"
" parameter int H = 2;\n"
"endmodule\n"},
{// packed dimensions are aligned
"module m;\n"
"parameter bit [7:0] X = 0;\n"
"parameter bit [31:0] YYYY = 1;\n"
"endmodule\n",
"module m;\n"
" parameter bit [ 7:0] X = 0;\n"
" parameter bit [31:0] YYYY = 1;\n"
"endmodule\n"},
{// multi-identifier comma-separated params are not split (no-crash)
"module m;\n"
"parameter int a=1, b=2, ccc=3;\n"
"localparam d=4, e=5;\n"
"endmodule\n",
"module m;\n"
" parameter int a = 1, b = 2, ccc = 3;\n"
" localparam d = 4, e = 5;\n"
"endmodule\n"},
{// parameter type declarations do not crash
"module m;\n"
"parameter type T = int;\n"
"parameter type TT_LONG = bit;\n"
"endmodule\n",
"module m;\n"
" parameter type T = int;\n"
" parameter type TT_LONG = bit;\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify kInferUserIntent behavior: body-level param/localparam
// declarations infer alignment intent from existing spacing.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentInferUserIntent) {
static constexpr FormatterTestCase kTestCases[] = {
{// flush-left localparams with small spacing diff: infer aligns
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"endmodule\n"},
{// pre-aligned localparams: infer preserves alignment
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"localparam baaaaz = 3;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" localparam baaaaz = 3;\n"
"endmodule\n"},
{// flush-left params in package with small spacing diff: infer aligns
"package p;\n"
"localparam X = 1;\n"
"localparam YY = 2;\n"
"endpackage\n",
"package p;\n"
" localparam X = 1;\n"
" localparam YY = 2;\n"
"endpackage\n"},
{// mixed param/localparam flush-left: infer keeps flush-left
"module m;\n"
"parameter int W = 8;\n"
"localparam L = 4;\n"
"endmodule\n",
"module m;\n"
" parameter int W = 8;\n"
" localparam L = 4;\n"
"endmodule\n"},
{// interface flush-left with small diff: infer aligns
"interface my_if;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"endinterface\n",
"interface my_if;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"endinterface\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kInferUserIntent;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify boundary behavior for param declarations with
// kBlankLinesAndSeparatorComments: both blank lines and separator comments
// break alignment groups.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentBoundary) {
static constexpr FormatterTestCase kTestCases[] = {
{// separator comment breaks param alignment group
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"// ============\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" // ============\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endmodule\n"},
{// blank line breaks param alignment group
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endmodule\n"},
{// no separator: single alignment group (all aligned together)
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endmodule\n"},
{// regular comment does NOT break alignment group
"module m;\n"
"localparam foo = 1;\n"
"// regular comment\n"
"localparam barr = 2;\n"
"localparam baaaaz = 1;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" // regular comment\n"
" localparam barr = 2;\n"
" localparam baaaaz = 1;\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
style.alignment_group_boundary =
AlignmentGroupBoundary::kBlankLinesAndSeparatorComments;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify edge cases: unpacked dimensions, signed/unsigned, implicit types,
// complex types, single declarations, deeply nested generate blocks.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentEdgeCases) {
// Use column_limit = 80 to avoid unintended line wrapping inside
// deeply nested generate blocks (generate-if, generate-for), which
// would interfere with verifying alignment behavior.
static constexpr FormatterTestCase kTestCases[] = {
{// unpacked dimension alignment
"module m;\n"
"parameter bit X [7:0] = 0;\n"
"parameter bit YYYY [15:0] = 1;\n"
"endmodule\n",
"module m;\n"
" parameter bit X [ 7:0] = 0;\n"
" parameter bit YYYY[15:0] = 1;\n"
"endmodule\n"},
{// param declarations with only type and default value (no idim)
"module m;\n"
"parameter int X = 0;\n"
"parameter int YYYY = 0;\n"
"endmodule\n",
"module m;\n"
" parameter int X = 0;\n"
" parameter int YYYY = 0;\n"
"endmodule\n"},
{// signed modifier with packed dimensions
"module m;\n"
"parameter bit signed [7:0] X = 0;\n"
"parameter bit signed [31:0] YYYY = 1;\n"
"endmodule\n",
"module m;\n"
" parameter bit signed [ 7:0] X = 0;\n"
" parameter bit signed [31:0] YYYY = 1;\n"
"endmodule\n"},
{// param with complex type (struct/typedef) — does not crash
"module m;\n"
"parameter foo_t X = foo_t'(0);\n"
"parameter foo_t Y_LONG = foo_t'(0);\n"
"endmodule\n",
"module m;\n"
" parameter foo_t X = foo_t'(0);\n"
" parameter foo_t Y_LONG = foo_t'(0);\n"
"endmodule\n"},
{// single param declaration (not enough for alignment group)
"module m;\n"
"localparam X = 1;\n"
"endmodule\n",
"module m;\n"
" localparam X = 1;\n"
"endmodule\n"},
{// params inside generate-if block
"module m;\n"
"generate\n"
"if (1) begin : blk\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"end\n"
"endgenerate\n"
"endmodule\n",
"module m;\n"
" generate\n"
" if (1) begin : blk\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" end\n"
" endgenerate\n"
"endmodule\n"},
{// unsigned keyword with packed dimensions (complement to signed)
"module m;\n"
"parameter bit unsigned [7:0] X = 0;\n"
"parameter bit unsigned [31:0] YYYY = 1;\n"
"endmodule\n",
"module m;\n"
" parameter bit unsigned [ 7:0] X = 0;\n"
" parameter bit unsigned [31:0] YYYY = 1;\n"
"endmodule\n"},
{// parameter with implicit type (no explicit type keyword)
"module m;\n"
"parameter X = 32;\n"
"parameter Y_LONG = 64;\n"
"endmodule\n",
"module m;\n"
" parameter X = 32;\n"
" parameter Y_LONG = 64;\n"
"endmodule\n"},
{// params inside generate-for block
"module m;\n"
"generate\n"
"for (i = 0; i < 2; i++) begin : blk\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"end\n"
"endgenerate\n"
"endmodule\n",
"module m;\n"
" generate\n"
" for (i = 0; i < 2; i++) begin : blk\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" end\n"
" endgenerate\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 80;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify parameter declarations inside generate-case blocks are aligned.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentGenerateCase) {
// Params inside generate-case need wider column limit to avoid wrapping the
// case label / begin block line.
static constexpr FormatterTestCase kTestCases[] = {
{// params inside generate-case block
"module m #(P = 0);\n"
"generate\n"
"case (P)\n"
"0: begin : blk\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"end\n"
"endcase\n"
"endgenerate\n"
"endmodule\n",
"module m #(\n"
" P = 0\n"
");\n"
" generate\n"
" case (P)\n"
" 0: begin : blk\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" end\n"
" endcase\n"
" endgenerate\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 80;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
TEST(FormatterEndToEndTest, FormalAndBodyParamAlignmentIndependence) {
// Verify that --formal_parameters_alignment and
// --parameter_declaration_alignment act independently: setting formal params
// to kFlushLeft should not affect body-level param alignment, and vice versa.
static constexpr FormatterTestCase kTestCases[] = {
{// formal flush-left + body align: only body params align
"module m #(\n"
"int W = 2,\n"
"int LLLL = 4\n"
");\n"
"localparam foo = 0;\n"
"localparam barrrr = 0;\n"
"endmodule\n",
"module m #(\n"
" int W = 2,\n"
" int LLLL = 4\n"
");\n"
" localparam foo = 0;\n"
" localparam barrrr = 0;\n"
"endmodule\n"},
{// formal align + body flush-left: only formal params align
"module m #(\n"
"int W = 2,\n"
"int LLLL = 4\n"
");\n"
"localparam foo = 0;\n"
"localparam barrrr = 0;\n"
"endmodule\n",
"module m #(\n"
" int W = 2,\n"
" int LLLL = 4\n"
");\n"
" localparam foo = 0;\n"
" localparam barrrr = 0;\n"
"endmodule\n"},
{// both flush-left: no alignment anywhere
"module m #(\n"
"int W = 2,\n"
"int LLLL = 4\n"
");\n"
"localparam foo = 0;\n"
"localparam barrrr = 0;\n"
"endmodule\n",
"module m #(\n"
" int W = 2,\n"
" int LLLL = 4\n"
");\n"
" localparam foo = 0;\n"
" localparam barrrr = 0;\n"
"endmodule\n"},
{// both align: both formal and body params aligned
"module m #(\n"
"int W = 2,\n"
"int LLLL = 4\n"
");\n"
"localparam foo = 0;\n"
"localparam barrrr = 0;\n"
"endmodule\n",
"module m #(\n"
" int W = 2,\n"
" int LLLL = 4\n"
");\n"
" localparam foo = 0;\n"
" localparam barrrr = 0;\n"
"endmodule\n"},
};
// First case: formal kFlushLeft, body kAlign
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
style.formal_parameters_alignment = AlignmentPolicy::kFlushLeft;
const auto &tc = kTestCases[0];
VLOG(1) << "code-to-format:\n" << tc.input << "<EOF>";
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// Second case: formal kAlign, body kFlushLeft
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kFlushLeft;
style.formal_parameters_alignment = AlignmentPolicy::kAlign;
const auto &tc = kTestCases[1];
VLOG(1) << "code-to-format:\n" << tc.input << "<EOF>";
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// Third case: both kFlushLeft
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kFlushLeft;
style.formal_parameters_alignment = AlignmentPolicy::kFlushLeft;
const auto &tc = kTestCases[2];
VLOG(1) << "code-to-format:\n" << tc.input << "<EOF>";
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// Fourth case: both kAlign
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
style.formal_parameters_alignment = AlignmentPolicy::kAlign;
const auto &tc = kTestCases[3];
VLOG(1) << "code-to-format:\n" << tc.input << "<EOF>";
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
}
TEST(FormatterEndToEndTest, ClassBodyParamNotAffected) {
// Verify that class body parameter/localparam declarations are NOT affected
// by --parameter_declaration_alignment, which targets only module/generate/
// package/interface body-level params.
static constexpr FormatterTestCase kTestCases[] = {
{// class body params are not affected
"class c;\n"
"parameter int X = 1;\n"
"parameter int YYYY = 2;\n"
"localparam foo = 3;\n"
"localparam barrrr = 4;\n"
"endclass\n",
"class c;\n"
" parameter int X = 1;\n"
" parameter int YYYY = 2;\n"
" localparam foo = 3;\n"
" localparam barrrr = 4;\n"
"endclass\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
TEST(FormatterEndToEndTest, PackageBodyVariableAlignment) {
// Verify that moving kPackageItemList to kTabularAlignment in tree-unwrapper
// enables net/variable declaration alignment in package bodies via
// module_net_variable_alignment.
static constexpr FormatterTestCase kTestCases[] = {
{// net/variable declaration alignment in package body
"package p;\n"
"logic [7:0] a;\n"
"logic [31:0] bb;\n"
"endpackage\n",
"package p;\n"
" logic [ 7:0] a;\n"
" logic [31:0] bb;\n"
"endpackage\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.module_net_variable_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentApplyToAll) {
// Verify that ApplyToAllAlignmentPolicies affects
// parameter_declaration_alignment for all four alignment policies.
static constexpr FormatterTestCase kTestCases[] = {
{// kAlign aligns identifiers and = signs across declarations
"module m;\n"
"localparam foo = 1;\n"
"localparam barrrr = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barrrr = 2;\n"
"endmodule\n"},
{// kFlushLeft: declarations remain flush-left
"module m;\n"
"localparam foo = 1;\n"
"localparam barrrr = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barrrr = 2;\n"
"endmodule\n"},
{// kPreserve: existing spacing is kept
"module m;\n"
"localparam foo = 1;\n"
"localparam barrrr = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barrrr = 2;\n"
"endmodule\n"},
{// kInferUserIntent: large identifier width difference (3 cols)
// suggests flush-left intent, no alignment.
"module m;\n"
"localparam foo = 1;\n"
"localparam barrrr = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barrrr = 2;\n"
"endmodule\n"},
};
// kAlign
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.ApplyToAllAlignmentPolicies(AlignmentPolicy::kAlign);
const auto &tc = kTestCases[0];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// kFlushLeft
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.ApplyToAllAlignmentPolicies(AlignmentPolicy::kFlushLeft);
const auto &tc = kTestCases[1];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// kPreserve
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.ApplyToAllAlignmentPolicies(AlignmentPolicy::kPreserve);
const auto &tc = kTestCases[2];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// kInferUserIntent
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.ApplyToAllAlignmentPolicies(AlignmentPolicy::kInferUserIntent);
const auto &tc = kTestCases[3];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
}
// Verify that alignment_group_boundary=kBlankLines treats only blank lines
// (not separator comments) as boundary breaks for param declarations.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentBoundaryBlankLines) {
static constexpr FormatterTestCase kTestCases[] = {
{// Only blank line breaks group; separator comment does not
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endmodule\n"},
{// Separator comment does NOT break group with kBlankLines
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"// ============\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" // ============\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
style.alignment_group_boundary = AlignmentGroupBoundary::kBlankLines;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify that alignment_group_boundary=kNone keeps all param declarations
// in a single alignment group regardless of blank lines or comments.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentBoundaryNone) {
static constexpr FormatterTestCase kTestCases[] = {
{// Blank line does NOT break group with kNone
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endmodule\n"},
{// Separator comment does NOT break group with kNone
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"// ============\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" // ============\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
style.alignment_group_boundary = AlignmentGroupBoundary::kNone;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify that alignment_group_boundary=kSeparatorComments treats only
// separator comments (not blank lines) as boundary breaks for param
// declarations.
TEST(FormatterEndToEndTest,
ParamDeclarationAlignmentBoundarySeparatorComments) {
static constexpr FormatterTestCase kTestCases[] = {
{// Separator comment breaks alignment group
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"// ============\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" // ============\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endmodule\n"},
{// Blank line does NOT break group with kSeparatorComments
"module m;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endmodule\n",
"module m;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
style.alignment_group_boundary = AlignmentGroupBoundary::kSeparatorComments;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify that class body parameter/localparam declarations are NOT affected
// by --parameter_declaration_alignment for the kFlushLeft, kPreserve,
// and kInferUserIntent policies (kAlign is covered in
// ClassBodyParamNotAffected).
TEST(FormatterEndToEndTest, ClassBodyParamNotAffectedOtherPolicies) {
static constexpr FormatterTestCase kTestCases[] = {
{// kFlushLeft: class body params remain flush-left
"class c;\n"
"parameter int X = 1;\n"
"parameter int YYYY = 2;\n"
"localparam foo = 3;\n"
"localparam barrrr = 4;\n"
"endclass\n",
"class c;\n"
" parameter int X = 1;\n"
" parameter int YYYY = 2;\n"
" localparam foo = 3;\n"
" localparam barrrr = 4;\n"
"endclass\n"},
{// kPreserve: parameter_declaration_alignment does not apply to class
// bodies; whitespace is normalized by default formatting.
"class c;\n"
"parameter int X = 1;\n"
"parameter int YYYY = 2;\n"
"endclass\n",
"class c;\n"
" parameter int X = 1;\n"
" parameter int YYYY = 2;\n"
"endclass\n"},
{// kInferUserIntent: class body params infer flush-left
"class c;\n"
"parameter int X = 1;\n"
"parameter int YYYY = 2;\n"
"endclass\n",
"class c;\n"
" parameter int X = 1;\n"
" parameter int YYYY = 2;\n"
"endclass\n"},
};
// kFlushLeft
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kFlushLeft;
const auto &tc = kTestCases[0];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// kPreserve
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kPreserve;
const auto &tc = kTestCases[1];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// kInferUserIntent
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kInferUserIntent;
const auto &tc = kTestCases[2];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
}
// Verify formal_parameters_alignment and parameter_declaration_alignment
// independence for kPreserve and kInferUserIntent combinations.
TEST(FormatterEndToEndTest,
FormalAndBodyParamAlignmentIndependenceOtherPolicies) {
static constexpr FormatterTestCase kTestCases[] = {
{// formal kPreserve + body kAlign: only body params aligned
"module m #(\n"
"int W = 2,\n"
"int LLLL = 4\n"
");\n"
"localparam foo = 0;\n"
"localparam barrrr = 0;\n"
"endmodule\n",
"module m #(\n"
" int W = 2,\n"
" int LLLL = 4\n"
");\n"
" localparam foo = 0;\n"
" localparam barrrr = 0;\n"
"endmodule\n"},
{// formal kAlign + body kPreserve: only formal params aligned
"module m #(\n"
"int W = 2,\n"
"int LLLL = 4\n"
");\n"
"localparam foo = 0;\n"
"localparam barrrr = 0;\n"
"endmodule\n",
"module m #(\n"
" int W = 2,\n"
" int LLLL = 4\n"
");\n"
" localparam foo = 0;\n"
" localparam barrrr = 0;\n"
"endmodule\n"},
{// formal kInferUserIntent + body kAlign: only body params aligned
"module m #(\n"
"int W = 2,\n"
"int LLLL = 4\n"
");\n"
"localparam foo = 0;\n"
"localparam barrrr = 0;\n"
"endmodule\n",
"module m #(\n"
" int W = 2,\n"
" int LLLL = 4\n"
");\n"
" localparam foo = 0;\n"
" localparam barrrr = 0;\n"
"endmodule\n"},
};
// formal kPreserve + body kAlign
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
style.formal_parameters_alignment = AlignmentPolicy::kPreserve;
const auto &tc = kTestCases[0];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// formal kAlign + body kPreserve
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kPreserve;
style.formal_parameters_alignment = AlignmentPolicy::kAlign;
const auto &tc = kTestCases[1];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
// formal kInferUserIntent + body kAlign
{
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
style.formal_parameters_alignment = AlignmentPolicy::kInferUserIntent;
const auto &tc = kTestCases[2];
std::ostringstream stream;
const auto status = FormatVerilog(tc.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), tc.expected) << "code:\n" << tc.input;
}
}
// Verify parameter declarations with string, real, and function-call default
// value types to exercise the ColumnSchemaScanner on non-standard type tokens.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentTypeVariants) {
static constexpr FormatterTestCase kTestCases[] = {
{// parameter real type
"module m;\n"
"parameter real X = 1.0;\n"
"parameter real Y_LONG = 2.0;\n"
"endmodule\n",
"module m;\n"
" parameter real X = 1.0;\n"
" parameter real Y_LONG = 2.0;\n"
"endmodule\n"},
{// parameter string type
"module m;\n"
"parameter string s = \"hello\";\n"
"parameter string long_s = \"world\";\n"
"endmodule\n",
"module m;\n"
" parameter string s = \"hello\";\n"
" parameter string long_s = \"world\";\n"
"endmodule\n"},
{// parameter with function call in default value
"module m;\n"
"parameter int W = func(1, 2);\n"
"parameter int H_LONG = other(3);\n"
"endmodule\n",
"module m;\n"
" parameter int W = func(1, 2);\n"
" parameter int H_LONG = other(3);\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify parameter_declaration_alignment kInferUserIntent in package bodies.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentPackageInfer) {
static constexpr FormatterTestCase kTestCases[] = {
{// flush-left params with small diff: infer aligns
"package p;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"endpackage\n",
"package p;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"endpackage\n"},
{// pre-aligned params: infer preserves
"package p;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"localparam baaaaz = 3;\n"
"endpackage\n",
"package p;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" localparam baaaaz = 3;\n"
"endpackage\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kInferUserIntent;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify parameter_declaration_alignment boundary behavior in package bodies.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentPackageBoundary) {
static constexpr FormatterTestCase kTestCases[] = {
{// blank line breaks alignment group in package
"package p;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endpackage\n",
"package p;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
"\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endpackage\n"},
{// separator comment breaks alignment group in package
"package p;\n"
"localparam foo = 1;\n"
"localparam barr = 2;\n"
"// ============\n"
"localparam baaaaz = 1;\n"
"localparam c = 2;\n"
"endpackage\n",
"package p;\n"
" localparam foo = 1;\n"
" localparam barr = 2;\n"
" // ============\n"
" localparam baaaaz = 1;\n"
" localparam c = 2;\n"
"endpackage\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
style.alignment_group_boundary =
AlignmentGroupBoundary::kBlankLinesAndSeparatorComments;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify the most common default scenario: both formal_parameters_alignment
// and parameter_declaration_alignment set to kInferUserIntent.
TEST(FormatterEndToEndTest, BothParamAlignmentsInferUserIntent) {
static constexpr FormatterTestCase kTestCases[] = {
{// both flush-left with small diff: infer aligns both formal and body
"module m #(\n"
"int W = 2,\n"
"int LL = 4\n"
");\n"
"localparam foo = 0;\n"
"localparam barr = 0;\n"
"endmodule\n",
"module m #(\n"
" int W = 2,\n"
" int LL = 4\n"
");\n"
" localparam foo = 0;\n"
" localparam barr = 0;\n"
"endmodule\n"},
{// both infer: pre-aligned formal, pre-aligned body preserved
"module m #(\n"
"int W = 2,\n"
"int LLLL = 4\n"
");\n"
"localparam foo = 0;\n"
"localparam barrrr = 0;\n"
"endmodule\n",
"module m #(\n"
" int W = 2,\n"
" int LLLL = 4\n"
");\n"
" localparam foo = 0;\n"
" localparam barrrr = 0;\n"
"endmodule\n"},
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kInferUserIntent;
style.formal_parameters_alignment = AlignmentPolicy::kInferUserIntent;
for (const auto &test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream;
const auto status =
FormatVerilog(test_case.input, "<filename>", style, stream);
EXPECT_OK(status) << status.message();
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
}
}
// Verify that a large multi-line comment block between parameter
// declarations does not crash the formatter. The tree-unwrapper may
// produce a partition structure where the comment tokens are absorbed
// into the following parameter partition, which the alignment code
// must handle gracefully by skipping alignment for that row.
TEST(FormatterEndToEndTest, ParamDeclarationAlignmentCommentBlockNoCrash) {
// These inputs contain large multi-line comment blocks between
// parameter/localparam declarations. The formatter must not crash
// (SIGABRT). Output correctness is secondary; the formatter may
// fall back to preserving the original input when the partition
// structure prevents safe alignment.
const char *kInputs[] = {
"module m;\n"
"parameter int W = 8;\n"
"// Multi-line comment block\n"
"// that spans across\n"
"//\n"
"// several lines\n"
"// of explanatory text\n"
"//\n"
"// It contains enough\n"
"// lines to trigger\n"
"// the partition structure\n"
"// edge case where\n"
"// comment tokens are\n"
"// absorbed into the\n"
"// following parameter\n"
"// partition.\n"
"//\n"
"localparam int H = 2;\n"
"endmodule\n",
"package p;\n"
"parameter int X = 1;\n"
"// Long comment block\n"
"// with many lines\n"
"//\n"
"// of text\n"
"//\n"
"localparam int Y = 2;\n"
"endpackage\n",
};
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
style.parameter_declaration_alignment = AlignmentPolicy::kAlign;
for (const char *input : kInputs) {
VLOG(1) << "code-to-format:\n" << input << "<EOF>";
std::ostringstream stream;
const auto status = FormatVerilog(input, "<filename>", style, stream);
// The primary requirement is that the formatter does not crash
// (SIGABRT). Gtest will report failure if the process aborts.
// The partition structure may cause output format differences;
// the important thing is the formatter handled it gracefully.
}
}
} // namespace
} // namespace formatter
} // namespace verilog