Commit af071f03 authored by Sam McCall's avatar Sam McCall
Browse files

[clangd] Improve ObjC property handling in SelectionTree.

Fixes https://github.com/clangd/clangd/issues/233

Reviewers: dgoldman

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D72634
parent 88d6f182
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -462,6 +462,14 @@ public:
             TraverseStmt(S->getRangeInit()) && TraverseStmt(S->getBody());
    });
  }
  // OpaqueValueExpr blocks traversal, we must explicitly traverse it.
  bool TraverseOpaqueValueExpr(OpaqueValueExpr *E) {
    return traverseNode(E, [&] { return TraverseStmt(E->getSourceExpr()); });
  }
  // We only want to traverse the *syntactic form* to understand the selection.
  bool TraversePseudoObjectExpr(PseudoObjectExpr *E) {
    return traverseNode(E, [&] { return TraverseStmt(E->getSyntacticForm()); });
  }

private:
  using Base = RecursiveASTVisitor<SelectionVisitor>;
+2 −1
Original line number Diff line number Diff line
@@ -536,7 +536,8 @@ TEST_F(TargetDeclTest, ObjC) {
      [[f.x]].y = 0;
    }
  )cpp";
  EXPECT_DECLS("OpaqueValueExpr", "@property(atomic, retain, readwrite) I *x");
  EXPECT_DECLS("ObjCPropertyRefExpr",
               "@property(atomic, retain, readwrite) I *x");

  Code = R"cpp(
    @protocol Foo
+41 −0
Original line number Diff line number Diff line
@@ -323,12 +323,52 @@ TEST(SelectionTest, CommonAncestor) {
            Foo x = [[^12_ud]];
          )cpp",
          "UserDefinedLiteral"},

      {
          R"cpp(
        int a;
        decltype([[^a]] + a) b;
        )cpp",
          "DeclRefExpr"},

      // Objective-C OpaqueValueExpr/PseudoObjectExpr has weird ASTs.
      // Need to traverse the contents of the OpaqueValueExpr to the POE,
      // and ensure we traverse only the syntactic form of the PseudoObjectExpr.
      {
          R"cpp(
            @interface I{}
            @property(retain) I*x;
            @property(retain) I*y;
            @end
            void test(I *f) { [[^f]].x.y = 0; }
          )cpp",
          "DeclRefExpr"},
      {
          R"cpp(
            @interface I{}
            @property(retain) I*x;
            @property(retain) I*y;
            @end
            void test(I *f) { [[f.^x]].y = 0; }
          )cpp",
          "ObjCPropertyRefExpr"},
      // Examples with implicit properties.
      {
          R"cpp(
            @interface I{}
            -(int)foo;
            @end
            int test(I *f) { return 42 + [[^f]].foo; }
          )cpp",
          "DeclRefExpr"},
      {
          R"cpp(
            @interface I{}
            -(int)foo;
            @end
            int test(I *f) { return 42 + [[f.^foo]]; }
          )cpp",
          "ObjCPropertyRefExpr"},
  };
  for (const Case &C : Cases) {
    Annotations Test(C.Code);
@@ -339,6 +379,7 @@ TEST(SelectionTest, CommonAncestor) {
    // FIXME: Auto-completion in a template requires disabling delayed template
    // parsing.
    TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
    TU.ExtraArgs.push_back("-xobjective-c++");

    auto AST = TU.build();
    auto T = makeSelectionTree(C.Code, AST);