head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.2
	netbsd-11-0-RC3:1.1.1.2
	netbsd-11-0-RC2:1.1.1.2
	netbsd-11-0-RC1:1.1.1.2
	perseant-exfatfs-base-20250801:1.1.1.2
	netbsd-11:1.1.1.2.0.10
	netbsd-11-base:1.1.1.2
	netbsd-10-1-RELEASE:1.1.1.2
	perseant-exfatfs-base-20240630:1.1.1.2
	perseant-exfatfs:1.1.1.2.0.8
	perseant-exfatfs-base:1.1.1.2
	netbsd-9-4-RELEASE:1.1.1.1
	netbsd-10-0-RELEASE:1.1.1.2
	netbsd-10-0-RC6:1.1.1.2
	netbsd-10-0-RC5:1.1.1.2
	netbsd-10-0-RC4:1.1.1.2
	netbsd-10-0-RC3:1.1.1.2
	netbsd-10-0-RC2:1.1.1.2
	netbsd-10-0-RC1:1.1.1.2
	netbsd-10:1.1.1.2.0.6
	netbsd-10-base:1.1.1.2
	netbsd-9-3-RELEASE:1.1.1.1
	cjep_sun2x:1.1.1.2.0.4
	cjep_sun2x-base:1.1.1.2
	cjep_staticlib_x-base1:1.1.1.2
	netbsd-9-2-RELEASE:1.1.1.1
	cjep_staticlib_x:1.1.1.2.0.2
	cjep_staticlib_x-base:1.1.1.2
	netbsd-9-1-RELEASE:1.1.1.1
	phil-wifi-20200421:1.1.1.2
	phil-wifi-20200411:1.1.1.2
	phil-wifi-20200406:1.1.1.2
	netbsd-9-0-RELEASE:1.1.1.1
	netbsd-9-0-RC2:1.1.1.1
	netbsd-9-0-RC1:1.1.1.1
	netbsd-9:1.1.1.1.0.6
	netbsd-9-base:1.1.1.1
	phil-wifi:1.1.1.1.0.4
	phil-wifi-20190609:1.1.1.1
	pgoyette-compat-merge-20190127:1.1.1.1.2.2
	pgoyette-compat-20190127:1.1.1.1
	pgoyette-compat-20190118:1.1.1.1
	pgoyette-compat-1226:1.1.1.1
	pgoyette-compat-1126:1.1.1.1
	pgoyette-compat-1020:1.1.1.1
	pgoyette-compat-0930:1.1.1.1
	pgoyette-compat-0906:1.1.1.1
	pgoyette-compat:1.1.1.1.0.2
	pgoyette-compat-0728:1.1.1.1
	clang-337282:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2018.07.17.18.31.14;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	wDzL46ALjrCZgwKA;

1.1.1.1
date	2018.07.17.18.31.14;	author joerg;	state Exp;
branches
	1.1.1.1.2.1
	1.1.1.1.4.1;
next	1.1.1.2;
commitid	wDzL46ALjrCZgwKA;

1.1.1.2
date	2019.11.13.22.19.30;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.1.2.1
date	2018.07.17.18.31.14;	author pgoyette;	state dead;
branches;
next	1.1.1.1.2.2;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.1.2.2
date	2018.07.28.04.33.25;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.1.4.1
date	2018.07.17.18.31.14;	author christos;	state dead;
branches;
next	1.1.1.1.4.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.1.4.2
date	2019.06.10.21.45.30;	author christos;	state Exp;
branches;
next	1.1.1.1.4.3;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.1.4.3
date	2020.04.13.07.46.40;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@//===--- Extract.cpp - Clang refactoring library --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implements the "extract" refactoring that can pull code into
/// new functions, methods or declare new variables.
///
//===----------------------------------------------------------------------===//

#include "clang/Tooling/Refactoring/Extract/Extract.h"
#include "SourceExtraction.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"

