dgoldman created this revision.
Herald added subscribers: usaxena95, kadircet, arphaman.
dgoldman requested review of this revision.
Herald added projects: clang, clang-tools-extra.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118063

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Parse/ParseObjc.cpp
  clang/lib/Sema/SemaCodeComplete.cpp

Index: clang/lib/Sema/SemaCodeComplete.cpp
===================================================================
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -3519,10 +3519,14 @@
   }
 
   if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+    // FIXME:(davg): should this just be a fix it itself?
+    bool needRBrac = FixIts.size() == 1;
     Selector Sel = Method->getSelector();
     if (Sel.isUnarySelector()) {
       Result.AddTypedTextChunk(
           Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
+      if (needRBrac)
+        Result.AddChunk(CodeCompletionString::CK_RightBracket);
       return Result.TakeString();
     }
 
@@ -3605,6 +3609,8 @@
 
       MaybeAddSentinel(PP, Method, Result);
     }
+    if (needRBrac)
+        Result.AddChunk(CodeCompletionString::CK_RightBracket);
 
     return Result.TakeString();
   }
@@ -4242,6 +4248,7 @@
                                        ParsedType Receiver,
                                        ArrayRef<IdentifierInfo *> SelIdents,
                                        bool AtArgumentExpression, bool IsSuper,
+                                       SourceRange BracFixIts,
                                        ResultBuilder &Results);
 
 void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
@@ -4302,8 +4309,12 @@
                         Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
           0) {
     ParsedType T = DS.getRepAsType();
-    if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
-      AddClassMessageCompletions(*this, S, T, None, false, false, Results);
+    if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) {
+      // FIXME: conditionalize fix it.
+      SourceRange InferredBrac = SourceRange(DS.getBeginLoc(), DS.getEndLoc());
+      AddClassMessageCompletions(*this, S, T, None, false, false,
+                                 InferredBrac, Results);
+    }
   }
 
   // Note that we intentionally suppress macro results here, since we do not
@@ -6924,7 +6935,8 @@
                            DeclContext *CurContext,
                            VisitedSelectorSet &Selectors, bool AllowSameLength,
                            ResultBuilder &Results, bool InOriginalClass = true,
-                           bool IsRootClass = false) {
+                           bool IsRootClass = false,
+                           SourceRange BracFixItsRange = SourceRange()) {
   typedef CodeCompletionResult Result;
   Container = getContainerDef(Container);
   ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
@@ -6947,6 +6959,13 @@
       R.AllParametersAreInformative = (WantKind != MK_Any);
       if (!InOriginalClass)
         setInBaseClass(R);
+      if (BracFixItsRange.isValid()) {
+        llvm::errs() << "Adding fix its\n";
+        R.FixIts.emplace_back(FixItHint::CreateInsertion(BracFixItsRange.getBegin(), "["));
+        R.FixIts.emplace_back(FixItHint::CreateInsertion(BracFixItsRange.getEnd(), "]"));
+      } else {
+        llvm::errs() << "fix it range invalid\n";
+      }
       Results.MaybeAddResult(R, CurContext);
     }
   }
@@ -6960,7 +6979,8 @@
                                                 E = Protocols.end();
            I != E; ++I)
         AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
-                       Selectors, AllowSameLength, Results, false, IsRootClass);
+                       Selectors, AllowSameLength, Results, false, IsRootClass,
+                       BracFixItsRange);
     }
   }
 
@@ -6970,13 +6990,14 @@
   // Add methods in protocols.
   for (ObjCProtocolDecl *I : IFace->protocols())
     AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
-                   Selectors, AllowSameLength, Results, false, IsRootClass);
+                   Selectors, AllowSameLength, Results, false, IsRootClass,
+                   BracFixItsRange);
 
   // Add methods in categories.
   for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
     AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
                    CurContext, Selectors, AllowSameLength, Results,
-                   InOriginalClass, IsRootClass);
+                   InOriginalClass, IsRootClass, BracFixItsRange);
 
     // Add a categories protocol methods.
     const ObjCList<ObjCProtocolDecl> &Protocols =
@@ -6985,13 +7006,14 @@
                                               E = Protocols.end();
          I != E; ++I)
       AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
-                     Selectors, AllowSameLength, Results, false, IsRootClass);
+                     Selectors, AllowSameLength, Results, false, IsRootClass,
+                     BracFixItsRange);
 
     // Add methods in category implementations.
     if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
       AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
                      Selectors, AllowSameLength, Results, InOriginalClass,
-                     IsRootClass);
+                     IsRootClass, BracFixItsRange);
   }
 
   // Add methods in superclass.
@@ -6999,13 +7021,14 @@
   if (IFace->getSuperClass())
     AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
                    SelIdents, CurContext, Selectors, AllowSameLength, Results,
-                   /*IsRootClass=*/false);
+                   /*InOriginalClass=*/false, /*IsRootClass=*/false,
+                   BracFixItsRange);
 
   // Add methods in our implementation, if any.
   if (ObjCImplementationDecl *Impl = IFace->getImplementation())
     AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
                    Selectors, AllowSameLength, Results, InOriginalClass,
-                   IsRootClass);
+                   IsRootClass, BracFixItsRange);
 }
 
 void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
@@ -7462,10 +7485,17 @@
                                        ParsedType Receiver,
                                        ArrayRef<IdentifierInfo *> SelIdents,
                                        bool AtArgumentExpression, bool IsSuper,
