|
| 1 | +//===--- TopLevelCommentSeparator.cpp ---------------------------*- C++ -*-===// |
| 2 | +// |
| 3 | +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | +// See https://llvm.org/LICENSE.txt for license information. |
| 5 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | +// |
| 7 | +//===----------------------------------------------------------------------===// |
| 8 | +/// |
| 9 | +/// \file |
| 10 | +/// This file implements TopLevelCommentSeparator, a TokenAnalyzer that inserts |
| 11 | +/// new lines or removes empty lines after the top level comment (i.e. comment |
| 12 | +/// block at the top of the source file), usually license text or documentation. |
| 13 | +/// |
| 14 | +//===----------------------------------------------------------------------===// |
| 15 | + |
| 16 | +#include "TopLevelCommentSeparator.h" |
| 17 | +#define DEBUG_TYPE "top-level-comment-separator" |
| 18 | + |
| 19 | +namespace clang { |
| 20 | +namespace format { |
| 21 | +std::pair<tooling::Replacements, unsigned> TopLevelCommentSeparator::analyze( |
| 22 | + TokenAnnotator &Annotator, SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, |
| 23 | + FormatTokenLexer &Tokens) { |
| 24 | + assert(Style.EmptyLinesAfterTopLevelComment.has_value()); |
| 25 | + AffectedRangeMgr.computeAffectedLines(AnnotatedLines); |
| 26 | + tooling::Replacements Result; |
| 27 | + separateTopLevelComment(AnnotatedLines, Result, Tokens); |
| 28 | + return {Result, 0}; |
| 29 | +} |
| 30 | + |
| 31 | +void TopLevelCommentSeparator::separateTopLevelComment( |
| 32 | + SmallVectorImpl<AnnotatedLine *> &Lines, tooling::Replacements &Result, |
| 33 | + FormatTokenLexer &Tokens) { |
| 34 | + unsigned NewlineCount = std::min(Style.MaxEmptyLinesToKeep, |
| 35 | + *Style.EmptyLinesAfterTopLevelComment) + |
| 36 | + 1; |
| 37 | + WhitespaceManager Whitespaces( |
| 38 | + Env.getSourceManager(), Style, |
| 39 | + Style.LineEnding > FormatStyle::LE_CRLF |
| 40 | + ? WhitespaceManager::inputUsesCRLF( |
| 41 | + Env.getSourceManager().getBufferData(Env.getFileID()), |
| 42 | + Style.LineEnding == FormatStyle::LE_DeriveCRLF) |
| 43 | + : Style.LineEnding == FormatStyle::LE_CRLF); |
| 44 | + |
| 45 | + bool InTopLevelComment = false; |
| 46 | + for (unsigned I = 0; I < Lines.size(); ++I) { |
| 47 | + const auto &CurrentLine = Lines[I]; |
| 48 | + if (CurrentLine->isComment()) { |
| 49 | + InTopLevelComment = true; |
| 50 | + } else if (InTopLevelComment) { |
| 51 | + // Do not handle EOF newlines. |
| 52 | + if (!CurrentLine->First->is(tok::eof) && CurrentLine->Affected) { |
| 53 | + Whitespaces.replaceWhitespace(*CurrentLine->First, NewlineCount, |
| 54 | + CurrentLine->First->OriginalColumn, |
| 55 | + CurrentLine->First->OriginalColumn); |
| 56 | + } |
| 57 | + break; |
| 58 | + } |
| 59 | + } |
| 60 | + |
| 61 | + for (const auto &R : Whitespaces.generateReplacements()) { |
| 62 | + // The add method returns an Error instance which simulates program exit |
| 63 | + // code through overloading boolean operator, thus false here indicates |
| 64 | + // success. |
| 65 | + if (Result.add(R)) |
| 66 | + return; |
| 67 | + } |
| 68 | +} |
| 69 | +} // namespace format |
| 70 | +} // namespace clang |
0 commit comments