namespace clang {
namespace tooling {

namespace {

/// Returns true if \c E is a simple literal or a reference expression that
/// should not be extracted.
bool isSimpleExpression(const Expr *E) {
  if (!E)
    return false;
  switch (E->IgnoreParenCasts()->getStmtClass()) {
  case Stmt::DeclRefExprClass:
  case Stmt::PredefinedExprClass:
  case Stmt::IntegerLiteralClass:
  case Stmt::FloatingLiteralClass:
  case Stmt::ImaginaryLiteralClass:
  case Stmt::CharacterLiteralClass:
  case Stmt::StringLiteralClass:
    return true;
  default:
    return false;
  }
}

SourceLocation computeFunctionExtractionLocation(const Decl *D) {
  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();
}

} // end anonymous namespace

const RefactoringDescriptor &ExtractFunction::describe() {
  static const RefactoringDescriptor Descriptor = {
      "extract-function",
      "Extract Function",
      "(WIP action; use with caution!) Extracts code into a new function",
  };
  return Descriptor;
}

Expected<ExtractFunction>
ExtractFunction::initiate(RefactoringRuleContext &Context,
                          CodeRangeASTSelection Code,
                          Optional<std::string> DeclName) {
  // We would like to extract code out of functions/methods/blocks.
  // Prohibit extraction from things like global variable / field
  // initializers and other top-level expressions.
  if (!Code.isInFunctionLikeBodyOfCode())
    return Context.createDiagnosticError(
        diag::err_refactor_code_outside_of_function);

  if (Code.size() == 1) {
    // Avoid extraction of simple literals and references.
    if (isSimpleExpression(dyn_cast<Expr>(Code[0])))
      return Context.createDiagnosticError(
          diag::err_refactor_extract_simple_expression);

    // Property setters can't be extracted.
    if (const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(Code[0])) {
      if (!PRE->isMessagingGetter())
        return Context.createDiagnosticError(
            diag::err_refactor_extract_prohibited_expression);
    }
  }

  return ExtractFunction(std::move(Code), DeclName);
}

// FIXME: Support C++ method extraction.
// FIXME: Support Objective-C method extraction.
Expected<AtomicChanges>
ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) {
  const Decl *ParentDecl = Code.getFunctionLikeNearestParent();
  assert(ParentDecl && "missing parent");

  // Compute the source range of the code that should be extracted.
  SourceRange ExtractedRange(Code[0]->getLocStart(),
                             Code[Code.size() - 1]->getLocEnd());
  // FIXME (Alex L): Add code that accounts for macro locations.

  ASTContext &AST = Context.getASTContext();
  SourceManager &SM = AST.getSourceManager();
  const LangOptions &LangOpts = AST.getLangOpts();
  Rewriter ExtractedCodeRewriter(SM, LangOpts);

  // FIXME: Capture used variables.

  // Compute the return type.
  QualType ReturnType = AST.VoidTy;
  // FIXME (Alex L): Account for the return statement in extracted code.
  // FIXME (Alex L): Check for lexical expression instead.
  bool IsExpr = Code.size() == 1 && isa<Expr>(Code[0]);
  if (IsExpr) {
    // FIXME (Alex L): Get a more user-friendly type if needed.
    ReturnType = cast<Expr>(Code[0])->getType();
  }

  // FIXME: Rewrite the extracted code performing any required adjustments.

  // FIXME: Capture any field if necessary (method -> function extraction).

  // FIXME: Sort captured variables by name.

  // FIXME: Capture 'this' / 'self' if necessary.

  // FIXME: Compute the actual parameter types.

  // Compute the location of the extracted declaration.
  SourceLocation ExtractedDeclLocation =
      computeFunctionExtractionLocation(ParentDecl);
  // FIXME: Adjust the location to account for any preceding comments.

  // FIXME: Adjust with PP awareness like in Sema to get correct 'bool'
  // treatment.
  PrintingPolicy PP = AST.getPrintingPolicy();
  // FIXME: PP.UseStdFunctionForLambda = true;
  PP.SuppressStrongLifetime = true;
  PP.SuppressLifetimeQualifiers = true;
  PP.SuppressUnwrittenScope = true;

  ExtractionSemicolonPolicy Semicolons = ExtractionSemicolonPolicy::compute(
      Code[Code.size() - 1], ExtractedRange, SM, LangOpts);
  AtomicChange Change(SM, ExtractedDeclLocation);
  // Create the replacement for the extracted declaration.
  {
    std::string ExtractedCode;
    llvm::raw_string_ostream OS(ExtractedCode);
    // FIXME: Use 'inline' in header.
    OS << "static ";
    ReturnType.print(OS, PP, DeclName);
    OS << '(';
    // FIXME: Arguments.
    OS << ')';

    // Function body.
    OS << " {\n";
    if (IsExpr && !ReturnType->isVoidType())
      OS << "return ";
    OS << ExtractedCodeRewriter.getRewrittenText(ExtractedRange);
    if (Semicolons.isNeededInExtractedFunction())
      OS << ';';
    OS << "\n}\n\n";
    auto Err = Change.insert(SM, ExtractedDeclLocation, OS.str());
    if (Err)
      return std::move(Err);
  }

  // Create the replacement for the call to the extracted declaration.
  {
    std::string ReplacedCode;
    llvm::raw_string_ostream OS(ReplacedCode);

    OS << DeclName << '(';
    // FIXME: Forward arguments.
    OS << ')';
    if (Semicolons.isNeededInOriginalFunction())
      OS << ';';

    auto Err = Change.replace(
        SM, CharSourceRange::getTokenRange(ExtractedRange), OS.str());
    if (Err)
      return std::move(Err);
  }

  // FIXME: Add support for assocciated symbol location to AtomicChange to mark
  // the ranges of the name of the extracted declaration.
  return AtomicChanges{std::move(Change)};
}

} // end namespace tooling
} // end namespace clang
@


