[clang-tools-extra] c5c3cdb - [clangd] Populate-switch triggers when the whole condition is selected.

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 8 12:06:16 PDT 2021


Author: Sam McCall
Date: 2021-08-08T21:06:08+02:00
New Revision: c5c3cdb9c92895a63993cee70d2dd776ff9519c3

URL: https://github.com/llvm/llvm-project/commit/c5c3cdb9c92895a63993cee70d2dd776ff9519c3
DIFF: https://github.com/llvm/llvm-project/commit/c5c3cdb9c92895a63993cee70d2dd776ff9519c3.diff

LOG: [clangd] Populate-switch triggers when the whole condition is selected.

This allows vscode to find it as a diagnostic quickfix for -Wswitch.

While here, group the code into chunks and add a couple more comments.

Added: 
    

Modified: 
    clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
    clang-tools-extra/clangd/unittests/tweaks/PopulateSwitchTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
index bae80cdecf590..40af43fef4aaf 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
@@ -88,47 +88,39 @@ bool PopulateSwitch::prepare(const Selection &Sel) {
   if (!CA)
     return false;
 
-  const Stmt *CAStmt = CA->ASTNode.get<Stmt>();
-  if (!CAStmt)
-    return false;
-
-  // Go up a level if we see a compound statement.
-  // switch (value) {}
-  //                ^^
-  if (isa<CompoundStmt>(CAStmt)) {
-    CA = CA->Parent;
-    if (!CA)
-      return false;
-
-    CAStmt = CA->ASTNode.get<Stmt>();
-    if (!CAStmt)
+  // Support targeting
+  //  - the switch statement itself (keyword, parens)
+  //  - the whole expression (possibly wrapped in implicit casts)
+  //  - the outer body (typically CompoundStmt)
+  // Selections *within* the expression or body don't trigger.
+  // direct child (the 
+  Switch = CA->ASTNode.get<SwitchStmt>();
+  if (!Switch) {
+    if (const SelectionTree::Node *Parent = CA->outerImplicit().Parent)
+      Switch = Parent->ASTNode.get<SwitchStmt>();
+    if (!Switch)
       return false;
   }
-
-  DeclCtx = &CA->getDeclContext();
-  Switch = dyn_cast<SwitchStmt>(CAStmt);
-  if (!Switch)
-    return false;
-
-  Body = dyn_cast<CompoundStmt>(Switch->getBody());
+  // Body need not be a CompoundStmt! But that's all we support editing.
+  Body = llvm::dyn_cast_or_null<CompoundStmt>(Switch->getBody());
   if (!Body)
     return false;
+  DeclCtx = &CA->getDeclContext();
 
+  // Examine the condition of the switch statement to see if it's an enum.
   const Expr *Cond = Switch->getCond();
   if (!Cond)
     return false;
-
   // Ignore implicit casts, since enums implicitly cast to integer types.
   Cond = Cond->IgnoreParenImpCasts();
-
   EnumT = Cond->getType()->getAsAdjusted<EnumType>();
   if (!EnumT)
     return false;
-
   EnumD = EnumT->getDecl();
   if (!EnumD || EnumD->isDependentType())
     return false;
 
+  // Finally, check which cases exist and which are covered.
   // We trigger if there are any values in the enum that aren't covered by the
   // switch.
 

diff  --git a/clang-tools-extra/clangd/unittests/tweaks/PopulateSwitchTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/PopulateSwitchTests.cpp
index 41518108a4f8d..13277c99cc314 100644
--- a/clang-tools-extra/clangd/unittests/tweaks/PopulateSwitchTests.cpp
+++ b/clang-tools-extra/clangd/unittests/tweaks/PopulateSwitchTests.cpp
@@ -95,6 +95,12 @@ TEST_F(PopulateSwitchTest, Test) {
           R""(enum Enum {A}; switch (^A) {})"",
           R""(enum Enum {A}; switch (A) {case A:break;})"",
       },
+      {
+          // Selection of whole switch condition
+          Function,
+          R""(enum Enum {A}; switch ([[A]]) {})"",
+          R""(enum Enum {A}; switch (A) {case A:break;})"",
+      },
       {
           // Selection in switch body
           Function,


        


More information about the cfe-commits mailing list