njames93 updated this revision to Diff 247538.
njames93 added a comment.

- Fix assertion when no Attrs are present


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75429/new/

https://reviews.llvm.org/D75429

Files:
  clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
  clang-tools-extra/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -2068,6 +2068,52 @@
               };)cpp",
           "Foo::Foo(int z) __attribute__((weak)) : bar(2){}\n",
       },
+      // Overridden Methods
+      {
+          R"cpp(
+            struct A {
+              virtual void f^oo() {}
+            };)cpp",
+          R"cpp(
+            struct A {
+              virtual void foo() ;
+            };)cpp",
+          " void A::foo() {}\n",
+      },
+      {
+          R"cpp(
+            struct A {
+              virtual void foo() = 0;
+            };
+            struct B : A {
+              void fo^o() override {}
+            };)cpp",
+          R"cpp(
+            struct A {
+              virtual void foo() = 0;
+            };
+            struct B : A {
+              void foo() override ;
+            };)cpp",
+          "void B::foo()  {}\n",
+      },
+      {
+          R"cpp(
+            struct A {
+              virtual void foo() = 0;
+            };
+            struct B : A {
+              void fo^o() final {}
+            };)cpp",
+          R"cpp(
+            struct A {
+              virtual void foo() = 0;
+            };
+            struct B : A {
+              void foo() final ;
+            };)cpp",
+          "void B::foo()  {}\n",
+      },
   };
   for (const auto &Case : Cases) {
     SCOPED_TRACE(Case.Test);
Index: clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
===================================================================
--- clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
@@ -16,6 +16,7 @@
 #include "SourceCode.h"
 #include "refactor/Tweak.h"
 #include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
@@ -211,6 +212,60 @@
     }
   }
 
+  // Remove the virtual, override and final specifiers.
+  if (FD->hasAttrs()) {
+    for (auto *Attr : FD->getAttrs()) {
+      if (isa<OverrideAttr>(Attr) || isa<FinalAttr>(Attr)) {
+        assert(Attr->getLocation().isValid());
+        if (Attr->getLocation().isMacroID()) {
+          Errors = llvm::joinErrors(
+              std::move(Errors),
+              llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                      isa<OverrideAttr>(Attr)
+                                          ? "define outline: Can't move out of "
+                                            "line as function has "
+                                            "a macro `override` specifier"
+                                          : "define outline: Can't move out of "
+                                            "line as function has "
+                                            "a macro `final` specifier"));
+          continue;
+        }
+        CharSourceRange DelRange =
+            CharSourceRange::getTokenRange(Attr->getLocation());
+        if (auto Err =
+                QualifierInsertions.add(tooling::Replacement(SM, DelRange, "")))
+          Errors = llvm::joinErrors(std::move(Errors), std::move(Err));
+      }
+    }
+  }
+  if (FD->isVirtualAsWritten()) {
+    SourceRange SpecRange{FD->getBeginLoc(), FD->getLocation()};
+    bool Any = false;
+    // Clang allows duplicating virtual specifiers so check for multiple
+    // occurances.
+    for (const syntax::Token &Tok : TokBuf.expandedTokens(SpecRange)) {
+      if (Tok.kind() == tok::kw_virtual) {
+        assert(Tok.location().isValid());
+        if (Tok.location().isMacroID()) {
+          Errors =
+              llvm::joinErrors(std::move(Errors),
+                               llvm::createStringError(
+                                   llvm::inconvertibleErrorCode(),
+                                   "define outline: Can't move out of line as "
+                                   "function has a macro `virtual` specifier"));
+          continue;
+        }
+        Any = true;
+        CharSourceRange DelRange =
+            CharSourceRange::getTokenRange(Tok.location());
+        if (auto Err =
+                QualifierInsertions.add(tooling::Replacement(SM, DelRange, "")))
+          Errors = llvm::joinErrors(std::move(Errors), std::move(Err));
+      }
+    }
+    assert(Any); // Ensure at least one virtual was found
+  }
+
   if (Errors)
     return std::move(Errors);
   return getFunctionSourceAfterReplacements(FD, QualifierInsertions);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to