]> granicus.if.org Git - clang/commitdiff
[refactor][extract] code extracted from inline method should be placed
authorAlex Lorenz <arphaman@gmail.com>
Wed, 1 Nov 2017 01:12:56 +0000 (01:12 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Wed, 1 Nov 2017 01:12:56 +0000 (01:12 +0000)
in a function defined before the outer class

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317062 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Tooling/Refactoring/Extract.cpp
test/Refactor/Extract/FromMethodToFunction.cpp [new file with mode: 0644]

index e81bb3ffe9b4f57f3bf47a999fffec04edb363da..3f5a839318b1536e7ebcef3900dc343e0054a501 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "clang/Tooling/Refactoring/Extract/Extract.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/Rewrite/Core/Rewriter.h"
@@ -44,8 +45,12 @@ bool isSimpleExpression(const Expr *E) {
 }
 
 SourceLocation computeFunctionExtractionLocation(const Decl *D) {
-  // FIXME (Alex L): Method -> function extraction should place function before
-  // C++ record if the method is defined inside the record.
+  if (isa<CXXMethodDecl>(D)) {
+    // Code from method that is defined in class body should be extracted to a
+    // function defined just before the class.
+    while (const auto *RD = dyn_cast<CXXRecordDecl>(D->getLexicalDeclContext()))
+      D = RD;
+  }
   return D->getLocStart();
 }
 
diff --git a/test/Refactor/Extract/FromMethodToFunction.cpp b/test/Refactor/Extract/FromMethodToFunction.cpp
new file mode 100644 (file)
index 0000000..86bec16
--- /dev/null
@@ -0,0 +1,42 @@
+// RUN: clang-refactor extract -selection=test:%s %s -- -std=c++11 2>&1 | grep -v CHECK | FileCheck --check-prefixes=CHECK,CHECK-INNER %s
+// RUN: clang-refactor extract -selection=test:%s %s -- -std=c++11 -DMULTIPLE 2>&1 | grep -v CHECK | FileCheck --check-prefixes=CHECK,CHECK-OUTER %s
+
+#ifdef MULTIPLE
+class OuterClass {
+#define PREFIX OuterClass ::
+#else
+#define PREFIX
+#endif
+
+class AClass {
+
+  int method(int x) {
+    return /*range inner=->+0:38*/1 + 2 * 2;
+  }
+// CHECK-INNER: 1 'inner' results:
+// CHECK-INNER:      static int extracted() {
+// CHECK-INNER-NEXT: return 1 + 2 * 2;{{$}}
+// CHECK-INNER-NEXT: }{{[[:space:]].*}}
+// CHECK-INNER-NEXT: class AClass {
+
+// CHECK-OUTER: 1 'inner' results:
+// CHECK-OUTER:      static int extracted() {
+// CHECK-OUTER-NEXT: return 1 + 2 * 2;{{$}}
+// CHECK-OUTER-NEXT: }{{[[:space:]].*}}
+// CHECK-OUTER-NEXT: class OuterClass {
+
+  int otherMethod(int x);
+};
+
+#ifdef MULTIPLE
+};
+#endif
+
+int PREFIX AClass::otherMethod(int x) {
+  return /*range outofline=->+0:46*/2 * 2 - 1;
+}
+// CHECK: 1 'outofline' results:
+// CHECK:      static int extracted() {
+// CHECK-NEXT: return 2 * 2 - 1;{{$}}
+// CHECK-NEXT: }{{[[:space:]].*}}
+// CHECK-NEXT: int PREFIX AClass::otherMethod