| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
- // Exceptions. See /LICENSE for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- #include "toolchain/format/formatter.h"
- namespace Carbon::Format {
- auto Formatter::Run() -> bool {
- if (tokens_->has_errors()) {
- // TODO: Error recovery.
- return false;
- }
- auto comments = tokens_->comments();
- auto comment_it = comments.begin();
- // If there are no tokens or comments, format as empty.
- if (tokens_->size() == 0 && comment_it == comments.end()) {
- *out_ << "\n";
- return true;
- }
- for (auto token : tokens_->tokens()) {
- auto token_kind = tokens_->GetKind(token);
- while (comment_it != comments.end() &&
- tokens_->IsAfterComment(token, *comment_it)) {
- RequireEmptyLine();
- PrepareForSpacedContent();
- // TODO: We do need to adjust the indent of multi-line comments.
- *out_ << tokens_->GetCommentText(*comment_it);
- // Comment text includes a terminating newline, so just update the state.
- line_state_ = LineState::Empty;
- ++comment_it;
- }
- switch (token_kind) {
- case Lex::TokenKind::FileStart:
- break;
- case Lex::TokenKind::FileEnd:
- RequireEmptyLine();
- break;
- case Lex::TokenKind::OpenCurlyBrace:
- PrepareForSpacedContent();
- *out_ << "{";
- // Check for `{}`.
- if (NextToken(token) != tokens_->GetMatchedClosingToken(token)) {
- RequireEmptyLine();
- }
- indent_ += 2;
- break;
- case Lex::TokenKind::CloseCurlyBrace:
- indent_ -= 2;
- PrepareForPackedContent();
- *out_ << "}";
- RequireEmptyLine();
- break;
- case Lex::TokenKind::Semi:
- PrepareForPackedContent();
- *out_ << ";";
- RequireEmptyLine();
- break;
- default:
- if (token_kind.IsOneOf(
- {Lex::TokenKind::CloseParen, Lex::TokenKind::Colon,
- Lex::TokenKind::ColonExclaim, Lex::TokenKind::Comma})) {
- PrepareForPackedContent();
- } else {
- PrepareForSpacedContent();
- }
- *out_ << tokens_->GetTokenText(token);
- line_state_ = token_kind.is_opening_symbol()
- ? LineState::HasSeparator
- : LineState::NeedsSeparator;
- break;
- }
- }
- return true;
- }
- auto Formatter::PrepareForPackedContent() -> void {
- if (line_state_ == LineState::Empty) {
- out_->indent(indent_);
- line_state_ = LineState::HasSeparator;
- }
- }
- auto Formatter::RequireEmptyLine() -> void {
- if (line_state_ != LineState::Empty) {
- *out_ << "\n";
- line_state_ = LineState::Empty;
- }
- }
- auto Formatter::PrepareForSpacedContent() -> void {
- if (line_state_ == LineState::NeedsSeparator) {
- *out_ << " ";
- line_state_ = LineState::HasSeparator;
- } else {
- PrepareForPackedContent();
- }
- }
- } // namespace Carbon::Format
|