|
13 | 13 | #include "clang/Basic/Module.h"
|
14 | 14 | #include "clang/Index/USRGeneration.h"
|
15 | 15 | #include "clang/Lex/Lexer.h"
|
| 16 | +#include "clang/Basic/CharInfo.h" |
16 | 17 |
|
17 | 18 | #include "llvm/Support/MemoryBuffer.h"
|
18 | 19 |
|
@@ -174,6 +175,25 @@ bool SemaLocResolver::visitModuleReference(ModuleEntity Mod,
|
174 | 175 | return !tryResolve(Mod, Range.getStart());
|
175 | 176 | }
|
176 | 177 |
|
| 178 | +void ResolvedRangeInfo::print(llvm::raw_ostream &OS) { |
| 179 | + OS << "<Kind>"; |
| 180 | + switch (Kind) { |
| 181 | + case RangeKind::SingleExpression: OS << "SingleExpression"; break; |
| 182 | + case RangeKind::SingleDecl: OS << "SingleDecl"; break; |
| 183 | + case RangeKind::MultiStatement: OS << "MultiStatement"; break; |
| 184 | + case RangeKind::SingleStatement: OS << "SingleStatement"; break; |
| 185 | + case RangeKind::Invalid: OS << "Invalid"; break; |
| 186 | + } |
| 187 | + OS << "</Kind>\n"; |
| 188 | + |
| 189 | + OS << "<Content>" << Content << "</Content>\n"; |
| 190 | + if (Ty) { |
| 191 | + OS << "<Type>"; |
| 192 | + Ty->print(OS); |
| 193 | + OS << "</Type>\n"; |
| 194 | + } |
| 195 | +} |
| 196 | + |
177 | 197 | struct RangeResolver::Implementation {
|
178 | 198 | SourceFile &File;
|
179 | 199 | private:
|
@@ -214,16 +234,77 @@ struct RangeResolver::Implementation {
|
214 | 234 | }
|
215 | 235 | }
|
216 | 236 |
|
217 |
| -public: |
| 237 | + static SourceLoc getNonwhitespaceLocBefore(SourceManager &SM, |
| 238 | + unsigned BufferID, |
| 239 | + unsigned Offset) { |
| 240 | + CharSourceRange entireRange = SM.getRangeForBuffer(BufferID); |
| 241 | + StringRef Buffer = SM.extractText(entireRange); |
| 242 | + |
| 243 | + const char *BufStart = Buffer.data(); |
| 244 | + if (Offset >= Buffer.size()) |
| 245 | + return SourceLoc(); |
| 246 | + |
| 247 | + for (unsigned Off = Offset; Off != 0; Off --) { |
| 248 | + if (!clang::isWhitespace(*(BufStart + Off))) { |
| 249 | + return SM.getLocForOffset(BufferID, Off); |
| 250 | + } |
| 251 | + } |
| 252 | + return clang::isWhitespace(*BufStart) ? SourceLoc() : |
| 253 | + SM.getLocForOffset(BufferID, 0); |
| 254 | + } |
| 255 | + |
| 256 | + static SourceLoc getNonwhitespaceLocAfter(SourceManager &SM, |
| 257 | + unsigned BufferID, |
| 258 | + unsigned Offset) { |
| 259 | + CharSourceRange entireRange = SM.getRangeForBuffer(BufferID); |
| 260 | + StringRef Buffer = SM.extractText(entireRange); |
| 261 | + |
| 262 | + const char *BufStart = Buffer.data(); |
| 263 | + if (Offset >= Buffer.size()) |
| 264 | + return SourceLoc(); |
| 265 | + |
| 266 | + for (unsigned Off = Offset; Off < Buffer.size(); Off ++) { |
| 267 | + if (!clang::isWhitespace(*(BufStart + Off))) { |
| 268 | + return SM.getLocForOffset(BufferID, Off); |
| 269 | + } |
| 270 | + } |
| 271 | + return SourceLoc(); |
| 272 | + } |
| 273 | + |
218 | 274 | Implementation(SourceFile &File, SourceLoc Start, SourceLoc End) :
|
219 | 275 | File(File), Start(Start), End(End), Content(getContent()) {}
|
| 276 | + |
| 277 | +public: |
220 | 278 | bool hasResult() { return Result.hasValue(); }
|
221 | 279 | void enter(ASTNode Node) { ContextStack.emplace_back(Node); }
|
222 | 280 | void leave(ASTNode Node) {
|
223 | 281 | assert(ContextStack.back().Parent.getOpaqueValue() == Node.getOpaqueValue());
|
224 | 282 | ContextStack.pop_back();
|
225 | 283 | }
|
226 | 284 |
|
| 285 | + static Implementation *createInstance(SourceFile &File, unsigned StartOff, |
| 286 | + unsigned Length) { |
| 287 | + SourceManager &SM = File.getASTContext().SourceMgr; |
| 288 | + unsigned BufferId = File.getBufferID().getValue(); |
| 289 | + SourceLoc StartLoc = Implementation::getNonwhitespaceLocAfter(SM, BufferId, |
| 290 | + StartOff); |
| 291 | + SourceLoc EndLoc = Implementation::getNonwhitespaceLocBefore(SM, BufferId, |
| 292 | + StartOff + Length - 1); |
| 293 | + StartLoc = Lexer::getLocForStartOfToken(SM, StartLoc); |
| 294 | + EndLoc = Lexer::getLocForStartOfToken(SM, EndLoc); |
| 295 | + return StartLoc.isInvalid() || EndLoc.isInvalid() ? nullptr : |
| 296 | + new Implementation(File, StartLoc, EndLoc); |
| 297 | + } |
| 298 | + |
| 299 | + static Implementation *createInstance(SourceFile &File, SourceLoc Start, |
| 300 | + SourceLoc End) { |
| 301 | + SourceManager &SM = File.getASTContext().SourceMgr; |
| 302 | + unsigned BufferId = File.getBufferID().getValue(); |
| 303 | + unsigned StartOff = SM.getLocOffsetInBuffer(Start, BufferId); |
| 304 | + unsigned EndOff = SM.getLocOffsetInBuffer(End, BufferId); |
| 305 | + return createInstance(File, StartOff, EndOff - StartOff); |
| 306 | + } |
| 307 | + |
227 | 308 | void analyze(ASTNode Node) {
|
228 | 309 | auto &DCInfo = getCurrentDC();
|
229 | 310 | switch (getRangeMatchKind(Node.getSourceRange())) {
|
@@ -283,53 +364,58 @@ struct RangeResolver::Implementation {
|
283 | 364 | };
|
284 | 365 |
|
285 | 366 | RangeResolver::RangeResolver(SourceFile &File, SourceLoc Start, SourceLoc End) :
|
286 |
| - Impl(*new Implementation(File, Start, End)) {} |
| 367 | + Impl(Implementation::createInstance(File, Start, End)) {} |
| 368 | + |
| 369 | +RangeResolver::RangeResolver(SourceFile &File, unsigned Offset, unsigned Length) : |
| 370 | + Impl(Implementation::createInstance(File, Offset, Length)) {} |
287 | 371 |
|
288 |
| -RangeResolver::~RangeResolver() { delete &Impl; } |
| 372 | +RangeResolver::~RangeResolver() { if (Impl) delete Impl; } |
289 | 373 |
|
290 | 374 | bool RangeResolver::walkToExprPre(Expr *E) {
|
291 |
| - if (!Impl.shouldEnter(E)) |
| 375 | + if (!Impl->shouldEnter(E)) |
292 | 376 | return false;
|
293 |
| - Impl.analyze(E); |
294 |
| - Impl.enter(E); |
| 377 | + Impl->analyze(E); |
| 378 | + Impl->enter(E); |
295 | 379 | return true;
|
296 | 380 | }
|
297 | 381 |
|
298 | 382 | bool RangeResolver::walkToStmtPre(Stmt *S) {
|
299 |
| - if (!Impl.shouldEnter(S)) |
| 383 | + if (!Impl->shouldEnter(S)) |
300 | 384 | return false;
|
301 |
| - Impl.analyze(S); |
302 |
| - Impl.enter(S); |
| 385 | + Impl->analyze(S); |
| 386 | + Impl->enter(S); |
303 | 387 | return true;
|
304 | 388 | };
|
305 | 389 |
|
306 | 390 | bool RangeResolver::walkToDeclPre(Decl *D, CharSourceRange Range) {
|
307 |
| - if (!Impl.shouldEnter(D)) |
| 391 | + if (!Impl->shouldEnter(D)) |
308 | 392 | return false;
|
309 |
| - Impl.analyze(D); |
310 |
| - Impl.enter(D); |
| 393 | + Impl->analyze(D); |
| 394 | + Impl->enter(D); |
311 | 395 | return true;
|
312 | 396 | }
|
313 | 397 |
|
314 | 398 | bool RangeResolver::walkToExprPost(Expr *E) {
|
315 |
| - Impl.leave(E); |
316 |
| - return !Impl.hasResult(); |
| 399 | + Impl->leave(E); |
| 400 | + return !Impl->hasResult(); |
317 | 401 | }
|
318 | 402 |
|
319 | 403 | bool RangeResolver::walkToStmtPost(Stmt *S) {
|
320 |
| - Impl.leave(S); |
321 |
| - return !Impl.hasResult(); |
| 404 | + Impl->leave(S); |
| 405 | + return !Impl->hasResult(); |
322 | 406 | };
|
323 | 407 |
|
324 | 408 | bool RangeResolver::walkToDeclPost(Decl *D) {
|
325 |
| - Impl.leave(D); |
326 |
| - return !Impl.hasResult(); |
| 409 | + Impl->leave(D); |
| 410 | + return !Impl->hasResult(); |
327 | 411 | }
|
328 | 412 |
|
329 | 413 | ResolvedRangeInfo RangeResolver::resolve() {
|
330 |
| - Impl.enter(ASTNode()); |
331 |
| - walk(Impl.File); |
332 |
| - return Impl.getResult(); |
| 414 | + if (!Impl) |
| 415 | + return ResolvedRangeInfo(); |
| 416 | + Impl->enter(ASTNode()); |
| 417 | + walk(Impl->File); |
| 418 | + return Impl->getResult(); |
333 | 419 | }
|
334 | 420 |
|
335 | 421 | void swift::ide::getLocationInfoForClangNode(ClangNode ClangNode,
|
|
0 commit comments