yvvan created this revision.
yvvan added reviewers: klimek, bkramer, arphaman, ilya-biryukov, erikjv.

Currently getting such completions requires source correction, reparsing and 
calling completion again. And if it shows no results and rollback is required 
then it costs one more reparse.
With this change it's possible to get all results which can be later filtered 
to split changes which require correction.


https://reviews.llvm.org/D41537

Files:
  include/clang-c/Index.h
  include/clang/Sema/CodeCompleteConsumer.h
  include/clang/Sema/CodeCompleteOptions.h
  lib/Frontend/ASTUnit.cpp
  lib/Sema/CodeCompleteConsumer.cpp
  lib/Sema/SemaCodeComplete.cpp
  test/Index/complete-arrow-for-dot.cpp
  tools/c-index-test/c-index-test.c
  tools/libclang/CIndexCodeCompletion.cpp

Index: tools/libclang/CIndexCodeCompletion.cpp
===================================================================
--- tools/libclang/CIndexCodeCompletion.cpp
+++ tools/libclang/CIndexCodeCompletion.cpp
@@ -238,6 +238,16 @@
   return cxstring::createRef(CCStr->getBriefComment());
 }
 
+unsigned
+clang_getCompletionRequiresDotToArrowCorrection(CXCompletionString completion_string) {
+  CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+
+  if (!CCStr)
+    return false;
+
+  return CCStr->requiresDotToArrowCorrection();
+}
+
 namespace {
 
 /// \brief The CXCodeCompleteResults structure we allocate internally;
@@ -643,13 +653,13 @@
                           ArrayRef<CXUnsavedFile> unsaved_files,
                           unsigned options) {
   bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;
+  bool TryArrowInsteadOfDot = options & CXCodeComplete_TryArrowInsteadOfDot;
 
 #ifdef UDP_CODE_COMPLETION_LOGGER
 #ifdef UDP_CODE_COMPLETION_LOGGER_PORT
   const llvm::TimeRecord &StartTime =  llvm::TimeRecord::getCurrentTime();
 #endif
 #endif
-
   bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr;
 
   if (cxtu::isNotUsableTU(TU)) {
@@ -689,6 +699,7 @@
   // Create a code-completion consumer to capture the results.
   CodeCompleteOptions Opts;
   Opts.IncludeBriefComments = IncludeBriefComments;
+  Opts.TryArrowInsteadOfDot = TryArrowInsteadOfDot;
   CaptureCompletionResults Capture(Opts, *Results, &TU);
 
   // Perform completion.
Index: tools/c-index-test/c-index-test.c
===================================================================
--- tools/c-index-test/c-index-test.c
+++ tools/c-index-test/c-index-test.c
@@ -2227,7 +2227,13 @@
     fprintf(file, "(brief comment: %s)", BriefCommentCString);
   }
   clang_disposeString(BriefComment);
-  
+
+  unsigned RequiresDotToArrowCorrection =
+      clang_getCompletionRequiresDotToArrowCorrection(
+          completion_result->CompletionString);
+  if (RequiresDotToArrowCorrection) {
+    fprintf(file, " (requires correction: \".\" to \"->\")");
+  }
   fprintf(file, "\n");
 }
 
@@ -2324,6 +2330,8 @@
     completionOptions |= CXCodeComplete_IncludeCodePatterns;
   if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
     completionOptions |= CXCodeComplete_IncludeBriefComments;
+  if (getenv("CINDEXTEST_COMPLETION_TRY_ARROW_INSTEAD_OF_DOT"))
+    completionOptions |= CXCodeComplete_TryArrowInsteadOfDot;
   
   if (timing_only)
     input += strlen("-code-completion-timing=");
