-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
SourceManager.h
239 lines (194 loc) · 8.22 KB
/
SourceManager.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
//===--- SourceManager.h - Manager for Source Buffers -----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_BASIC_SOURCEMANAGER_H
#define SWIFT_BASIC_SOURCEMANAGER_H
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/SourceMgr.h"
#include <map>
namespace swift {
/// \brief This class manages and owns source buffers.
class SourceManager {
llvm::SourceMgr LLVMSourceMgr;
unsigned CodeCompletionBufferID = 0U;
unsigned CodeCompletionOffset;
/// \brief The buffer ID where a hashbang line #! is allowed.
unsigned HashbangBufferID = 0U;
/// Associates buffer identifiers to buffer IDs.
llvm::StringMap<unsigned> BufIdentIDMap;
// #line directive handling.
struct VirtualFile {
CharSourceRange Range;
std::string Name;
int LineOffset;
};
std::map<const char *, VirtualFile> VirtualFiles;
mutable std::pair<const char *, const VirtualFile*> CachedVFile = {nullptr, nullptr};
public:
llvm::SourceMgr &getLLVMSourceMgr() {
return LLVMSourceMgr;
}
const llvm::SourceMgr &getLLVMSourceMgr() const {
return LLVMSourceMgr;
}
void setCodeCompletionPoint(unsigned BufferID, unsigned Offset) {
assert(BufferID != 0U && "Buffer should be valid");
CodeCompletionBufferID = BufferID;
CodeCompletionOffset = Offset;
}
unsigned getCodeCompletionBufferID() const {
return CodeCompletionBufferID;
}
unsigned getCodeCompletionOffset() const {
return CodeCompletionOffset;
}
SourceLoc getCodeCompletionLoc() const;
void setHashbangBufferID(unsigned BufferID) {
assert(HashbangBufferID == 0U && "Hashbang buffer ID already set");
HashbangBufferID = BufferID;
}
unsigned getHashbangBufferID() const {
return HashbangBufferID;
}
/// Returns true if \c LHS is before \c RHS in the source buffer.
bool isBeforeInBuffer(SourceLoc LHS, SourceLoc RHS) const {
return LHS.Value.getPointer() < RHS.Value.getPointer();
}
/// Returns true if range \c R contains the location \c Loc. The location
/// \c Loc should point at the beginning of the token.
bool rangeContainsTokenLoc(SourceRange R, SourceLoc Loc) const {
return Loc == R.Start || Loc == R.End ||
(isBeforeInBuffer(R.Start, Loc) && isBeforeInBuffer(Loc, R.End));
}
/// Returns true if range \c Enclosing contains the range \c Inner.
bool rangeContains(SourceRange Enclosing, SourceRange Inner) const {
return rangeContainsTokenLoc(Enclosing, Inner.Start) &&
rangeContainsTokenLoc(Enclosing, Inner.End);
}
/// Returns the buffer ID for the specified *valid* location.
///
/// Because a valid source location always corresponds to a source buffer,
/// this routine always returns a valid buffer ID.
unsigned findBufferContainingLoc(SourceLoc Loc) const;
/// Adds a memory buffer to the SourceManager, taking ownership of it.
unsigned addNewSourceBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer);
/// Add a #line-defined virtual file region.
///
/// By default, this region continues to the end of the buffer.
///
/// \returns True if the new file was added, false if the file already exists.
/// The name and line offset must match exactly in that case.
///
/// \sa closeVirtualFile.
bool openVirtualFile(SourceLoc loc, StringRef name, int lineOffset);
/// Close a #line-defined virtual file region.
void closeVirtualFile(SourceLoc end);
/// Creates a copy of a \c MemoryBuffer and adds it to the \c SourceManager,
/// taking ownership of the copy.
unsigned addMemBufferCopy(llvm::MemoryBuffer *Buffer);
/// Creates and adds a memory buffer to the \c SourceManager, taking
/// ownership of the newly created copy.
///
/// \p InputData and \p BufIdentifier are copied, so that this memory can go
/// away as soon as this function returns.
unsigned addMemBufferCopy(StringRef InputData, StringRef BufIdentifier = "");
/// Returns a buffer ID for a previously added buffer with the given
/// buffer identifier, or None if there is no such buffer.
Optional<unsigned> getIDForBufferIdentifier(StringRef BufIdentifier);
/// Returns the identifier for the buffer with the given ID.
///
/// \p BufferID must be a valid buffer ID.
StringRef getIdentifierForBuffer(unsigned BufferID) const;
/// \brief Returns a SourceRange covering the entire specified buffer.
///
/// Note that the start location might not point at the first token: it
/// might point at whitespace or a comment.
CharSourceRange getRangeForBuffer(unsigned BufferID) const;
/// Returns the SourceLoc for the beginning of the specified buffer
/// (at offset zero).
///
/// Note that the resulting location might not point at the first token: it
/// might point at whitespace or a comment.
SourceLoc getLocForBufferStart(unsigned BufferID) const {
return getRangeForBuffer(BufferID).getStart();
}
/// \brief Returns the offset in bytes for the given valid source location.
unsigned getLocOffsetInBuffer(SourceLoc Loc, unsigned BufferID) const;
/// \brief Returns the distance in bytes between the given valid source
/// locations.
unsigned getByteDistance(SourceLoc Start, SourceLoc End) const;
/// Returns the SourceLoc for the byte offset in the specified buffer.
SourceLoc getLocForOffset(unsigned BufferID, unsigned Offset) const {
return getLocForBufferStart(BufferID).getAdvancedLoc(Offset);
}
/// Returns the identifier string for the buffer containing the given source
/// location.
///
/// This respects #line directives.
StringRef getBufferIdentifierForLoc(SourceLoc Loc) const {
if (auto VFile = getVirtualFile(Loc))
return VFile->Name;
else
return getIdentifierForBuffer(findBufferContainingLoc(Loc));
}
/// Returns the line and column represented by the given source location.
///
/// If \p BufferID is provided, \p Loc must come from that source buffer.
///
/// This respects #line directives.
std::pair<unsigned, unsigned>
getLineAndColumn(SourceLoc Loc, unsigned BufferID = 0) const {
assert(Loc.isValid());
int LineOffset = getLineOffset(Loc);
int l, c;
std::tie(l, c) = LLVMSourceMgr.getLineAndColumn(Loc.Value, BufferID);
assert(LineOffset+l > 0 && "bogus line offset");
return { LineOffset + l, c };
}
/// Returns the real line number for a source location.
///
/// If \p BufferID is provided, \p Loc must come from that source buffer.
///
/// This does not respect #line directives.
unsigned getLineNumber(SourceLoc Loc, unsigned BufferID = 0) const {
assert(Loc.isValid());
return LLVMSourceMgr.FindLineNumber(Loc.Value, BufferID);
}
StringRef getEntireTextForBuffer(unsigned BufferID) const;
StringRef extractText(CharSourceRange Range,
Optional<unsigned> BufferID = None) const;
llvm::SMDiagnostic GetMessage(SourceLoc Loc, llvm::SourceMgr::DiagKind Kind,
const Twine &Msg,
ArrayRef<llvm::SMRange> Ranges,
ArrayRef<llvm::SMFixIt> FixIts) const;
/// Verifies that all buffers are still valid.
void verifyAllBuffers() const;
/// Translate line and column pair to the offset.
llvm::Optional<unsigned> resolveFromLineCol(unsigned BufferId, unsigned Line,
unsigned Col) const;
SourceLoc getLocForLineCol(unsigned BufferId, unsigned Line, unsigned Col) const {
auto Offset = resolveFromLineCol(BufferId, Line, Col);
return Offset.hasValue() ? getLocForOffset(BufferId, Offset.getValue()) :
SourceLoc();
}
private:
const VirtualFile *getVirtualFile(SourceLoc Loc) const;
int getLineOffset(SourceLoc Loc) const {
if (auto VFile = getVirtualFile(Loc))
return VFile->LineOffset;
else
return 0;
}
};
} // end namespace swift
#endif // SWIFT_BASIC_SOURCEMANAGER_H