Expose a short-term flag to configure wrapping/indentation spaces.
This supports teams who insist on a "different" style than the default.
--port_declarations_indentation= {indent for 2 spaces, wrap for 4 spaces}
Initially, this only covers port declarations (modules, interfaces).
Other contexts may follow.
We do not publish these flags because they will be re-organized down the road.
issues #40
PiperOrigin-RevId: 330977558
diff --git a/common/formatting/BUILD b/common/formatting/BUILD
index d27c821..6d2972f 100644
--- a/common/formatting/BUILD
+++ b/common/formatting/BUILD
@@ -51,7 +51,21 @@
cc_library(
name = "basic_format_style",
+ srcs = ["basic_format_style.cc"],
hdrs = ["basic_format_style.h"],
+ deps = [
+ "//common/util:enum_flags",
+ "@com_google_absl//absl/strings",
+ ],
+)
+
+cc_test(
+ name = "basic_format_style_test",
+ srcs = ["basic_format_style_test.cc"],
+ deps = [
+ ":basic_format_style",
+ "@com_google_googletest//:gtest_main",
+ ],
)
cc_library(
diff --git a/common/formatting/basic_format_style.cc b/common/formatting/basic_format_style.cc
new file mode 100644
index 0000000..9ccf9da
--- /dev/null
+++ b/common/formatting/basic_format_style.cc
@@ -0,0 +1,58 @@
+// Copyright 2017-2020 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.
+
+#include "common/formatting/basic_format_style.h"
+
+#include <initializer_list>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "absl/strings/string_view.h"
+#include "common/util/enum_flags.h"
+
+namespace verible {
+
+namespace internal {
+// This mapping defines how this enum is displayed and parsed.
+constexpr std::initializer_list<
+ std::pair<const absl::string_view, IndentationStyle>>
+ kIndentationStyleStringMap = {
+ {"indent", IndentationStyle::kIndent},
+ {"wrap", IndentationStyle::kWrap},
+};
+} // namespace internal
+
+std::ostream& operator<<(std::ostream& stream, IndentationStyle p) {
+ static const auto* flag_map =
+ verible::MakeEnumToStringMap(internal::kIndentationStyleStringMap);
+ return stream << flag_map->find(p)->second;
+}
+
+bool AbslParseFlag(absl::string_view text, IndentationStyle* mode,
+ std::string* error) {
+ static const auto* flag_map =
+ verible::MakeStringToEnumMap(internal::kIndentationStyleStringMap);
+ return EnumMapParseFlag(*flag_map, text, mode, error);
+}
+
+std::string AbslUnparseFlag(const IndentationStyle& mode) {
+ std::ostringstream stream;
+ stream << mode;
+ return stream.str();
+}
+
+} // namespace verible
diff --git a/common/formatting/basic_format_style.h b/common/formatting/basic_format_style.h
index b93a0e1..cf4b782 100644
--- a/common/formatting/basic_format_style.h
+++ b/common/formatting/basic_format_style.h
@@ -15,6 +15,11 @@
#ifndef VERIBLE_COMMON_FORMATTING_BASIC_FORMAT_STYLE_H_
#define VERIBLE_COMMON_FORMATTING_BASIC_FORMAT_STYLE_H_
+#include <iosfwd>
+#include <string>
+
+#include "absl/strings/string_view.h"
+
namespace verible {
// Style configuration common to all languages.
@@ -36,6 +41,24 @@
int over_column_limit_penalty = 100;
};
+// Control how a section of code is indented.
+enum class IndentationStyle {
+ // One unit of indentation.
+ // This applies verible::BasicFormatStyle::indentation_spaces amount of
+ // spaces.
+ kIndent,
+ // Indentation that is applied to long, continued lines.
+ // This is also known as hang-indent.
+ // This applies verible::BasicFormatStyle::wrap_spaces amount of spaces.
+ kWrap,
+};
+
+std::ostream& operator<<(std::ostream&, IndentationStyle);
+
+bool AbslParseFlag(absl::string_view, IndentationStyle*, std::string*);
+
+std::string AbslUnparseFlag(const IndentationStyle&);
+
} // namespace verible
#endif // VERIBLE_COMMON_FORMATTING_BASIC_FORMAT_STYLE_H_
diff --git a/common/formatting/basic_format_style_test.cc b/common/formatting/basic_format_style_test.cc
new file mode 100644
index 0000000..f908553
--- /dev/null
+++ b/common/formatting/basic_format_style_test.cc
@@ -0,0 +1,44 @@
+// Copyright 2017-2020 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.
+
+#include "common/formatting/basic_format_style.h"
+
+#include <string>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace verible {
+namespace {
+
+TEST(IndentationStyleParseFlagTest, Parse) {
+ std::string error;
+ IndentationStyle istyle;
+ // Test valid values.
+ EXPECT_TRUE(AbslParseFlag("indent", &istyle, &error));
+ EXPECT_EQ(istyle, IndentationStyle::kIndent);
+ EXPECT_TRUE(AbslParseFlag("wrap", &istyle, &error));
+ EXPECT_EQ(istyle, IndentationStyle::kWrap);
+ // Test for invalid string.
+ EXPECT_FALSE(AbslParseFlag("invalid", &istyle, &error));
+}
+
+TEST(IndentationStyleUnparseFlagTest, Unparse) {
+ EXPECT_EQ(AbslUnparseFlag(IndentationStyle::kIndent), "indent");
+ EXPECT_EQ(AbslUnparseFlag(IndentationStyle::kWrap), "wrap");
+}
+
+} // namespace
+} // namespace verible
diff --git a/verilog/formatting/BUILD b/verilog/formatting/BUILD
index 6238a5c..ec81614 100644
--- a/verilog/formatting/BUILD
+++ b/verilog/formatting/BUILD
@@ -229,26 +229,14 @@
cc_library(
name = "format_style",
- srcs = ["format_style.cc"],
hdrs = ["format_style.h"],
deps = [
"//common/formatting:align",
"//common/formatting:basic_format_style",
- "//common/util:enum_flags",
"@com_google_absl//absl/strings",
],
)
-cc_test(
- name = "format_style_test",
- srcs = ["format_style_test.cc"],
- deps = [
- ":format_style",
- "//common/util:enum_flags_test_util",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
cc_library(
name = "token_annotator",
srcs = ["token_annotator.cc"],
diff --git a/verilog/formatting/format_style.cc b/verilog/formatting/format_style.cc
deleted file mode 100644
index abd3153..0000000
--- a/verilog/formatting/format_style.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017-2020 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.
-
-#include "verilog/formatting/format_style.h"
-
-#include <map>
-#include <sstream>
-#include <string>
-
-#include "absl/strings/string_view.h"
-#include "common/util/enum_flags.h"
-
-namespace verilog {
-namespace formatter {
-
-} // namespace formatter
-} // namespace verilog
diff --git a/verilog/formatting/format_style.h b/verilog/formatting/format_style.h
index fcc8454..885b9de 100644
--- a/verilog/formatting/format_style.h
+++ b/verilog/formatting/format_style.h
@@ -15,6 +15,10 @@
#ifndef VERIBLE_VERILOG_FORMATTING_FORMAT_STYLE_H_
#define VERIBLE_VERILOG_FORMATTING_FORMAT_STYLE_H_
+#include <iosfwd>
+#include <string>
+
+#include "absl/strings/string_view.h"
#include "common/formatting/align.h"
#include "common/formatting/basic_format_style.h"
@@ -24,11 +28,15 @@
// Style parameters that are specific to Verilog formatter
struct FormatStyle : public verible::BasicFormatStyle {
using AlignmentPolicy = verible::AlignmentPolicy;
+ using IndentationStyle = verible::IndentationStyle;
FormatStyle() : verible::BasicFormatStyle() {
over_column_limit_penalty = 10000;
}
+ // Control indentation amount for port declarations.
+ IndentationStyle port_declarations_indentation = IndentationStyle::kWrap;
+
// Control how named port_declaration (e.g. in modules, interfaces) are
// formatted. Internal tests assume these are forced to kAlign.
AlignmentPolicy port_declarations_alignment = AlignmentPolicy::kAlign;
@@ -78,6 +86,12 @@
// TODO(fangism): parameter to limit number of consecutive blank lines to
// preserve between partitions.
+ int PortDeclarationsIndentation() const {
+ return port_declarations_indentation == IndentationStyle::kWrap
+ ? wrap_spaces
+ : indentation_spaces;
+ }
+
void ApplyToAllAlignmentPolicies(AlignmentPolicy policy) {
port_declarations_alignment = policy;
named_parameter_alignment = policy;
diff --git a/verilog/formatting/format_style_test.cc b/verilog/formatting/format_style_test.cc
deleted file mode 100644
index af5ef67..0000000
--- a/verilog/formatting/format_style_test.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017-2020 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.
-
-#include "verilog/formatting/format_style.h"
-
-#include <utility>
-
-#include "gtest/gtest.h"
-#include "common/util/enum_flags_test_util.h"
-
-namespace verilog {
-namespace formatter {
-namespace {
-
-} // namespace
-} // namespace formatter
-} // namespace verilog
diff --git a/verilog/formatting/formatter_test.cc b/verilog/formatting/formatter_test.cc
index 70ec6d8..23b8a17 100644
--- a/verilog/formatting/formatter_test.cc
+++ b/verilog/formatting/formatter_test.cc
@@ -7477,6 +7477,65 @@
}
}
+TEST(FormatterEndToEndTest, ModulePortDeclarationsIndentNotWrap) {
+ static constexpr FormatterTestCase kTestCases[] = {
+ {"", ""},
+ {"\n", "\n"},
+ {"\n\n", "\n\n"},
+ {"module m ;\t\n"
+ " endmodule\n",
+ "module m;\n"
+ "endmodule\n"},
+ {"module m( ) ;\n"
+ " endmodule\n",
+ "module m ();\n" // empty ports formatted compactly
+ "endmodule\n"},
+ {// single port example
+ "module m ( input clk )\t;\n"
+ " endmodule\n",
+ "module m (\n"
+ " input clk\n" // 2 spaces
+ ");\n"
+ "endmodule\n"},
+ {// example with two ports
+ "module m (\n"
+ "input clk,\n"
+ "output bar\n"
+ ")\t;\n"
+ " endmodule\n",
+ "module m (\n"
+ " input clk,\n" // indented 2 spaces, and aligned
+ " output bar\n"
+ ");\n"
+ "endmodule\n"},
+ {// interface example
+ "interface handshake (\n"
+ "wire req,\n"
+ "wire ack\n"
+ ")\t;\n"
+ " endinterface\n",
+ "interface handshake (\n"
+ " wire req,\n" // indented 2 spaces
+ " wire ack\n"
+ ");\n"
+ "endinterface\n"},
+ };
+ FormatStyle style;
+ style.column_limit = 40;
+ style.indentation_spaces = 2;
+ style.wrap_spaces = 4;
+ // Indent 2 spaces instead of wrapping 4 spaces.
+ style.port_declarations_indentation = verible::IndentationStyle::kIndent;
+ 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);
+ // Require these test cases to be valid.
+ EXPECT_OK(status) << status.message();
+ EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
+ }
+}
struct SelectLinesTestCase {
absl::string_view input;
LineNumberSet lines; // explicit set of lines to enable formatting
diff --git a/verilog/formatting/tree_unwrapper.cc b/verilog/formatting/tree_unwrapper.cc
index 1b1e96c..c13b775 100644
--- a/verilog/formatting/tree_unwrapper.cc
+++ b/verilog/formatting/tree_unwrapper.cc
@@ -1030,7 +1030,21 @@
break;
}
- case NodeEnum::kPortDeclarationList:
+ case NodeEnum::kPortDeclarationList: {
+ // Do not further indent preprocessor clauses.
+ const int indent =
+ suppress_indentation ? 0 : style_.PortDeclarationsIndentation();
+ if (Context().IsInside(NodeEnum::kClassHeader) ||
+ // kModuleHeader covers interfaces and programs
+ Context().IsInside(NodeEnum::kModuleHeader)) {
+ VisitIndentedSection(node, indent,
+ PartitionPolicyEnum::kTabularAlignment);
+ } else {
+ VisitIndentedSection(node, indent,
+ PartitionPolicyEnum::kFitOnLineElseExpand);
+ }
+ break;
+ }
case NodeEnum::kFormalParameterList: {
// Do not further indent preprocessor clauses.
const int indent = suppress_indentation ? 0 : style_.wrap_spaces;
diff --git a/verilog/tools/formatter/verilog_format.cc b/verilog/tools/formatter/verilog_format.cc
index f504886..a3fbb63 100644
--- a/verilog/tools/formatter/verilog_format.cc
+++ b/verilog/tools/formatter/verilog_format.cc
@@ -47,6 +47,7 @@
using absl::StatusCode;
using verible::AlignmentPolicy;
+using verible::IndentationStyle;
using verible::LineNumberSet;
using verilog::formatter::ExecutionControl;
using verilog::formatter::FormatStyle;
@@ -122,6 +123,8 @@
// These flags exist in the short term to disable formatting of some regions.
// Do not expect to be able to use these in the long term, once they find
// a better home in a configuration struct.
+ABSL_FLAG(IndentationStyle, port_declarations_indentation,
+ IndentationStyle::kWrap, "Indent port declarations: {indent,wrap}");
// For most of the following in this group, kInferUserIntent is a reasonable
// default behavior because it allows for user-control with minimal invasiveness
@@ -205,6 +208,10 @@
// formatting style flags
format_style.try_wrap_long_lines = absl::GetFlag(FLAGS_try_wrap_long_lines);
+ // various indentation control
+ format_style.port_declarations_indentation =
+ absl::GetFlag(FLAGS_port_declarations_indentation);
+
// various alignment control
format_style.port_declarations_alignment =
absl::GetFlag(FLAGS_port_declarations_alignment);