blob: 577eccfe23b3cb03eb0cf62d07b5fa552884c600 [file] [log] [blame]
Guillaume Papin64feb392013-08-27 14:50:26 +00001//===-- Core/IncludeDirectives.h - Include directives handling --*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file declares the IncludeDirectives class that helps with
12/// detecting and modifying \#include directives.
13///
14//===----------------------------------------------------------------------===//
15
Chandler Carruth35c03612013-09-04 19:13:50 +000016#ifndef CLANG_MODERNIZE_INCLUDE_DIRECTIVES_H
17#define CLANG_MODERNIZE_INCLUDE_DIRECTIVES_H
Guillaume Papin64feb392013-08-27 14:50:26 +000018
19#include "clang/Basic/SourceLocation.h"
20#include "clang/Tooling/Refactoring.h"
21#include "llvm/ADT/DenseMap.h"
Guillaume Papin64feb392013-08-27 14:50:26 +000022#include "llvm/ADT/SmallPtrSet.h"
Chandler Carruth85e6e872014-01-07 20:05:01 +000023#include "llvm/ADT/StringRef.h"
Guillaume Papin64feb392013-08-27 14:50:26 +000024#include <vector>
25
26namespace clang {
27class Preprocessor;
28} // namespace clang
29
30/// \brief Support for include directives handling.
31///
32/// This class should be created with a \c clang::CompilerInstance before the
33/// file is preprocessed in order to collect the inclusion information. It can
34/// be queried as long as the compiler instance is valid.
35class IncludeDirectives {
36public:
37 IncludeDirectives(clang::CompilerInstance &CI);
38
39 /// \brief Add an angled include to a the given file.
40 ///
41 /// \param File A file accessible by a SourceManager
42 /// \param Include The include file as it should be written in the code.
43 ///
NAKAMURA Takumie677e2f2015-09-19 02:21:28 +000044 /// \returns \parblock
Guillaume Papin64feb392013-08-27 14:50:26 +000045 /// \li A null Replacement (check using \c Replacement::isApplicable()), if
46 /// the \c Include is already visible from \c File.
47 /// \li Otherwise, a non-null Replacement that, when applied, inserts an
48 /// \c \#include into \c File.
49 clang::tooling::Replacement addAngledInclude(llvm::StringRef File,
50 llvm::StringRef Include);
51 clang::tooling::Replacement addAngledInclude(const clang::FileEntry *File,
52 llvm::StringRef Include);
53
54 /// \brief Check if \p Include is included by \p File or any of the files
55 /// \p File includes.
56 bool hasInclude(const clang::FileEntry *File, llvm::StringRef Include) const;
57
58private:
59 friend class IncludeDirectivesPPCallback;
60
61 /// \brief Contains information about an inclusion.
62 class Entry {
63 public:
64 Entry(clang::SourceLocation HashLoc, const clang::FileEntry *IncludedFile,
65 bool Angled)
66 : HashLoc(HashLoc), IncludedFile(IncludedFile), Angled(Angled) {}
67
68 /// \brief The location of the '#'.
69 clang::SourceLocation getHashLocation() const { return HashLoc; }
70
71 /// \brief The file included by this include directive.
72 const clang::FileEntry *getIncludedFile() const { return IncludedFile; }
73
74 /// \brief \c true if the include use angle brackets, \c false otherwise
75 /// when using of quotes.
76 bool isAngled() const { return Angled; }
77
78 private:
79 clang::SourceLocation HashLoc;
80 const clang::FileEntry *IncludedFile;
81 bool Angled;
82 };
83
84 // A list of entries.
85 typedef std::vector<Entry> EntryVec;
86
87 // A list of source locations.
88 typedef std::vector<clang::SourceLocation> LocationVec;
89
90 // Associates files to their includes.
91 typedef llvm::DenseMap<const clang::FileEntry *, EntryVec> FileToEntriesMap;
92
93 // Associates headers to their include guards if any. The location is the
94 // location of the hash from the #define.
95 typedef llvm::DenseMap<const clang::FileEntry *, clang::SourceLocation>
96 HeaderToGuardMap;
97
98 /// \brief Type used by \c lookForInclude() to keep track of the files that
99 /// have already been processed.
100 typedef llvm::SmallPtrSet<const clang::FileEntry *, 32> SeenFilesSet;
101
102 /// \brief Recursively look if an include is included by \p File or any of the
103 /// headers \p File includes.
104 ///
105 /// \param File The file where to start the search.
106 /// \param IncludeLocs These are the hash locations of the \#include
107 /// directives we are looking for.
108 /// \param Seen Used to avoid visiting a same file more than once during the
109 /// recursion.
110 bool lookForInclude(const clang::FileEntry *File,
111 const LocationVec &IncludeLocs, SeenFilesSet &Seen) const;
112
113 /// \brief Find the end of a file header and returns a pair (FileOffset,
114 /// NewLineFlags).
115 ///
116 /// Source files often contain a file header (copyright, license, explanation
Alp Toker9a5134e2013-12-01 05:08:12 +0000117 /// of the file content). An \#include should preferably be put after this.
Guillaume Papin64feb392013-08-27 14:50:26 +0000118 std::pair<unsigned, unsigned>
119 findFileHeaderEndOffset(clang::FileID FID) const;
120
121 /// \brief Finds the offset where an angled include should be added and
122 /// returns a pair (FileOffset, NewLineFlags).
123 std::pair<unsigned, unsigned>
124 angledIncludeInsertionOffset(clang::FileID FID) const;
125
126 /// \brief Find the location of an include directive that can be used to
127 /// insert an inclusion after.
128 ///
129 /// If no such include exists returns a null SourceLocation.
130 clang::SourceLocation angledIncludeHintLoc(clang::FileID FID) const;
131
132 clang::CompilerInstance &CI;
133 clang::SourceManager &Sources;
134 FileToEntriesMap FileToEntries;
135 // maps include filename as written in the source code to the source locations
136 // where it appears
137 llvm::StringMap<LocationVec> IncludeAsWrittenToLocationsMap;
138 HeaderToGuardMap HeaderToGuard;
139};
140
Chandler Carruth35c03612013-09-04 19:13:50 +0000141#endif // CLANG_MODERNIZE_INCLUDE_DIRECTIVES_H