kadircet created this revision.
kadircet added reviewers: ioeric, ilya-biryukov.
Herald added a subscriber: cfe-commits.

In clangd we had a new type of completion suggestions for cpp
class/struct/unions that will show override signatures for virtual methods in
base classes. This patch implements it in sema because it is hard to deduce more
info about completion token outside of Sema and handle itchy cases.

See the patch https://reviews.llvm.org/D50898 for more info on the 
functionality.

In addition to above patch this one also converts the suggestion into a
CK_Pattern with whole insertion text as the name of the suggestion and factors
out CodeCompletionString generation for declerations so that it can be re-used
by others.


Repository:
  rC Clang

https://reviews.llvm.org/D52225

Files:
  include/clang/Sema/CodeCompleteConsumer.h
  lib/Sema/SemaCodeComplete.cpp

Index: lib/Sema/SemaCodeComplete.cpp
===================================================================
--- lib/Sema/SemaCodeComplete.cpp
+++ lib/Sema/SemaCodeComplete.cpp
@@ -1596,6 +1596,66 @@
   Results.AddResult(CodeCompletionResult(Builder.TakeString()));
 }
 
+static void AddOverrideResults(ResultBuilder &Results,
+                               const CodeCompletionContext &CCContext,
+                               CodeCompletionBuilder &Builder, Sema &S) {
+  const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
+  // If not inside a class/struct/union return empty.
+  if (!CR)
+    return;
+  // First store overrides within current class.
+  // These are stored by name to make querying fast in the later step.
+  llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
+  for (auto *Method : CR->methods()) {
+    if (!Method->isVirtual() || !Method->getIdentifier())
+      continue;
+    Overrides[Method->getName()].push_back(Method);
+  }
+
+  for (const auto &Base : CR->bases()) {
+    const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
+    if (!BR)
+      continue;
+    for (auto *Method : BR->methods()) {
+      if (!Method->isVirtual() || !Method->getIdentifier())
+        continue;
+      const auto it = Overrides.find(Method->getName());
+      bool IsOverriden = false;
+      if (it != Overrides.end()) {
+        for (auto *MD : it->second) {
+          // If the method in current body is not an overload of this virtual
+          // function, then it overrides this one.
+          if (!S.IsOverload(MD, Method, false)) {
+            IsOverriden = true;
+            break;
+          }
+        }
+      }
+      if (!IsOverriden) {
+        std::string OverrideSignature;
+        llvm::raw_string_ostream OS(OverrideSignature);
+        CodeCompletionResult CCR(Method, 0);
+        PrintingPolicy Policy =
+            getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
+        CCR.createCodeCompletionStringForDecl(
+            S.getPreprocessor(), S.getASTContext(), Builder,
+            false, CCContext, Policy);
+        for(const auto& C : *Builder.TakeString()) {
+          if (C.Kind == CodeCompletionString::CK_Optional)
+            continue;
+          OS << C.Text;
+          if (C.Kind == CodeCompletionString::CK_ResultType)
+            OS << ' ';
+        }
+        OS << " override";
+        Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(OS.str()));
+        Results.AddResult(CodeCompletionResult(Builder.TakeString(), Method,
+                                               CCP_CodePattern));
+      }
+    }
+  }
+}
+
 /// Add language constructs that show up for "ordinary" names.
 static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
                                    Scope *S,
@@ -1704,6 +1764,9 @@
         if (IsNotInheritanceScope && Results.includeCodePatterns())
           Builder.AddChunk(CodeCompletionString::CK_Colon);
         Results.AddResult(Result(Builder.TakeString()));
+
+        AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
+                           Builder, SemaRef);
       }
     }
     LLVM_FALLTHROUGH;
@@ -2791,48 +2854,11 @@
   return Result.TakeString();
 }
 
