forked from OSchip/llvm-project
142 lines
5.3 KiB
C++
142 lines
5.3 KiB
C++
//===-- Core/IncludeDirectives.h - Include directives handling --*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// \brief This file declares the IncludeDirectives class that helps with
|
|
/// detecting and modifying \#include directives.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef CLANG_MODERNIZE_INCLUDE_DIRECTIVES_H
|
|
#define CLANG_MODERNIZE_INCLUDE_DIRECTIVES_H
|
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
#include "clang/Tooling/Refactoring.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include <vector>
|
|
|
|
namespace clang {
|
|
class Preprocessor;
|
|
} // namespace clang
|
|
|
|
/// \brief Support for include directives handling.
|
|
///
|
|
/// This class should be created with a \c clang::CompilerInstance before the
|
|
/// file is preprocessed in order to collect the inclusion information. It can
|
|
/// be queried as long as the compiler instance is valid.
|
|
class IncludeDirectives {
|
|
public:
|
|
IncludeDirectives(clang::CompilerInstance &CI);
|
|
|
|
/// \brief Add an angled include to a the given file.
|
|
///
|
|
/// \param File A file accessible by a SourceManager
|
|
/// \param Include The include file as it should be written in the code.
|
|
///
|
|
/// \returns \parblock
|
|
/// \li A null Replacement (check using \c Replacement::isApplicable()), if
|
|
/// the \c Include is already visible from \c File.
|
|
/// \li Otherwise, a non-null Replacement that, when applied, inserts an
|
|
/// \c \#include into \c File.
|
|
clang::tooling::Replacement addAngledInclude(llvm::StringRef File,
|
|
llvm::StringRef Include);
|
|
clang::tooling::Replacement addAngledInclude(const clang::FileEntry *File,
|
|
llvm::StringRef Include);
|
|
|
|
/// \brief Check if \p Include is included by \p File or any of the files
|
|
/// \p File includes.
|
|
bool hasInclude(const clang::FileEntry *File, llvm::StringRef Include) const;
|
|
|
|
private:
|
|
friend class IncludeDirectivesPPCallback;
|
|
|
|
/// \brief Contains information about an inclusion.
|
|
class Entry {
|
|
public:
|
|
Entry(clang::SourceLocation HashLoc, const clang::FileEntry *IncludedFile,
|
|
bool Angled)
|
|
: HashLoc(HashLoc), IncludedFile(IncludedFile), Angled(Angled) {}
|
|
|
|
/// \brief The location of the '#'.
|
|
clang::SourceLocation getHashLocation() const { return HashLoc; }
|
|
|
|
/// \brief The file included by this include directive.
|
|
const clang::FileEntry *getIncludedFile() const { return IncludedFile; }
|
|
|
|
/// \brief \c true if the include use angle brackets, \c false otherwise
|
|
/// when using of quotes.
|
|
bool isAngled() const { return Angled; }
|
|
|
|
private:
|
|
clang::SourceLocation HashLoc;
|
|
const clang::FileEntry *IncludedFile;
|
|
bool Angled;
|
|
};
|
|
|
|
// A list of entries.
|
|
typedef std::vector<Entry> EntryVec;
|
|
|
|
// A list of source locations.
|
|
typedef std::vector<clang::SourceLocation> LocationVec;
|
|
|
|
// Associates files to their includes.
|
|
typedef llvm::DenseMap<const clang::FileEntry *, EntryVec> FileToEntriesMap;
|
|
|
|
// Associates headers to their include guards if any. The location is the
|
|
// location of the hash from the #define.
|
|
typedef llvm::DenseMap<const clang::FileEntry *, clang::SourceLocation>
|
|
HeaderToGuardMap;
|
|
|
|
/// \brief Type used by \c lookForInclude() to keep track of the files that
|
|
/// have already been processed.
|
|
typedef llvm::SmallPtrSet<const clang::FileEntry *, 32> SeenFilesSet;
|
|
|
|
/// \brief Recursively look if an include is included by \p File or any of the
|
|
/// headers \p File includes.
|
|
///
|
|
/// \param File The file where to start the search.
|
|
/// \param IncludeLocs These are the hash locations of the \#include
|
|
/// directives we are looking for.
|
|
/// \param Seen Used to avoid visiting a same file more than once during the
|
|
/// recursion.
|
|
bool lookForInclude(const clang::FileEntry *File,
|
|
const LocationVec &IncludeLocs, SeenFilesSet &Seen) const;
|
|
|
|
/// \brief Find the end of a file header and returns a pair (FileOffset,
|
|
/// NewLineFlags).
|
|
///
|
|
/// Source files often contain a file header (copyright, license, explanation
|
|
/// of the file content). An \#include should preferably be put after this.
|
|
std::pair<unsigned, unsigned>
|
|
findFileHeaderEndOffset(clang::FileID FID) const;
|
|
|
|
/// \brief Finds the offset where an angled include should be added and
|
|
/// returns a pair (FileOffset, NewLineFlags).
|
|
std::pair<unsigned, unsigned>
|
|
angledIncludeInsertionOffset(clang::FileID FID) const;
|
|
|
|
/// \brief Find the location of an include directive that can be used to
|
|
/// insert an inclusion after.
|
|
///
|
|
/// If no such include exists returns a null SourceLocation.
|
|
clang::SourceLocation angledIncludeHintLoc(clang::FileID FID) const;
|
|
|
|
clang::CompilerInstance &CI;
|
|
clang::SourceManager &Sources;
|
|
FileToEntriesMap FileToEntries;
|
|
// maps include filename as written in the source code to the source locations
|
|
// where it appears
|
|
llvm::StringMap<LocationVec> IncludeAsWrittenToLocationsMap;
|
|
HeaderToGuardMap HeaderToGuard;
|
|
};
|
|
|
|
#endif // CLANG_MODERNIZE_INCLUDE_DIRECTIVES_H
|