Index: include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h =================================================================== --- include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h +++ include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h @@ -63,15 +63,16 @@ Expected evaluate(RefactoringRuleContext &Context) const; }; -/// A selection requirement that is satisfied when a portion of code in a -/// declaration like function is selected using a non-empty source selection -/// (i.e. cursors won't be accepted). +/// A selection requirement that is satisfied when the selection range overlaps +/// with a number of neighbouring statements in the AST. The statemenst must be +/// contained in declaration like a function. The selection range must be a +/// non-empty source selection (i.e. cursors won't be accepted). /// /// The requirement will be evaluated only once during the initiation and search /// of matching refactoring action rules. /// /// \see CodeRangeASTSelection -class CodeRangeSelectionRequirement : public ASTSelectionRequirement { +class CodeRangeASTSelectionRequirement : public ASTSelectionRequirement { public: Expected evaluate(RefactoringRuleContext &Context) const; Index: include/clang/Tooling/Refactoring/RefactoringRuleContext.h =================================================================== --- include/clang/Tooling/Refactoring/RefactoringRuleContext.h +++ include/clang/Tooling/Refactoring/RefactoringRuleContext.h @@ -64,7 +64,7 @@ } void setASTSelection(std::unique_ptr Node) { - ASTSelection = std::move(Node); + ASTNodeSelection = std::move(Node); } private: @@ -81,7 +81,7 @@ PartialDiagnostic::StorageAllocator DiagStorage; // FIXME: Remove when memoized. - std::unique_ptr ASTSelection; + std::unique_ptr ASTNodeSelection; }; } // end namespace tooling Index: lib/Tooling/Refactoring/ASTSelection.cpp =================================================================== --- lib/Tooling/Refactoring/ASTSelection.cpp +++ lib/Tooling/Refactoring/ASTSelection.cpp @@ -337,6 +337,9 @@ bool CodeRangeASTSelection::isInFunctionLikeBodyOfCode() const { bool IsPrevCompound = false; + // Scan through the parents (bottom-to-top) and check if the selection is + // contained in a compound statement that's a body of a function/method + // declaration. for (const auto &Parent : llvm::reverse(Parents)) { const DynTypedNode &Node = Parent.get().Node; if (const auto *D = Node.get()) { Index: lib/Tooling/Refactoring/ASTSelectionRequirements.cpp =================================================================== --- lib/Tooling/Refactoring/ASTSelectionRequirements.cpp +++ lib/Tooling/Refactoring/ASTSelectionRequirements.cpp @@ -28,8 +28,8 @@ return std::move(*Selection); } -Expected -CodeRangeSelectionRequirement::evaluate(RefactoringRuleContext &Context) const { +Expected CodeRangeASTSelectionRequirement::evaluate( + RefactoringRuleContext &Context) const { // FIXME: Memoize so that selection is evaluated only once. Expected ASTSelection = ASTSelectionRequirement::evaluate(Context); Index: lib/Tooling/Refactoring/Extract.cpp =================================================================== --- lib/Tooling/Refactoring/Extract.cpp +++ lib/Tooling/Refactoring/Extract.cpp @@ -45,12 +45,12 @@ } class ExtractableCodeSelectionRequirement final - : public CodeRangeSelectionRequirement { + : public CodeRangeASTSelectionRequirement { public: Expected evaluate(RefactoringRuleContext &Context) const { Expected Selection = - CodeRangeSelectionRequirement::evaluate(Context); + CodeRangeASTSelectionRequirement::evaluate(Context); if (!Selection) return Selection.takeError(); CodeRangeASTSelection &Code = *Selection; @@ -207,7 +207,8 @@ StringRef getCommand() const override { return "extract"; } StringRef getDescription() const override { - return "Extracts code into a new function / method / variable"; + return "(WIP action; use with caution!) Extracts code into a new function " + "/ method / variable"; } /// Returns a set of refactoring actions rules that are defined by this Index: test/Refactor/Extract/ExtractExprIntoFunction.cpp =================================================================== --- test/Refactor/Extract/ExtractExprIntoFunction.cpp +++ test/Refactor/Extract/ExtractExprIntoFunction.cpp @@ -1,4 +1,4 @@ -// RUN: clang-refactor extract -selection=test:%s %s -- -std=c++11 2>&1 | FileCheck %s +// RUN: clang-refactor extract -selection=test:%s %s -- -std=c++11 2>&1 | grep -v CHECK | FileCheck %s void simpleExtractNoCaptures() { Index: test/Refactor/LocalRename/Field.cpp =================================================================== --- test/Refactor/LocalRename/Field.cpp +++ test/Refactor/LocalRename/Field.cpp @@ -1,4 +1,4 @@ -// RUN: clang-refactor local-rename -selection=test:%s -new-name=Bar %s -- | FileCheck %s +// RUN: clang-refactor local-rename -selection=test:%s -new-name=Bar %s -- | grep -v CHECK | FileCheck %s class Baz { int /*range=*/Foo; Index: test/Refactor/LocalRename/NoSymbolSelectedError.cpp =================================================================== --- test/Refactor/LocalRename/NoSymbolSelectedError.cpp +++ test/Refactor/LocalRename/NoSymbolSelectedError.cpp @@ -1,5 +1,5 @@ -// RUN: not clang-refactor local-rename -selection=%s:4:1 -new-name=Bar %s -- 2>&1 | FileCheck %s -// RUN: clang-refactor local-rename -selection=test:%s -new-name=Bar %s -- 2>&1 | FileCheck --check-prefix=TESTCHECK %s +// RUN: not clang-refactor local-rename -selection=%s:4:1 -new-name=Bar %s -- 2>&1 | grep -v CHECK | FileCheck %s +// RUN: clang-refactor local-rename -selection=test:%s -new-name=Bar %s -- 2>&1 | grep -v CHECK | FileCheck --check-prefix=TESTCHECK %s class Baz { // CHECK: [[@LINE]]:1: error: there is no symbol at the given location }; Index: tools/clang-refactor/TestSupport.cpp =================================================================== --- tools/clang-refactor/TestSupport.cpp +++ tools/clang-refactor/TestSupport.cpp @@ -102,14 +102,7 @@ llvm::errs() << toString(Result.takeError()); return true; } - auto Buf = llvm::MemoryBuffer::getMemBuffer(Result->c_str()); - for (llvm::line_iterator It(*Buf, /*SkipBlanks=*/false); !It.is_at_end(); - ++It) { - // Drop the 'CHECK' lines alltogether to avoid erroneous matches. - if (It->contains("CHECK")) - continue; - OS << *It << "\n"; - } + OS << *Result; } return false; }