-/// If possible, create a new code completion string for the given
-/// result.
-///
-/// \returns Either a new, heap-allocated code completion string describing
-/// how to use this result, or NULL to indicate that the string or name of the
-/// result is all that is needed.
-CodeCompletionString *
-CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
-                                                 Preprocessor &PP,
-                                         const CodeCompletionContext &CCContext,
-                                           CodeCompletionAllocator &Allocator,
-                                           CodeCompletionTUInfo &CCTUInfo,
-                                           bool IncludeBriefComments) {
-  if (Kind == RK_Macro)
-    return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
-
-  CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
-
-  PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
-  if (Kind == RK_Pattern) {
-    Pattern->Priority = Priority;
-    Pattern->Availability = Availability;
-
-    if (Declaration) {
-      Result.addParentContext(Declaration->getDeclContext());
-      Pattern->ParentName = Result.getParentName();
-      if (const RawComment *RC =
-              getPatternCompletionComment(Ctx, Declaration)) {
-        Result.addBriefComment(RC->getBriefText(Ctx));
-        Pattern->BriefComment = Result.getBriefComment();
-      }
-    }
-
-    return Pattern;
-  }
-
-  if (Kind == RK_Keyword) {
-    Result.AddTypedTextChunk(Keyword);
-    return Result.TakeString();
-  }
-  assert(Kind == RK_Declaration && "Missed a result kind?");
-  const NamedDecl *ND = Declaration;
+void CodeCompletionResult::createCodeCompletionStringForDecl(
+    Preprocessor &PP, ASTContext &Ctx,
+    CodeCompletionBuilder &Result, bool IncludeBriefComments,
+    const CodeCompletionContext &CCContext, PrintingPolicy &Policy) {
+  const NamedDecl* ND = Declaration;
   Result.addParentContext(ND->getDeclContext());
 
   if (IncludeBriefComments) {
@@ -2846,7 +2872,7 @@
     Result.AddTypedTextChunk(
                       Result.getAllocator().CopyString(ND->getNameAsString()));
     Result.AddTextChunk("::");
-    return Result.TakeString();
+    return;
   }
 
   for (const auto *I : ND->specific_attrs<AnnotateAttr>())
@@ -2862,7 +2888,7 @@
     AddFunctionParameterChunks(PP, Policy, Function, Result);
     Result.AddChunk(CodeCompletionString::CK_RightParen);
     AddFunctionTypeQualsToCompletionString(Result, Function);
-    return Result.TakeString();
+    return;
   }
 
   if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
@@ -2916,7 +2942,7 @@
     AddFunctionParameterChunks(PP, Policy, Function, Result);
     Result.AddChunk(CodeCompletionString::CK_RightParen);
     AddFunctionTypeQualsToCompletionString(Result, Function);
-    return Result.TakeString();
+    return;
   }
 
   if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
@@ -2927,15 +2953,14 @@
     Result.AddChunk(CodeCompletionString::CK_LeftAngle);
     AddTemplateParameterChunks(Ctx, Policy, Template, Result);
     Result.AddChunk(CodeCompletionString::CK_RightAngle);
-    return Result.TakeString();
+    return;
   }
-
   if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
     Selector Sel = Method->getSelector();
     if (Sel.isUnarySelector()) {
       Result.AddTypedTextChunk(Result.getAllocator().CopyString(
                                   Sel.getNameForSlot(0)));
-      return Result.TakeString();
+      return;
     }
 
     std::string SelName = Sel.getNameForSlot(0).str();
@@ -3017,15 +3042,60 @@
       MaybeAddSentinel(PP, Method, Result);
     }
 
-    return Result.TakeString();
+    return;
   }
 
   if (Qualifier)
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
                                    Ctx, Policy);
 
   Result.AddTypedTextChunk(
                        Result.getAllocator().CopyString(ND->getNameAsString()));
+}
+
+/// If possible, create a new code completion string for the given
+/// result.
+///
+/// \returns Either a new, heap-allocated code completion string describing
+/// how to use this result, or NULL to indicate that the string or name of the
+/// result is all that is needed.
+CodeCompletionString *
+CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
+                                                 Preprocessor &PP,
+                                         const CodeCompletionContext &CCContext,
+                                           CodeCompletionAllocator &Allocator,
+                                           CodeCompletionTUInfo &CCTUInfo,
+                                           bool IncludeBriefComments) {
+  if (Kind == RK_Macro)
+    return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
+
+  CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
+
+  PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
+  if (Kind == RK_Pattern) {
+    Pattern->Priority = Priority;
+    Pattern->Availability = Availability;
+
+    if (Declaration) {
+      Result.addParentContext(Declaration->getDeclContext());
+      Pattern->ParentName = Result.getParentName();
+      if (const RawComment *RC =
+              getPatternCompletionComment(Ctx, Declaration)) {
+        Result.addBriefComment(RC->getBriefText(Ctx));
+        Pattern->BriefComment = Result.getBriefComment();
+      }
+    }
+
+    return Pattern;
+  }
+
+  if (Kind == RK_Keyword) {
+    Result.AddTypedTextChunk(Keyword);
+    return Result.TakeString();
+  }
+  assert(Kind == RK_Declaration && "Missed a result kind?");
+  createCodeCompletionStringForDecl(PP, Ctx, Result, IncludeBriefComments,
+                                    CCContext, Policy);
   return Result.TakeString();
 }
 
Index: include/clang/Sema/CodeCompleteConsumer.h
===================================================================
--- include/clang/Sema/CodeCompleteConsumer.h
+++ include/clang/Sema/CodeCompleteConsumer.h
@@ -943,6 +943,12 @@
                                      CodeCompletionAllocator &Allocator,
                                      CodeCompletionTUInfo &CCTUInfo);
 
+  void createCodeCompletionStringForDecl(Preprocessor &PP, ASTContext &Ctx,
+                                         CodeCompletionBuilder &Result,
+                                         bool IncludeBriefComments,
+                                         const CodeCompletionContext &CCContext,
+                                         PrintingPolicy &Policy);
+
   /// Retrieve the name that should be used to order a result.
   ///
   /// If the name needs to be constructed as a string, that string will be
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to