[Test] Add range-info test driver to swift-ide-test. NFC

This commit is contained in:
Xi Ge
2016-11-15 13:47:32 -08:00
parent 6a9298cd36
commit 5e8d8da380
5 changed files with 209 additions and 78 deletions

View File

@@ -13,6 +13,7 @@
#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/Lexer.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -174,6 +175,25 @@ bool SemaLocResolver::visitModuleReference(ModuleEntity Mod,
return !tryResolve(Mod, Range.getStart());
}
void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
OS << "<Kind>";
switch (Kind) {
case RangeKind::SingleExpression: OS << "SingleExpression"; break;
case RangeKind::SingleDecl: OS << "SingleDecl"; break;
case RangeKind::MultiStatement: OS << "MultiStatement"; break;
case RangeKind::SingleStatement: OS << "SingleStatement"; break;
case RangeKind::Invalid: OS << "Invalid"; break;
}
OS << "</Kind>\n";
OS << "<Content>" << Content << "</Content>\n";
if (Ty) {
OS << "<Type>";
Ty->print(OS);
OS << "</Type>\n";
}
}
struct RangeResolver::Implementation {
SourceFile &File;
private:
@@ -214,9 +234,47 @@ private:
}
}
public:
static SourceLoc getNonwhitespaceLocBefore(SourceManager &SM,
unsigned BufferID,
unsigned Offset) {
CharSourceRange entireRange = SM.getRangeForBuffer(BufferID);
StringRef Buffer = SM.extractText(entireRange);
const char *BufStart = Buffer.data();
if (Offset >= Buffer.size())
return SourceLoc();
for (unsigned Off = Offset; Off != 0; Off --) {
if (!clang::isWhitespace(*(BufStart + Off))) {
return SM.getLocForOffset(BufferID, Off);
}
}
return clang::isWhitespace(*BufStart) ? SourceLoc() :
SM.getLocForOffset(BufferID, 0);
}
static SourceLoc getNonwhitespaceLocAfter(SourceManager &SM,
unsigned BufferID,
unsigned Offset) {
CharSourceRange entireRange = SM.getRangeForBuffer(BufferID);
StringRef Buffer = SM.extractText(entireRange);
const char *BufStart = Buffer.data();
if (Offset >= Buffer.size())
return SourceLoc();
for (unsigned Off = Offset; Off < Buffer.size(); Off ++) {
if (!clang::isWhitespace(*(BufStart + Off))) {
return SM.getLocForOffset(BufferID, Off);
}
}
return SourceLoc();
}
Implementation(SourceFile &File, SourceLoc Start, SourceLoc End) :
File(File), Start(Start), End(End), Content(getContent()) {}
public:
bool hasResult() { return Result.hasValue(); }
void enter(ASTNode Node) { ContextStack.emplace_back(Node); }
void leave(ASTNode Node) {
@@ -224,6 +282,29 @@ public:
ContextStack.pop_back();
}
static Implementation *createInstance(SourceFile &File, unsigned StartOff,
unsigned Length) {
SourceManager &SM = File.getASTContext().SourceMgr;
unsigned BufferId = File.getBufferID().getValue();
SourceLoc StartLoc = Implementation::getNonwhitespaceLocAfter(SM, BufferId,
StartOff);
SourceLoc EndLoc = Implementation::getNonwhitespaceLocBefore(SM, BufferId,
StartOff + Length - 1);
StartLoc = Lexer::getLocForStartOfToken(SM, StartLoc);
EndLoc = Lexer::getLocForStartOfToken(SM, EndLoc);
return StartLoc.isInvalid() || EndLoc.isInvalid() ? nullptr :
new Implementation(File, StartLoc, EndLoc);
}
static Implementation *createInstance(SourceFile &File, SourceLoc Start,
SourceLoc End) {
SourceManager &SM = File.getASTContext().SourceMgr;
unsigned BufferId = File.getBufferID().getValue();
unsigned StartOff = SM.getLocOffsetInBuffer(Start, BufferId);
unsigned EndOff = SM.getLocOffsetInBuffer(End, BufferId);
return createInstance(File, StartOff, EndOff - StartOff);
}
void analyze(ASTNode Node) {
auto &DCInfo = getCurrentDC();
switch (getRangeMatchKind(Node.getSourceRange())) {
@@ -283,53 +364,58 @@ private:
};
RangeResolver::RangeResolver(SourceFile &File, SourceLoc Start, SourceLoc End) :
Impl(*new Implementation(File, Start, End)) {}
Impl(Implementation::createInstance(File, Start, End)) {}
RangeResolver::~RangeResolver() { delete &Impl; }
RangeResolver::RangeResolver(SourceFile &File, unsigned Offset, unsigned Length) :
Impl(Implementation::createInstance(File, Offset, Length)) {}
RangeResolver::~RangeResolver() { if (Impl) delete Impl; }
bool RangeResolver::walkToExprPre(Expr *E) {
if (!Impl.shouldEnter(E))
if (!Impl->shouldEnter(E))
return false;
Impl.analyze(E);
Impl.enter(E);
Impl->analyze(E);
Impl->enter(E);
return true;
}
bool RangeResolver::walkToStmtPre(Stmt *S) {
if (!Impl.shouldEnter(S))
if (!Impl->shouldEnter(S))
return false;
Impl.analyze(S);
Impl.enter(S);
Impl->analyze(S);
Impl->enter(S);
return true;
};
bool RangeResolver::walkToDeclPre(Decl *D, CharSourceRange Range) {
if (!Impl.shouldEnter(D))
if (!Impl->shouldEnter(D))
return false;
Impl.analyze(D);
Impl.enter(D);
Impl->analyze(D);
Impl->enter(D);
return true;
}
bool RangeResolver::walkToExprPost(Expr *E) {
Impl.leave(E);
return !Impl.hasResult();
Impl->leave(E);
return !Impl->hasResult();
}
bool RangeResolver::walkToStmtPost(Stmt *S) {
Impl.leave(S);
return !Impl.hasResult();
Impl->leave(S);
return !Impl->hasResult();
};
bool RangeResolver::walkToDeclPost(Decl *D) {
Impl.leave(D);
return !Impl.hasResult();
Impl->leave(D);
return !Impl->hasResult();
}
ResolvedRangeInfo RangeResolver::resolve() {
Impl.enter(ASTNode());
walk(Impl.File);
return Impl.getResult();
if (!Impl)
return ResolvedRangeInfo();
Impl->enter(ASTNode());
walk(Impl->File);
return Impl->getResult();
}
void swift::ide::getLocationInfoForClangNode(ClangNode ClangNode,