Index: test/Index/complete-arrow-for-dot.cpp
===================================================================
--- /dev/null
+++ test/Index/complete-arrow-for-dot.cpp
@@ -0,0 +1,29 @@
+struct X {
+  void doSomething();
+
+  int field;
+};
+
+void X::doSomething() {
+  // RUN: c-index-test -code-completion-at=%s:10:8 %s | FileCheck %s
+  // RUN: env CINDEXTEST_COMPLETION_TRY_ARROW_INSTEAD_OF_DOT=1 c-index-test -code-completion-at=%s:10:8 %s | FileCheck -check-prefix=CHECK-WITH-CORRECTION %s
+  this.;
+}
+
+// CHECK-NOT: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires correction: "." to "->")
+// CHECK-NOT: FieldDecl:{ResultType int}{TypedText field} (35) (requires correction: "." to "->")
+// CHECK-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires correction: "." to "->")
+// CHECK-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires correction: "." to "->")
+// CHECK-NOT: StructDecl:{TypedText X}{Text ::} (75) (requires correction: "." to "->")
+// CHECK-NOT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires correction: "." to "->")
+// CHECK: Completion contexts:
+// CHECK: Dot member access
+
+// CHECK-WITH-CORRECTION: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires correction: "." to "->")
+// CHECK-WITH-CORRECTION: FieldDecl:{ResultType int}{TypedText field} (35) (requires correction: "." to "->")
+// CHECK-WITH-CORRECTION: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires correction: "." to "->")
+// CHECK-WITH-CORRECTION: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires correction: "." to "->")
+// CHECK-WITH-CORRECTION: StructDecl:{TypedText X}{Text ::} (75) (requires correction: "." to "->")
+// CHECK-WITH-CORRECTION: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires correction: "." to "->")
+// CHECK-WITH-CORRECTION: Completion contexts:
+// CHECK-WITH-CORRECTION: Dot member access
Index: lib/Sema/SemaCodeComplete.cpp
===================================================================
--- lib/Sema/SemaCodeComplete.cpp
+++ lib/Sema/SemaCodeComplete.cpp
@@ -2740,7 +2740,8 @@
                                            CodeCompletionAllocator &Allocator,
                                            CodeCompletionTUInfo &CCTUInfo,
                                            bool IncludeBriefComments) {
-  CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
+  CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability,
+                               RequiresDotToArrowCorrection);
   
   PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
   if (Kind == RK_Pattern) {
@@ -3961,62 +3962,41 @@
   }
 }
 
-void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
-                                           SourceLocation OpLoc, bool IsArrow,
-                                           bool IsBaseExprStatement) {
-  if (!Base || !CodeCompleter)
-    return;
-  
-  ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
-  if (ConvertedBase.isInvalid())
-    return;
-  Base = ConvertedBase.get();
-  
-  QualType BaseType = Base->getType();
-
-  if (IsArrow) {
-    if (const PointerType *Ptr = BaseType->getAs<PointerType>())
-      BaseType = Ptr->getPointeeType();
-    else if (BaseType->isObjCObjectPointerType())
-      /*Do nothing*/ ;
-    else
-      return;
-  }
-  
+static ResultBuilder
+GetCodeCompleteMemberReferenceResults(Sema &SemaRef, Scope *S,
+                                      QualType BaseType, bool IsArrow,
+                                      bool IsBaseExprStatement) {
   enum CodeCompletionContext::Kind contextKind;
-  
+
   if (IsArrow) {
     contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
-  }
-  else {
+  } else {
     if (BaseType->isObjCObjectPointerType() ||
         BaseType->isObjCObjectOrInterfaceType()) {
       contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
-    }
-    else {
+    } else {
       contextKind = CodeCompletionContext::CCC_DotMemberAccess;
     }
   }
 
   CodeCompletionContext CCContext(contextKind, BaseType);
-  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
-                        CodeCompleter->getCodeCompletionTUInfo(),
-                        CCContext,
-                        &ResultBuilder::IsMember);
+  ResultBuilder Results(SemaRef, SemaRef.CodeCompleter->getAllocator(),
+                        SemaRef.CodeCompleter->getCodeCompletionTUInfo(),
+                        CCContext, &ResultBuilder::IsMember);
   Results.EnterNewScope();
   if (const RecordType *Record = BaseType->getAs<RecordType>()) {
-    AddRecordMembersCompletionResults(*this, Results, S, BaseType,
+    AddRecordMembersCompletionResults(SemaRef, Results, S, BaseType,
                                       Record->getDecl());
   } else if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {
     TemplateName TN = TST->getTemplateName();
     if (const auto *TD =
             dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
       CXXRecordDecl *RD = TD->getTemplatedDecl();
-      AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
+      AddRecordMembersCompletionResults(SemaRef, Results, S, BaseType, RD);
     }
   } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
     if (auto *RD = ICNT->getDecl())
-      AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
+      AddRecordMembersCompletionResults(SemaRef, Results, S, BaseType, RD);
   } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
     // Objective-C property reference.
     AddedPropertiesSet AddedProperties;
@@ -4026,42 +4006,120 @@
       // Add property results based on our interface.
       assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
       AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
-                        /*AllowNullaryMethods=*/true, CurContext,
+                        /*AllowNullaryMethods=*/true, SemaRef.CurContext,
                         AddedProperties, Results, IsBaseExprStatement);
     }
 
     // Add properties from the protocols in a qualified interface.
     for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
       AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
