Commit c7832581 authored by Yitzhak Mandelbaum's avatar Yitzhak Mandelbaum
Browse files

[clang][tooling] Fix `name` range-selector to handle TypeLocs correctly.

Previously, where `name` was applied to a template-specialization TypeLoc, it
returned the entire specialization (name, brackets, args) rather than just the
name identifier. With this change, exactly the name token is selected.

Differential Revision: https://reviews.llvm.org/D158771
parent 50b12761
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -232,9 +232,11 @@ RangeSelector transformer::name(std::string ID) {
    if (const auto *T = Node.get<TypeLoc>()) {
      TypeLoc Loc = *T;
      auto ET = Loc.getAs<ElaboratedTypeLoc>();
      if (!ET.isNull()) {
      if (!ET.isNull())
        Loc = ET.getNamedTypeLoc();
      }
      if (auto SpecLoc = Loc.getAs<TemplateSpecializationTypeLoc>();
          !SpecLoc.isNull())
        return CharSourceRange::getTokenRange(SpecLoc.getTemplateNameLoc());
      return CharSourceRange::getTokenRange(Loc.getSourceRange());
    }
    return typeError(ID, Node.getNodeKind(),
+16 −0
Original line number Diff line number Diff line
@@ -486,6 +486,22 @@ TEST(RangeSelectorTest, NameOpTypeLoc) {
  EXPECT_THAT_EXPECTED(select(name(CtorTy), MatchC), HasValue("Foo"));
}

TEST(RangeSelectorTest, NameOpTemplateSpecializationTypeLoc) {
  StringRef Code = R"cc(
    namespace ns {
    template <typename T>
    struct Foo {};
    }  // namespace ns

    ns::Foo<int> a;
  )cc";
  const char *Loc = "tyloc";
  // Matches declaration of `a`.
  TestMatch MatchA =
      matchCode(Code, varDecl(hasName("a"), hasTypeLoc(typeLoc().bind(Loc))));
  EXPECT_THAT_EXPECTED(select(name(Loc), MatchA), HasValue("Foo"));
}

TEST(RangeSelectorTest, NameOpErrors) {
  EXPECT_THAT_EXPECTED(selectFromTrivial(name("unbound_id")),
                       Failed<StringError>(withUnboundNodeMessage()));