1.1.1.1
log
@Import clang r337282 from trunk
@
text
@@


1.1.1.2
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.1.4.1
log
@file Extract.cpp was added on branch phil-wifi on 2019-06-10 21:45:30 +0000
@
text
@d1 199
@


1.1.1.1.4.2
log
@Sync with HEAD
@
text
@a0 199
//===--- Extract.cpp - Clang refactoring library --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implements the "extract" refactoring that can pull code into
/// new functions, methods or declare new variables.
///
//===----------------------------------------------------------------------===//

#include "clang/Tooling/Refactoring/Extract/Extract.h"
#include "SourceExtraction.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"

namespace clang {
namespace tooling {

namespace {

/// Returns true if \c E is a simple literal or a reference expression that
/// should not be extracted.
bool isSimpleExpression(const Expr *E) {
  if (!E)
    return false;
  switch (E->IgnoreParenCasts()->getStmtClass()) {
  case Stmt::DeclRefExprClass:
  case Stmt::PredefinedExprClass:
  case Stmt::IntegerLiteralClass:
  case Stmt::FloatingLiteralClass:
  case Stmt::ImaginaryLiteralClass:
  case Stmt::CharacterLiteralClass:
  case Stmt::StringLiteralClass:
    return true;
  default:
    return false;
  }
}

SourceLocation computeFunctionExtractionLocation(const Decl *D) {
  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();
}

} // end anonymous namespace

const RefactoringDescriptor &ExtractFunction::describe() {
  static const RefactoringDescriptor Descriptor = {
      "extract-function",
      "Extract Function",
      "(WIP action; use with caution!) Extracts code into a new function",
  };
  return Descriptor;
}

Expected<ExtractFunction>
ExtractFunction::initiate(RefactoringRuleContext &Context,
                          CodeRangeASTSelection Code,
                          Optional<std::string> DeclName) {
  // We would like to extract code out of functions/methods/blocks.
  // Prohibit extraction from things like global variable / field
  // initializers and other top-level expressions.
  if (!Code.isInFunctionLikeBodyOfCode())
    return Context.createDiagnosticError(
        diag::err_refactor_code_outside_of_function);

  if (Code.size() == 1) {
    // Avoid extraction of simple literals and references.
    if (isSimpleExpression(dyn_cast<Expr>(Code[0])))
      return Context.createDiagnosticError(
          diag::err_refactor_extract_simple_expression);

    // Property setters can't be extracted.
    if (const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(Code[0])) {
      if (!PRE->isMessagingGetter())
        return Context.createDiagnosticError(
            diag::err_refactor_extract_prohibited_expression);
    }
  }

  return ExtractFunction(std::move(Code), DeclName);
}

// FIXME: Support C++ method extraction.
// FIXME: Support Objective-C method extraction.
Expected<AtomicChanges>
ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) {
  const Decl *ParentDecl = Code.getFunctionLikeNearestParent();
  assert(ParentDecl && "missing parent");

  // Compute the source range of the code that should be extracted.
  SourceRange ExtractedRange(Code[0]->getLocStart(),
                             Code[Code.size() - 1]->getLocEnd());
  // FIXME (Alex L): Add code that accounts for macro locations.

  ASTContext &AST = Context.getASTContext();
  SourceManager &SM = AST.getSourceManager();
  const LangOptions &LangOpts = AST.getLangOpts();
  Rewriter ExtractedCodeRewriter(SM, LangOpts);

  // FIXME: Capture used variables.

  // Compute the return type.
  QualType ReturnType = AST.VoidTy;
  // FIXME (Alex L): Account for the return statement in extracted code.
  // FIXME (Alex L): Check for lexical expression instead.
  bool IsExpr = Code.size() == 1 && isa<Expr>(Code[0]);
  if (IsExpr) {
    // FIXME (Alex L): Get a more user-friendly type if needed.
    ReturnType = cast<Expr>(Code[0])->getType();
  }

  // FIXME: Rewrite the extracted code performing any required adjustments.

  // FIXME: Capture any field if necessary (method -> function extraction).

  // FIXME: Sort captured variables by name.

  // FIXME: Capture 'this' / 'self' if necessary.

  // FIXME: Compute the actual parameter types.

  // Compute the location of the extracted declaration.
  SourceLocation ExtractedDeclLocation =
      computeFunctionExtractionLocation(ParentDecl);
  // FIXME: Adjust the location to account for any preceding comments.

  // FIXME: Adjust with PP awareness like in Sema to get correct 'bool'
  // treatment.
  PrintingPolicy PP = AST.getPrintingPolicy();
  // FIXME: PP.UseStdFunctionForLambda = true;
  PP.SuppressStrongLifetime = true;
  PP.SuppressLifetimeQualifiers = true;
  PP.SuppressUnwrittenScope = true;

  ExtractionSemicolonPolicy Semicolons = ExtractionSemicolonPolicy::compute(
      Code[Code.size() - 1], ExtractedRange, SM, LangOpts);
  AtomicChange Change(SM, ExtractedDeclLocation);
  // Create the replacement for the extracted declaration.
  {
    std::string ExtractedCode;
    llvm::raw_string_ostream OS(ExtractedCode);
    // FIXME: Use 'inline' in header.
    OS << "static ";
    ReturnType.print(OS, PP, DeclName);
    OS << '(';
    // FIXME: Arguments.
    OS << ')';

    // Function body.
    OS << " {\n";
    if (IsExpr && !ReturnType->isVoidType())
      OS << "return ";
    OS << ExtractedCodeRewriter.getRewrittenText(ExtractedRange);
    if (Semicolons.isNeededInExtractedFunction())
      OS << ';';
    OS << "\n}\n\n";
    auto Err = Change.insert(SM, ExtractedDeclLocation, OS.str());
    if (Err)
      return std::move(Err);
  }

  // Create the replacement for the call to the extracted declaration.
  {
    std::string ReplacedCode;
    llvm::raw_string_ostream OS(ReplacedCode);

    OS << DeclName << '(';
    // FIXME: Forward arguments.
    OS << ')';
    if (Semicolons.isNeededInOriginalFunction())
      OS << ';';

    auto Err = Change.replace(
        SM, CharSourceRange::getTokenRange(ExtractedRange), OS.str());
    if (Err)
      return std::move(Err);
  }

  // FIXME: Add support for assocciated symbol location to AtomicChange to mark
  // the ranges of the name of the extracted declaration.
  return AtomicChanges{std::move(Change)};
}

} // end namespace tooling
} // end namespace clang
@


