brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · 20a3fc2 Raw
119 lines · c
1//===--- CollectMacros.h -----------------------------------------*- 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTMACROS_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTMACROS_H11 12#include "Protocol.h"13#include "SourceCode.h"14#include "index/SymbolID.h"15#include "clang/Basic/SourceLocation.h"16#include "clang/Lex/PPCallbacks.h"17#include "clang/Lex/Preprocessor.h"18#include "llvm/ADT/DenseMap.h"19#include <cstddef>20#include <string>21 22namespace clang {23namespace clangd {24 25struct MacroOccurrence {26  // Half-open range (end offset is exclusive) inside the main file.27  size_t StartOffset;28  size_t EndOffset;29 30  bool IsDefinition;31  // True if the occurence is used in a conditional directive, e.g. #ifdef MACRO32  bool InConditionalDirective;33 34  CharSourceRange toSourceRange(const SourceManager &SM) const;35  Range toRange(const SourceManager &SM) const;36};37 38struct MainFileMacros {39  llvm::StringSet<> Names;40  llvm::DenseMap<SymbolID, std::vector<MacroOccurrence>> MacroRefs;41  // Somtimes it is not possible to compute the SymbolID for the Macro, e.g. a42  // reference to an undefined macro. Store them separately, e.g. for semantic43  // highlighting.44  std::vector<MacroOccurrence> UnknownMacros;45  // Ranges skipped by the preprocessor due to being inactive.46  std::vector<Range> SkippedRanges;47};48 49/// Collects macro references (e.g. definitions, expansions) in the main file.50/// It is used to:51///  - collect macros in the preamble section of the main file (in Preamble.cpp)52///  - collect macros after the preamble of the main file (in ParsedAST.cpp)53class CollectMainFileMacros : public PPCallbacks {54public:55  explicit CollectMainFileMacros(const Preprocessor &PP, MainFileMacros &Out)56      : SM(PP.getSourceManager()), PP(PP), Out(Out) {}57 58  void FileChanged(SourceLocation Loc, FileChangeReason,59                   SrcMgr::CharacteristicKind, FileID) override;60 61  void MacroDefined(const Token &MacroName, const MacroDirective *MD) override;62 63  void MacroExpands(const Token &MacroName, const MacroDefinition &MD,64                    SourceRange Range, const MacroArgs *Args) override;65 66  void MacroUndefined(const clang::Token &MacroName,67                      const clang::MacroDefinition &MD,68                      const clang::MacroDirective *Undef) override;69 70  void Ifdef(SourceLocation Loc, const Token &MacroName,71             const MacroDefinition &MD) override;72  void Ifndef(SourceLocation Loc, const Token &MacroName,73              const MacroDefinition &MD) override;74  using PPCallbacks::Elifdef;75  using PPCallbacks::Elifndef;76  void Elifdef(SourceLocation Loc, const Token &MacroNameTok,77               const MacroDefinition &MD) override;78  void Elifndef(SourceLocation Loc, const Token &MacroNameTok,79                const MacroDefinition &MD) override;80 81  void Defined(const Token &MacroName, const MacroDefinition &MD,82               SourceRange Range) override;83 84  void SourceRangeSkipped(SourceRange R, SourceLocation EndifLoc) override;85 86  // Called when the AST build is done to disable further recording87  // of macros by this class. This is needed because some clang-tidy88  // checks can trigger PP callbacks by calling directly into the89  // preprocessor. Such calls are not interleaved with FileChanged()90  // in the expected way, leading this class to erroneously process91  // macros that are not in the main file.92  void doneParse() { InMainFile = false; }93 94private:95  void add(const Token &MacroNameTok, const MacroInfo *MI,96           bool IsDefinition = false, bool InConditionalDirective = false);97  const SourceManager &SM;98  const Preprocessor &PP;99  bool InMainFile = true;100  MainFileMacros &Out;101};102 103/// Represents a `#pragma mark` in the main file.104///105/// There can be at most one pragma mark per line.106struct PragmaMark {107  Range Rng;108  std::string Trivia;109};110 111/// Collect all pragma marks from the main file.112std::unique_ptr<PPCallbacks>113collectPragmaMarksCallback(const SourceManager &, std::vector<PragmaMark> &Out);114 115} // namespace clangd116} // namespace clang117 118#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTMACROS_H119