http://llvm-reviews.chandlerc.com/D72

Files:
  unittests/AST/CMakeLists.txt
  unittests/AST/SourceLocationTest.cpp
Index: unittests/AST/CMakeLists.txt
===================================================================
--- unittests/AST/CMakeLists.txt
+++ unittests/AST/CMakeLists.txt
@@ -2,6 +2,7 @@
   CommentLexer.cpp
   CommentParser.cpp
   DeclPrinterTest.cpp
+  SourceLocationTest.cpp
   StmtPrinterTest.cpp
   )
 
Index: unittests/AST/SourceLocationTest.cpp
===================================================================
--- /dev/null
+++ unittests/AST/SourceLocationTest.cpp
@@ -0,0 +1,198 @@
+//===- unittest/AST/SourceLocationTest.cpp - AST source loc unit tests ----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using clang::tooling::newFrontendActionFactory;
+using clang::tooling::runToolOnCodeWithArgs;
+using clang::tooling::FrontendActionFactory;
+
+/// \brief Base class for verifying some property of nodes found by a matcher.
+class MatchVerifier : public MatchFinder::MatchCallback {
+public:
+  MatchVerifier() : Verified(false), VerifyResult("Could not find match") {}
+
+  virtual void run(const MatchFinder::MatchResult &Result) {
+    Verified = verify(Result);
+  }
+
+  virtual bool verify(const MatchFinder::MatchResult &Result) = 0;
+
+  void setResult(const Twine &Result) {
+    VerifyResult = Result.str();
+  }
+
+  testing::AssertionResult getResult() {
+    if (Verified)
+      return testing::AssertionSuccess();
+    return testing::AssertionFailure() << VerifyResult;
+  }
+
+private:
+  bool Verified;
+  std::string VerifyResult;
+};
+
+enum Language { Lang_C, Lang_CXX };
+
+/// \brief Runs a matcher over some code, and returns the result of the
+/// verifier for the matched node.
+template <typename T>
+testing::AssertionResult match(const std::string &Code,
+                               const T &AMatcher,
+                               MatchVerifier &Verifier,
+                               Language L = Lang_CXX) {
+  MatchFinder Finder;
+  Finder.addMatcher(AMatcher, &Verifier);
+  OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));
+  std::vector<std::string> Args;
+  StringRef FileName;
+  switch (L) {
+  case Lang_C:
+    Args.push_back("-std=c99");
+    FileName = "input.c";
+    break;
+  case Lang_CXX:
+    Args.push_back("-std=c++98");
+    FileName = "input.cc";
+    break;
+  }
+  if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName))
+    return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
+  return Verifier.getResult();
+}
+
+/// \brief Base class for verifying some property of the node with the
+/// given Id that is found by a matcher.
+template <typename T>
+class NodeVerifier : public MatchVerifier {
+public:
+  NodeVerifier<T> &expectId(StringRef Id) {
+    ExpectId = Id;
+    return *this;
+  }
+
+  virtual bool verify(const MatchFinder::MatchResult &Result) {
+    const T *Node = Result.Nodes.getNodeAs<T>(ExpectId);
+    if (!Node) {
+      this->setResult("Could not find node with id \"" + ExpectId + "\"");
+      return false;
+    }
+    return verifyNode(Result, *Node);
+  }
+
+  virtual bool verifyNode(const MatchFinder::MatchResult &Result,
+                          const T &Node) = 0;
+
+protected:
+  std::string ExpectId;
+};
+
+/// \brief Verify whether a node has the correct source location.
+///
+/// By default, Node.getSourceLocation() is checked. This can be changed
+/// by overriding getLocation().
+template <typename T>
+class LocationVerifier : public NodeVerifier<T> {
+public:
+  LocationVerifier<T> &expectLocation(unsigned Line, unsigned Column) {
+    ExpectLine = Line;
+    ExpectColumn = Column;
+    return *this;
+  }
+
+  bool verifyNode(const MatchFinder::MatchResult &Result, const T &Node) {
+    SourceLocation Loc = getLocation(Node);
+    FullSourceLoc FullLoc = Result.Context->getFullLoc(Loc);
+    unsigned Line = FullLoc.getSpellingLineNumber();
+    unsigned Column = FullLoc.getSpellingColumnNumber();
+    if (Line != ExpectLine || Column != ExpectColumn) {
+      this->setResult(
+          "Expected location <" +
+          Twine(ExpectLine) + ":" + Twine(ExpectColumn) + ">, found <" +
+          Twine(Line) + ":" + Twine(Column) + ">");
+      return false;
+    }
+    return true;
+  }
+
+  virtual SourceLocation getLocation(const T &Node) {
+    return Node.getLocation();
+  }
+
+private:
+  unsigned ExpectLine, ExpectColumn;
+};
+
+/// \brief Verify whether a node has the correct source range.
+///
+/// By default, Node.getSourceRange() is checked. This can be changed
+/// by overriding getRange().
+template <typename T>
+class RangeVerifier : public NodeVerifier<T> {
+public:
+  RangeVerifier<T> &expectRange(unsigned BeginLine, unsigned BeginColumn,
+                                unsigned EndLine, unsigned EndColumn) {
+    ExpectBeginLine = BeginLine;
+    ExpectBeginColumn = BeginColumn;
+    ExpectEndLine = EndLine;
+    ExpectEndColumn = EndColumn;
+    return *this;
+  }
+
+  bool verifyNode(const MatchFinder::MatchResult &Result, const T &Node) {
+    SourceRange R = getRange(Node);
+    FullSourceLoc Begin = Result.Context->getFullLoc(R.getBegin());
+    FullSourceLoc End = Result.Context->getFullLoc(R.getEnd());
+    unsigned BeginLine = Begin.getSpellingLineNumber();
+    unsigned BeginColumn = Begin.getSpellingColumnNumber();
+    unsigned EndLine = End.getSpellingLineNumber();
+    unsigned EndColumn = End.getSpellingColumnNumber();
+    if (BeginLine != ExpectBeginLine || BeginColumn != ExpectBeginColumn ||
+        EndLine != ExpectEndLine || EndColumn != ExpectEndColumn) {
+      this->setResult(
+          "Expected range <" +
+          Twine(ExpectBeginLine) + ":" + Twine(ExpectBeginColumn) + ", " +
+          Twine(ExpectEndLine) + ":" + Twine(ExpectEndColumn) + ">, found <" +
+          Twine(BeginLine) + ":" + Twine(BeginColumn) + ", " +
+          Twine(EndLine) + ":" + Twine(EndColumn) + ">");
+      return false;
+    }
+    return true;
+  }
+
+  virtual SourceRange getRange(const T &Node) {
+    return Node.getSourceRange();
+  }
+
+private:
+  unsigned ExpectBeginLine, ExpectBeginColumn, ExpectEndLine, ExpectEndColumn;
+};
+
+TEST(SourceLocation, KNRParamLocation) {
+  LocationVerifier<ParmVarDecl> Verifier;
+  Verifier.expectLocation(1, 8).expectId("i");
+  EXPECT_TRUE(match("void f(i) {}", varDecl().bind("i"), Verifier, Lang_C));
+}
+
+TEST(SourceLocation, KNRParamRange) {
+  RangeVerifier<ParmVarDecl> Verifier;
+  Verifier.expectRange(1, 8, 1, 8).expectId("i");
+  EXPECT_TRUE(match("void f(i) {}", varDecl().bind("i"), Verifier, Lang_C));
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to