-                        CurContext, AddedProperties, Results,
+                        SemaRef.CurContext, AddedProperties, Results,
                         IsBaseExprStatement);
   } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
              (!IsArrow && BaseType->isObjCObjectType())) {
     // Objective-C instance variable access.
     ObjCInterfaceDecl *Class = nullptr;
-    if (const ObjCObjectPointerType *ObjCPtr
-                                    = BaseType->getAs<ObjCObjectPointerType>())
+    if (const ObjCObjectPointerType *ObjCPtr =
+            BaseType->getAs<ObjCObjectPointerType>())
       Class = ObjCPtr->getInterfaceDecl();
     else
       Class = BaseType->getAs<ObjCObjectType>()->getInterface();
-    
+
     // Add all ivars from this class and its superclasses.
     if (Class) {
-      CodeCompletionDeclConsumer Consumer(Results, CurContext);
+      CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);
       Results.setFilter(&ResultBuilder::IsObjCIvar);
-      LookupVisibleDecls(Class, LookupMemberName, Consumer,
-                         CodeCompleter->includeGlobals());
+      SemaRef.LookupVisibleDecls(Class, SemaRef.LookupMemberName, Consumer,
+                                 SemaRef.CodeCompleter->includeGlobals());
     }
   }
-  
+
   // FIXME: How do we cope with isa?
-  
+
   Results.ExitScope();
+  return Results;
+}
 