1.1.1.1.4.3
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.1.2.1
log
@file Extract.cpp was added on branch pgoyette-compat on 2018-07-28 04:33:25 +0000
@
text
@d1 199
@


1.1.1.1.2.2
log
@Sync with HEAD
@
text
@a0 199
//===--- Extract.cpp - Clang refactoring library --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implements the "extract" refactoring that can pull code into
/// new functions, methods or declare new variables.
///
//===----------------------------------------------------------------------===//

#include "clang/Tooling/Refactoring/Extract/Extract.h"
#include "SourceExtraction.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"

namespace clang {
namespace tooling {

namespace {

/// Returns true if \c E is a simple literal or a reference expression that
/// should not be extracted.
bool isSimpleExpression(const Expr *E) {
  if (!E)
    return false;
  switch (E->IgnoreParenCasts()->getStmtClass()) {
  case Stmt::DeclRefExprClass:
  case Stmt::PredefinedExprClass:
  case Stmt::IntegerLiteralClass:
  case Stmt::FloatingLiteralClass:
  case Stmt::ImaginaryLiteralClass:
  case Stmt::CharacterLiteralClass:
  case Stmt::StringLiteralClass:
    return true;
  default:
    return false;
  }
}

SourceLocation computeFunctionExtractionLocation(const Decl *D) {
  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();
}

} // end anonymous namespace

const RefactoringDescriptor &ExtractFunction::describe() {
  static const RefactoringDescriptor Descriptor = {
      "extract-function",
      "Extract Function",
      "(WIP action; use with caution!) Extracts code into a new function",
  };
  return Descriptor;
}

Expected<ExtractFunction>
ExtractFunction::initiate(RefactoringRuleContext &Context,
                          CodeRangeASTSelection Code,
                          Optional<std::string> DeclName) {
  // We would like to extract code out of functions/methods/blocks.
  // Prohibit extraction from things like global variable / field
  // initializers and other top-level expressions.
  if (!Code.isInFunctionLikeBodyOfCode())
    return Context.createDiagnosticError(
        diag::err_refactor_code_outside_of_function);

  if (Code.size() == 1) {
    // Avoid extraction of simple literals and references.
    if (isSimpleExpression(dyn_cast<Expr>(Code[0])))
      return Context.createDiagnosticError(
          diag::err_refactor_extract_simple_expression);

    // Property setters can't be extracted.
    if (const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(Code[0])) {
      if (!PRE->isMessagingGetter())
        return Context.createDiagnosticError(
            diag::err_refactor_extract_prohibited_expression);
    }
  }

  return ExtractFunction(std::move(Code), DeclName);
}

// FIXME: Support C++ method extraction.
// FIXME: Support Objective-C method extraction.
Expected<AtomicChanges>
ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) {
  const Decl *ParentDecl = Code.getFunctionLikeNearestParent();
  assert(ParentDecl && "missing parent");

  // Compute the source range of the code that should be extracted.
  SourceRange ExtractedRange(Code[0]->getLocStart(),
                             Code[Code.size() - 1]->getLocEnd());
  // FIXME (Alex L): Add code that accounts for macro locations.

  ASTContext &AST = Context.getASTContext();
  SourceManager &SM = AST.getSourceManager();
  const LangOptions &LangOpts = AST.getLangOpts();
  Rewriter ExtractedCodeRewriter(SM, LangOpts);

  // FIXME: Capture used variables.

  // Compute the return type.
  QualType ReturnType = AST.VoidTy;
  // FIXME (Alex L): Account for the return statement in extracted code.
  // FIXME (Alex L): Check for lexical expression instead.
  bool IsExpr = Code.size() == 1 && isa<Expr>(Code[0]);
  if (IsExpr) {
    // FIXME (Alex L): Get a more user-friendly type if needed.
    ReturnType = cast<Expr>(Code[0])->getType();
  }

  // FIXME: Rewrite the extracted code performing any required adjustments.

  // FIXME: Capture any field if necessary (method -> function extraction).

  // FIXME: Sort captured variables by name.

  // FIXME: Capture 'this' / 'self' if necessary.

  // FIXME: Compute the actual parameter types.

  // Compute the location of the extracted declaration.
  SourceLocation ExtractedDeclLocation =
      computeFunctionExtractionLocation(ParentDecl);
  // FIXME: Adjust the location to account for any preceding comments.

  // FIXME: Adjust with PP awareness like in Sema to get correct 'bool'
  // treatment.
  PrintingPolicy PP = AST.getPrintingPolicy();
  // FIXME: PP.UseStdFunctionForLambda = true;
  PP.SuppressStrongLifetime = true;
  PP.SuppressLifetimeQualifiers = true;
  PP.SuppressUnwrittenScope = true;

  ExtractionSemicolonPolicy Semicolons = ExtractionSemicolonPolicy::compute(
      Code[Code.size() - 1], ExtractedRange, SM, LangOpts);
  AtomicChange Change(SM, ExtractedDeclLocation);
  // Create the replacement for the extracted declaration.
  {
    std::string ExtractedCode;
    llvm::raw_string_ostream OS(ExtractedCode);
    // FIXME: Use 'inline' in header.
    OS << "static ";
    ReturnType.print(OS, PP, DeclName);
    OS << '(';
    // FIXME: Arguments.
    OS << ')';

    // Function body.
    OS << " {\n";
    if (IsExpr && !ReturnType->isVoidType())
      OS << "return ";
    OS << ExtractedCodeRewriter.getRewrittenText(ExtractedRange);
    if (Semicolons.isNeededInExtractedFunction())
      OS << ';';
    OS << "\n}\n\n";
    auto Err = Change.insert(SM, ExtractedDeclLocation, OS.str());
    if (Err)
      return std::move(Err);
  }

  // Create the replacement for the call to the extracted declaration.
  {
    std::string ReplacedCode;
    llvm::raw_string_ostream OS(ReplacedCode);

    OS << DeclName << '(';
    // FIXME: Forward arguments.
    OS << ')';
    if (Semicolons.isNeededInOriginalFunction())
      OS << ';';

    auto Err = Change.replace(
        SM, CharSourceRange::getTokenRange(ExtractedRange), OS.str());
    if (Err)
      return std::move(Err);
  }

  // FIXME: Add support for assocciated symbol location to AtomicChange to mark
  // the ranges of the name of the extracted declaration.
  return AtomicChanges{std::move(Change)};
}

} // end namespace tooling
} // end namespace clang
@


