| // 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. |
| |
| #ifndef VERIBLE_COMMON_FORMATTING_UNWRAPPED_LINE_H_ |
| #define VERIBLE_COMMON_FORMATTING_UNWRAPPED_LINE_H_ |
| |
| #include <iosfwd> |
| #include <string> |
| #include <vector> |
| |
| #include "common/formatting/format_token.h" |
| #include "common/text/symbol.h" |
| |
| namespace verible { |
| |
| // Enumeration of partitioning choices at each node in the UnwrappedLine |
| // token range partition tree. |
| // TODO(fangism): It is forseeable that each language's formatter may have a |
| // different set of policies, this this might eventually have to move into |
| // language-specific implementation code. |
| enum class PartitionPolicyEnum { |
| // Denotes that no partition policy has been set. |
| kUninitialized, |
| |
| // This partition exists solely just for grouping purposes. |
| // Always view subpartitions of node tagged with this, rather than whole range |
| // spanned by the subpartitions. |
| kAlwaysExpand, |
| |
| // Collapse into one line if it doesn't exceed column limit. |
| kFitOnLineElseExpand, |
| |
| // There's no kNeverExpand, because one would just not create the partition in |
| // the first place. |
| |
| // This is where future formatting configuration policies could go: |
| // e.g. kOneItemPerLine, kCompactItems |
| |
| // With this policy, coordinate the spacing of subpartitions like auto-sized |
| // columns that use space-padding to achieve vertical alignment. |
| kTabularAlignment, |
| |
| // Signal that this unwrapped line (a direct child of a partition marked with |
| // kTabularAlignment) has been successfully aligned with spacing padded. |
| // In this case, do NOT bother to call SearchLineWraps or perform any other |
| // spacing/wrapping optimization. |
| // Reserved for setting only from align.cc. |
| kSuccessfullyAligned, |
| |
| // Treats subpartitions as units, and appends them to the same line as |
| // long as they fit, else wrap them aligned to the position of the first |
| // element It uses first subpartition length to compute indentation spaces or |
| // FormatStyle.wrap_spaces when wrapping. |
| kAppendFittingSubPartitions, |
| }; |
| |
| std::ostream& operator<<(std::ostream&, PartitionPolicyEnum); |
| |
| // An UnwrappedLine represents a partition of the input token stream that |
| // is an independent unit of work for other phases of formatting, such as |
| // line wrap optimization. It consists of a lightweight const_iterator range |
| // that can be easily grown without any copy-overhead. |
| class UnwrappedLine { |
| typedef FormatTokenRange::const_iterator token_iterator; |
| |
| public: |
| enum { |
| kIndentationMarker = '>' // for readable debug printing |
| }; |
| |
| // Parameter d is the indentation level, and iterator b points to the first |
| // PreFormatToken spanned by this range, which is initially empty. |
| UnwrappedLine(int d, token_iterator b, |
| PartitionPolicyEnum p = PartitionPolicyEnum::kUninitialized) |
| : indentation_spaces_(d), tokens_(b, b), partition_policy_(p) {} |
| |
| // Allow default construction for use in resize-able containers. |
| UnwrappedLine() = default; |
| UnwrappedLine(const UnwrappedLine&) = default; |
| UnwrappedLine(UnwrappedLine&&) = default; |
| UnwrappedLine& operator=(const UnwrappedLine&) = default; |
| UnwrappedLine& operator=(UnwrappedLine&&) = default; |
| |
| // Extends PreFormatToken range spanned by this UnwrappedLine by one token at |
| // the back. |
| void SpanNextToken() { tokens_.extend_back(); } |
| |
| // Extends PreFormatToken range spanned by this UnwrappedLine by one token at |
| // the front. |
| void SpanPrevToken() { tokens_.extend_front(); } |
| |
| // Extends PreFormatToken range's lower bound to the given token (inclusive). |
| void SpanBackToToken(token_iterator iter) { tokens_.set_begin(iter); } |
| |
| // Extends PreFormatToken range's upper bound up to the given token |
| // (exclusive). |
| void SpanUpToToken(token_iterator iter) { tokens_.set_end(iter); } |
| |
| int IndentationSpaces() const { return indentation_spaces_; } |
| |
| void SetIndentationSpaces(int spaces); |
| |
| PartitionPolicyEnum PartitionPolicy() const { return partition_policy_; } |
| |
| void SetPartitionPolicy(PartitionPolicyEnum policy) { |
| partition_policy_ = policy; |
| } |
| |
| const Symbol* Origin() const { return origin_; } |
| void SetOrigin(const Symbol* origin) { origin_ = origin; } |
| |
| // Returns the range of PreFormatTokens spanned by this UnwrappedLine. |
| // Note that this is a *copy*, and not a reference to the underlying range. |
| FormatTokenRange TokensRange() const { return tokens_; } |
| |
| // Returns the number of tokens in this UnwrappedLine |
| size_t Size() const { return tokens_.size(); } |
| |
| // Returns true if the UnwrappedLine is empty, if it has no tokens |
| bool IsEmpty() const { return tokens_.empty(); } |
| |
| // Currently for debugging, prints the UnwrappedLine as Code |
| std::ostream* AsCode(std::ostream*, bool verbose = false) const; |
| |
| private: |
| // Data members: |
| |
| // indentation_spaces_ is the number of spaces to indent from the left. |
| int indentation_spaces_; |
| |
| // The range of sequential PreFormatTokens spanned by this UnwrappedLine. |
| // These represent the tokens that will be formatted independently. |
| // The memory for these must be owned elsewhere. |
| FormatTokenRange tokens_; |
| |
| // This determines under what conditions this UnwrappedLine should be |
| // further partitioned for formatting. |
| PartitionPolicyEnum partition_policy_ = PartitionPolicyEnum::kUninitialized; |
| |
| // Hint about the origin of this partition, e.g. a particular syntax |
| // tree node/leaf. |
| const Symbol* origin_ = nullptr; |
| }; |
| |
| std::ostream& operator<<(std::ostream&, const UnwrappedLine&); |
| |
| // FormattedExcerpt is the result of formatting a slice of code represented |
| // as an UnwrappedLine. In this representation, wrapping and spacing decisions |
| // are considered bound. |
| // TODO(fangism): move this class to its own file. |
| class FormattedExcerpt { |
| public: |
| FormattedExcerpt() = default; |
| |
| explicit FormattedExcerpt(const UnwrappedLine&); |
| |
| // Returns the number of spaces to indent. |
| int IndentationSpaces() const { return indentation_spaces_; } |
| |
| const std::vector<FormattedToken>& Tokens() const { return tokens_; } |
| |
| // Note: The mutable variant is only intended for use in StateNode. |
| std::vector<FormattedToken>& MutableTokens() { return tokens_; } |
| |
| // Prints formatted text. If indent is true, include the spacing |
| // that is to the left of the first token. |
| std::ostream& FormattedText(std::ostream&, bool indent) const; |
| |
| // Returns formatted code as a string. |
| std::string Render() const; |
| |
| // Signal to the consumer that the analysis use to construct this |
| // formatted excerpt did not run to completion, and that the result |
| // may be unoptimal. |
| void MarkIncomplete() { completed_formatting_ = false; } |
| |
| // Returns true if this result represents optimal formatting. |
| bool CompletedFormatting() const { return completed_formatting_; } |
| |
| private: |
| // Number of spaces to indent this line from the left. |
| int indentation_spaces_ = 0; |
| |
| // Sequence of formatted tokens. |
| std::vector<FormattedToken> tokens_; |
| |
| // If true, this result can be interpreted as formatting-optimal. |
| // if false, this is the result of incomplete optimization. |
| bool completed_formatting_ = true; |
| }; |
| |
| std::ostream& operator<<(std::ostream&, const FormattedExcerpt&); |
| |
| } // namespace verible |
| |
| #endif // VERIBLE_COMMON_FORMATTING_UNWRAPPED_LINE_H_ |