+static void TryCompleteArrowInsteadOfDot(Sema &SemaRef, Scope *S, Expr *Base,
+                                         SourceLocation OpLoc,
+                                         bool IsBaseExprStatement,
+                                         ResultBuilder &ExistingResults) {
+  QualType BaseType = Base->getType();
+  if (BaseType->isPointerType()) {
+    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+  } else {
+    const DeclarationName ArrowOpName =
+        SemaRef.Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
+    bool HasArrowOp = false;
+    for (CodeCompletionResult *result = ExistingResults.data();
+         result != ExistingResults.data() + ExistingResults.size(); ++result) {
+      if (result->Kind != CodeCompletionResult::RK_Declaration)
+        continue;
+      const NamedDecl *decl = result->getDeclaration();
+      if (decl && decl->getDeclName() == ArrowOpName) {
+        HasArrowOp = true;
+        break;
+      }
+    }
+    if (!HasArrowOp)
+      return;
+    ParsedType ObjectType;
+    bool MayBePseudoDestructor = false;
+    ExprResult LHS = SemaRef.ActOnStartCXXMemberReference(
+        S, Base, OpLoc, tok::arrow, ObjectType, MayBePseudoDestructor);
+    ExprResult ConvertedBase =
+        SemaRef.PerformMemberExprBaseConversion(LHS.get(), true);
+    if (ConvertedBase.isInvalid())
+      return;
+    Base = ConvertedBase.get();
+    BaseType = Base->getType();
+    if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+      BaseType = Ptr->getPointeeType();
+  }
+
+  ResultBuilder ArrowResults = GetCodeCompleteMemberReferenceResults(
+      SemaRef, S, BaseType, true, IsBaseExprStatement);
+  for (size_t i = 0; i < ArrowResults.size(); ++i)
+    ArrowResults.data()[i].RequiresDotToArrowCorrection = true;
+  HandleCodeCompleteResults(&SemaRef, SemaRef.CodeCompleter,
+                            ArrowResults.getCompletionContext(),
+                            ArrowResults.data(), ArrowResults.size());
+}
+
+void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
+                                           SourceLocation OpLoc, bool IsArrow,
+                                           bool IsBaseExprStatement) {
+  if (!Base || !CodeCompleter)
+    return;
+
+  ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
+  if (ConvertedBase.isInvalid())
+    return;
+  Base = ConvertedBase.get();
+
+  QualType BaseType = Base->getType();
+
+  if (IsArrow) {
+    if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+      BaseType = Ptr->getPointeeType();
+    else if (BaseType->isObjCObjectPointerType())
+      /*Do nothing*/;
+    else
+      return;
+  }
+
+  ResultBuilder Results = GetCodeCompleteMemberReferenceResults(
+      *this, S, BaseType, IsArrow, IsBaseExprStatement);
+
+  if (CodeCompleter->tryArrowInsteadOfDot() && !IsArrow &&
+      !BaseType->isObjCObjectPointerType() &&
+      !BaseType->isObjCObjectOrInterfaceType()) {
+    TryCompleteArrowInsteadOfDot(*this, S, Base, OpLoc, IsBaseExprStatement,
+                                 Results);
+  }
   // Hand off the results found for code completion.
-  HandleCodeCompleteResults(this, CodeCompleter, 
-                            Results.getCompletionContext(),
-                            Results.data(),Results.size());
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+                            Results.data(), Results.size());
 }
 
 void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
Index: lib/Sema/CodeCompleteConsumer.cpp
===================================================================
--- lib/Sema/CodeCompleteConsumer.cpp
+++ lib/Sema/CodeCompleteConsumer.cpp
@@ -194,10 +194,12 @@
                                            const char **Annotations,
                                            unsigned NumAnnotations,
                                            StringRef ParentName,
-                                           const char *BriefComment)
+                                           const char *BriefComment,
+                                           bool RequiresDotToArrowCorrection)
   : NumChunks(NumChunks), NumAnnotations(NumAnnotations),
     Priority(Priority), Availability(Availability),
-    ParentName(ParentName), BriefComment(BriefComment)
+    ParentName(ParentName), BriefComment(BriefComment),
+    RequiresDotToArrowCorrection(RequiresDotToArrowCorrection)
 { 
   assert(NumChunks <= 0xffff);
   assert(NumAnnotations <= 0xffff);
@@ -335,7 +337,7 @@
     = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
                                      Priority, Availability,
                                      Annotations.data(), Annotations.size(),
-                                     ParentName, BriefComment);
+                                     ParentName, BriefComment, RequiresDotToArrowCorrection);
   Chunks.clear();
   return Result;
 }
Index: lib/Frontend/ASTUnit.cpp
===================================================================
--- lib/Frontend/ASTUnit.cpp
+++ lib/Frontend/ASTUnit.cpp
@@ -2068,6 +2068,7 @@
   CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;
   CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();
   CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;
+  CodeCompleteOpts.TryArrowInsteadOfDot = Consumer.tryArrowInsteadOfDot();
 
   assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion);
 