+                                       SourceRange BracFixIts,
                                        ResultBuilder &Results) {
   typedef CodeCompletionResult Result;
   ObjCInterfaceDecl *CDecl = nullptr;
 
+  llvm::errs() << "AddClassMessageCompletions\n";
+  if (BracFixIts.getBegin().isValid())
+    llvm::errs() << "LBracValid\n";
+  if (BracFixIts.getEnd().isValid())
+    llvm::errs() << "RBracValid\n";
+
   // If the given name refers to an interface type, retrieve the
   // corresponding declaration.
   if (Receiver) {
@@ -7495,7 +7525,8 @@
   VisitedSelectorSet Selectors;
   if (CDecl)
     AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
-                   Selectors, AtArgumentExpression, Results);
+                   Selectors, AtArgumentExpression, Results, false, false,
+                   BracFixIts);
   else {
     // We're messaging "id" as a type; provide all class/factory methods.
 
@@ -7525,6 +7556,7 @@
                  Results.getBasePriority(MethList->getMethod()), nullptr);
         R.StartParameter = SelIdents.size();
         R.AllParametersAreInformative = false;
+        // FIXME: add it fix it here too.
         Results.MaybeAddResult(R, SemaRef.CurContext);
       }
     }
@@ -7536,7 +7568,8 @@
 void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
                                         ArrayRef<IdentifierInfo *> SelIdents,
                                         bool AtArgumentExpression,
-                                        bool IsSuper) {
+                                        bool IsSuper,
+                                        SourceRange InferredBrac) {
 
   QualType T = this->GetTypeFromParser(Receiver);
 
@@ -7546,8 +7579,15 @@
       CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
                             SelIdents));
 
+  llvm::errs() << "CodeCompleteObjCClassMessage\n";
+  SourceRange BracFixIt;
+  if (CodeCompleter->includeFixIts() && InferredBrac.isValid()) {
+    BracFixIt = std::move(InferredBrac);
+  }
+
   AddClassMessageCompletions(*this, S, Receiver, SelIdents,
-                             AtArgumentExpression, IsSuper, Results);
+                             AtArgumentExpression, IsSuper,
+                             BracFixIt, Results);
 
   // If we're actually at the argument expression (rather than prior to the
   // selector), we're actually performing code completion for an expression.
Index: clang/lib/Parse/ParseObjc.cpp
===================================================================
--- clang/lib/Parse/ParseObjc.cpp
+++ clang/lib/Parse/ParseObjc.cpp
@@ -3145,16 +3145,27 @@
 Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
                                        SourceLocation SuperLoc,
                                        ParsedType ReceiverType,
-                                       Expr *ReceiverExpr) {
+                                       Expr *ReceiverExpr,
+                                       SourceLocation InferredLBracLoc) {
   InMessageExpressionRAIIObject InMessage(*this, true);
 
   if (Tok.is(tok::code_completion)) {
+    SourceRange InferredBrac;
+    if (InferredLBracLoc.isValid()) {
+      InferredBrac = SourceRange(InferredLBracLoc, Tok.getLocation());
+      llvm::errs() << "[BUMBO] Found bracket replacement ";
+      llvm::errs().flush();
+      // InferredBrac.dump();
+    }
+    llvm::errs() << "[BUMBO] Triggering objc message code completion";
+    llvm::errs().flush();
+
     if (SuperLoc.isValid())
       Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None,
                                            false);
     else if (ReceiverType)
       Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, None,
-                                           false);
+                                           false, false, InferredBrac);
     else
       Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
                                               None, false);
Index: clang/lib/Parse/ParseExpr.cpp
===================================================================
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -1185,7 +1185,7 @@
          (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||
          Tok.is(tok::code_completion))) {
       Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, nullptr,
-                                           nullptr);
+                                           nullptr, ILoc);
       break;
     }
 
@@ -1219,7 +1219,7 @@
 
             Res = ParseObjCMessageExpressionBody(SourceLocation(),
                                                  SourceLocation(),
-                                                 Ty.get(), nullptr);
+                                                 Ty.get(), nullptr, ILoc);
             break;
           }
     }
@@ -1492,7 +1492,7 @@
 
       ConsumeAnnotationToken();
       Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
-                                           Ty.get(), nullptr);
+                                           Ty.get(), nullptr, Tok.getLocation());
       break;
     }
     LLVM_FALLTHROUGH;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -12271,7 +12271,8 @@
   void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
                                     ArrayRef<IdentifierInfo *> SelIdents,
                                     bool AtArgumentExpression,
-                                    bool IsSuper = false);
+                                    bool IsSuper = false,
+                                    SourceRange InferredBrac = SourceRange());
   void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
                                        ArrayRef<IdentifierInfo *> SelIdents,
                                        bool AtArgumentExpression,
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2047,7 +2047,8 @@
   ExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
                                             SourceLocation SuperLoc,
                                             ParsedType ReceiverType,
-                                            Expr *ReceiverExpr);
+                                            Expr *ReceiverExpr,
+                                            SourceLocation InferredLBracLoc = SourceLocation());
   ExprResult ParseAssignmentExprWithObjCMessageExprStart(
       SourceLocation LBracloc, SourceLocation SuperLoc,
       ParsedType ReceiverType, Expr *ReceiverExpr);
Index: clang-tools-extra/clangd/CodeComplete.cpp
===================================================================
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -1967,6 +1967,9 @@
     if (FixIt.range.end == LSP.textEdit->range.start) {
       LSP.textEdit->newText = FixIt.newText + LSP.textEdit->newText;
       LSP.textEdit->range.start = FixIt.range.start;
+    } else if (FixIt.range.start == LSP.textEdit->range.end) {
+      LSP.textEdit->newText = LSP.textEdit->newText + FixIt.newText;
+      LSP.textEdit->range.end = FixIt.range.end;
     } else {
       LSP.additionalTextEdits.push_back(FixIt);
     }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to