Index: include/clang/Sema/CodeCompleteOptions.h
===================================================================
--- include/clang/Sema/CodeCompleteOptions.h
+++ include/clang/Sema/CodeCompleteOptions.h
@@ -35,9 +35,12 @@
   /// Show brief documentation comments in code completion results.
   unsigned IncludeBriefComments : 1;
 
+  /// Show also results after dot to arrow correction if arrow operator can be applied.
+  unsigned TryArrowInsteadOfDot : 1;
+
   CodeCompleteOptions()
       : IncludeMacros(0), IncludeCodePatterns(0), IncludeGlobals(1),
-        IncludeNamespaceLevelDecls(1), IncludeBriefComments(0) {}
+        IncludeNamespaceLevelDecls(1), IncludeBriefComments(0), TryArrowInsteadOfDot(0) {}
 };
 
 } // namespace clang
Index: include/clang/Sema/CodeCompleteConsumer.h
===================================================================
--- include/clang/Sema/CodeCompleteConsumer.h
+++ include/clang/Sema/CodeCompleteConsumer.h
@@ -456,22 +456,25 @@
 
   /// \brief The availability of this code-completion result.
   unsigned Availability : 2;
-  
+
   /// \brief The name of the parent context.
   StringRef ParentName;
 
   /// \brief A brief documentation comment attached to the declaration of
   /// entity being completed by this result.
   const char *BriefComment;
-  
+
+  /// \brief If this is the result of arrow completion when dot is present.
+  bool RequiresDotToArrowCorrection : 1;
+
   CodeCompletionString(const CodeCompletionString &) = delete;
   void operator=(const CodeCompletionString &) = delete;
 
   CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
                        unsigned Priority, CXAvailabilityKind Availability,
                        const char **Annotations, unsigned NumAnnotations,
-                       StringRef ParentName,
-                       const char *BriefComment);
+                       StringRef ParentName, const char *BriefComment,
+                       bool RequiresDotToArrowCorrection = false);
   ~CodeCompletionString() = default;
 
   friend class CodeCompletionBuilder;
@@ -498,6 +501,9 @@
   /// \brief Retrieve the availability of this code completion result.
   unsigned getAvailability() const { return Availability; }
 
+  /// \brief Check if this completion requires dot to arrow correction.
+  bool requiresDotToArrowCorrection() const { return RequiresDotToArrowCorrection; }
+
   /// \brief Retrieve the number of annotations for this code completion result.
   unsigned getAnnotationCount() const;
 
@@ -570,6 +576,7 @@
   CXAvailabilityKind Availability;
   StringRef ParentName;
   const char *BriefComment;
+  bool RequiresDotToArrowCorrection = false;
   
   /// \brief The chunks stored in this string.
   SmallVector<Chunk, 4> Chunks;
@@ -585,10 +592,12 @@
 
   CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
                         CodeCompletionTUInfo &CCTUInfo,
-                        unsigned Priority, CXAvailabilityKind Availability)
+                        unsigned Priority, CXAvailabilityKind Availability,
+                        bool RequiresDotToArrowCorrection = false)
     : Allocator(Allocator), CCTUInfo(CCTUInfo),
       Priority(Priority), Availability(Availability),
-      BriefComment(nullptr) { }
+      BriefComment(nullptr),
+      RequiresDotToArrowCorrection(RequiresDotToArrowCorrection) { }
 
   /// \brief Retrieve the allocator into which the code completion
   /// strings should be allocated.
@@ -698,6 +707,9 @@
   /// rather than a use of that entity.
   bool DeclaringEntity : 1;
 
+  /// \brief If this is the result of arrow completion when dot is present.
+  bool RequiresDotToArrowCorrection : 1;
+
   /// \brief If the result should have a nested-name-specifier, this is it.
   /// When \c QualifierIsInformative, the nested-name-specifier is
   /// informative rather than required.
@@ -714,7 +726,8 @@
       Availability(CXAvailability_Available), Hidden(false),
       QualifierIsInformative(QualifierIsInformative),
       StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-      DeclaringEntity(false), Qualifier(Qualifier) {
+      DeclaringEntity(false), RequiresDotToArrowCorrection(false),
+      Qualifier(Qualifier) {
     computeCursorKindAndAvailability(Accessible);
   }
 
@@ -725,7 +738,7 @@
       Availability(CXAvailability_Available), Hidden(false),
       QualifierIsInformative(0), StartsNestedNameSpecifier(false),
       AllParametersAreInformative(false), DeclaringEntity(false),
-      Qualifier(nullptr) {}
+      RequiresDotToArrowCorrection(false), Qualifier(nullptr) {}
 
   /// \brief Build a result that refers to a macro.
   CodeCompletionResult(const IdentifierInfo *Macro,
@@ -735,7 +748,7 @@
       Availability(CXAvailability_Available), Hidden(false),
       QualifierIsInformative(0), StartsNestedNameSpecifier(false),
       AllParametersAreInformative(false), DeclaringEntity(false),
-      Qualifier(nullptr) {}
+      RequiresDotToArrowCorrection(false), Qualifier(nullptr) {}
 
   /// \brief Build a result that refers to a pattern.
   CodeCompletionResult(CodeCompletionString *Pattern,
@@ -747,7 +760,8 @@
       Kind(RK_Pattern), CursorKind(CursorKind), Availability(Availability),
       Hidden(false), QualifierIsInformative(0),
       StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-      DeclaringEntity(false), Qualifier(nullptr)
+      DeclaringEntity(false), RequiresDotToArrowCorrection(false),
+      Qualifier(nullptr)
   {
   }
 
@@ -759,7 +773,7 @@
       Kind(RK_Pattern), Availability(CXAvailability_Available), Hidden(false),
       QualifierIsInformative(false), StartsNestedNameSpecifier(false),
       AllParametersAreInformative(false), DeclaringEntity(false),
-      Qualifier(nullptr) {
+      RequiresDotToArrowCorrection(false), Qualifier(nullptr) {
     computeCursorKindAndAvailability();
   }  
   
@@ -934,6 +948,11 @@
     return CodeCompleteOpts.IncludeBriefComments;
   }
 
+  /// \brief Whether to try dot to arrow correction if arrow operator can be applied.
+  bool tryArrowInsteadOfDot() const {
+    return CodeCompleteOpts.TryArrowInsteadOfDot;
+  }
+
   /// \brief Determine whether the output of this consumer is binary.
   bool isOutputBinary() const { return OutputIsBinary; }
 
Index: include/clang-c/Index.h
===================================================================
--- include/clang-c/Index.h
+++ include/clang-c/Index.h
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 45
+#define CINDEX_VERSION_MINOR 46
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
       ((major) * 10000)                       \
@@ -5096,6 +5096,12 @@
 clang_getCompletionBriefComment(CXCompletionString completion_string);
 
 /**
+ * \brief Retrieve the necessity of dot to arrow correction for the given completion string.
+ */
+CINDEX_LINKAGE unsigned
+clang_getCompletionRequiresDotToArrowCorrection(CXCompletionString completion_string);
+
+/**
  * \brief Retrieve a completion string for an arbitrary declaration or macro
  * definition cursor.
  *
@@ -5151,7 +5157,12 @@
    * \brief Whether to include brief documentation within the set of code
    * completions returned.
    */
-  CXCodeComplete_IncludeBriefComments = 0x04
+  CXCodeComplete_IncludeBriefComments = 0x04,
+
+  /**
+   * \brief Whether to try dot to arrow correction if arrow operator can be applied.
+   */
+  CXCodeComplete_TryArrowInsteadOfDot = 0x08
 };
 
 /**
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to