forked from OSchip/llvm-project
Refactor libTooling to reduce required dependencies.
This moves classes for storing and applying replacements to separate files. These classes specifically are used by clang-format which doesn't have any other dependencies on clangAST. Thereby, the size of clang-format's binary can be cut roughly in half and its build time sped up. llvm-svn: 220867
This commit is contained in:
parent
ce2164f45c
commit
cb3e6188bc
|
@ -0,0 +1,229 @@
|
|||
//===--- Replacement.h - Framework for clang refactoring tools --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Classes supporting refactorings that span multiple translation units.
|
||||
// While single translation unit refactorings are supported via the Rewriter,
|
||||
// when refactoring multiple translation units changes must be stored in a
|
||||
// SourceManager independent form, duplicate changes need to be removed, and
|
||||
// all changes must be applied at once at the end of the refactoring so that
|
||||
// the code is always parseable.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
|
||||
#define LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class Rewriter;
|
||||
|
||||
namespace tooling {
|
||||
|
||||
/// \brief A source range independent of the \c SourceManager.
|
||||
class Range {
|
||||
public:
|
||||
Range() : Offset(0), Length(0) {}
|
||||
Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {}
|
||||
|
||||
/// \brief Accessors.
|
||||
/// @{
|
||||
unsigned getOffset() const { return Offset; }
|
||||
unsigned getLength() const { return Length; }
|
||||
/// @}
|
||||
|
||||
/// \name Range Predicates
|
||||
/// @{
|
||||
/// \brief Whether this range overlaps with \p RHS or not.
|
||||
bool overlapsWith(Range RHS) const {
|
||||
return Offset + Length > RHS.Offset && Offset < RHS.Offset + RHS.Length;
|
||||
}
|
||||
|
||||
/// \brief Whether this range contains \p RHS or not.
|
||||
bool contains(Range RHS) const {
|
||||
return RHS.Offset >= Offset &&
|
||||
(RHS.Offset + RHS.Length) <= (Offset + Length);
|
||||
}
|
||||
/// @}
|
||||
|
||||
private:
|
||||
unsigned Offset;
|
||||
unsigned Length;
|
||||
};
|
||||
|
||||
/// \brief A text replacement.
|
||||
///
|
||||
/// Represents a SourceManager independent replacement of a range of text in a
|
||||
/// specific file.
|
||||
class Replacement {
|
||||
public:
|
||||
/// \brief Creates an invalid (not applicable) replacement.
|
||||
Replacement();
|
||||
|
||||
/// \brief Creates a replacement of the range [Offset, Offset+Length) in
|
||||
/// FilePath with ReplacementText.
|
||||
///
|
||||
/// \param FilePath A source file accessible via a SourceManager.
|
||||
/// \param Offset The byte offset of the start of the range in the file.
|
||||
/// \param Length The length of the range in bytes.
|
||||
Replacement(StringRef FilePath, unsigned Offset,
|
||||
unsigned Length, StringRef ReplacementText);
|
||||
|
||||
/// \brief Creates a Replacement of the range [Start, Start+Length) with
|
||||
/// ReplacementText.
|
||||
Replacement(const SourceManager &Sources, SourceLocation Start, unsigned Length,
|
||||
StringRef ReplacementText);
|
||||
|
||||
/// \brief Creates a Replacement of the given range with ReplacementText.
|
||||
Replacement(const SourceManager &Sources, const CharSourceRange &Range,
|
||||
StringRef ReplacementText);
|
||||
|
||||
/// \brief Creates a Replacement of the node with ReplacementText.
|
||||
template <typename Node>
|
||||
Replacement(const SourceManager &Sources, const Node &NodeToReplace,
|
||||
StringRef ReplacementText);
|
||||
|
||||
/// \brief Returns whether this replacement can be applied to a file.
|
||||
///
|
||||
/// Only replacements that are in a valid file can be applied.
|
||||
bool isApplicable() const;
|
||||
|
||||
/// \brief Accessors.
|
||||
/// @{
|
||||
StringRef getFilePath() const { return FilePath; }
|
||||
unsigned getOffset() const { return ReplacementRange.getOffset(); }
|
||||
unsigned getLength() const { return ReplacementRange.getLength(); }
|
||||
StringRef getReplacementText() const { return ReplacementText; }
|
||||
/// @}
|
||||
|
||||
/// \brief Applies the replacement on the Rewriter.
|
||||
bool apply(Rewriter &Rewrite) const;
|
||||
|
||||
/// \brief Returns a human readable string representation.
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
void setFromSourceLocation(const SourceManager &Sources, SourceLocation Start,
|
||||
unsigned Length, StringRef ReplacementText);
|
||||
void setFromSourceRange(const SourceManager &Sources,
|
||||
const CharSourceRange &Range,
|
||||
StringRef ReplacementText);
|
||||
|
||||
std::string FilePath;
|
||||
Range ReplacementRange;
|
||||
std::string ReplacementText;
|
||||
};
|
||||
|
||||
/// \brief Less-than operator between two Replacements.
|
||||
bool operator<(const Replacement &LHS, const Replacement &RHS);
|
||||
|
||||
/// \brief Equal-to operator between two Replacements.
|
||||
bool operator==(const Replacement &LHS, const Replacement &RHS);
|
||||
|
||||
/// \brief A set of Replacements.
|
||||
/// FIXME: Change to a vector and deduplicate in the RefactoringTool.
|
||||
typedef std::set<Replacement> Replacements;
|
||||
|
||||
/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
|
||||
///
|
||||
/// Replacement applications happen independently of the success of
|
||||
/// other applications.
|
||||
///
|
||||
/// \returns true if all replacements apply. false otherwise.
|
||||
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
|
||||
|
||||
/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
|
||||
///
|
||||
/// Replacement applications happen independently of the success of
|
||||
/// other applications.
|
||||
///
|
||||
/// \returns true if all replacements apply. false otherwise.
|
||||
bool applyAllReplacements(const std::vector<Replacement> &Replaces,
|
||||
Rewriter &Rewrite);
|
||||
|
||||
/// \brief Applies all replacements in \p Replaces to \p Code.
|
||||
///
|
||||
/// This completely ignores the path stored in each replacement. If one or more
|
||||
/// replacements cannot be applied, this returns an empty \c string.
|
||||
std::string applyAllReplacements(StringRef Code, const Replacements &Replaces);
|
||||
|
||||
/// \brief Calculates how a code \p Position is shifted when \p Replaces are
|
||||
/// applied.
|
||||
unsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position);
|
||||
|
||||
/// \brief Calculates how a code \p Position is shifted when \p Replaces are
|
||||
/// applied.
|
||||
///
|
||||
/// \pre Replaces[i].getOffset() <= Replaces[i+1].getOffset().
|
||||
unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
|
||||
unsigned Position);
|
||||
|
||||
/// \brief Removes duplicate Replacements and reports if Replacements conflict
|
||||
/// with one another. All Replacements are assumed to be in the same file.
|
||||
///
|
||||
/// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset().
|
||||
///
|
||||
/// This function sorts \p Replaces so that conflicts can be reported simply by
|
||||
/// offset into \p Replaces and number of elements in the conflict.
|
||||
void deduplicate(std::vector<Replacement> &Replaces,
|
||||
std::vector<Range> &Conflicts);
|
||||
|
||||
/// \brief Collection of Replacements generated from a single translation unit.
|
||||
struct TranslationUnitReplacements {
|
||||
/// Name of the main source for the translation unit.
|
||||
std::string MainSourceFile;
|
||||
|
||||
/// A freeform chunk of text to describe the context of the replacements.
|
||||
/// Will be printed, for example, when detecting conflicts during replacement
|
||||
/// deduplication.
|
||||
std::string Context;
|
||||
|
||||
std::vector<Replacement> Replacements;
|
||||
};
|
||||
|
||||
/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
|
||||
///
|
||||
/// Replacement applications happen independently of the success of
|
||||
/// other applications.
|
||||
///
|
||||
/// \returns true if all replacements apply. false otherwise.
|
||||
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
|
||||
|
||||
/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
|
||||
///
|
||||
/// Replacement applications happen independently of the success of
|
||||
/// other applications.
|
||||
///
|
||||
/// \returns true if all replacements apply. false otherwise.
|
||||
bool applyAllReplacements(const std::vector<Replacement> &Replaces,
|
||||
Rewriter &Rewrite);
|
||||
|
||||
/// \brief Applies all replacements in \p Replaces to \p Code.
|
||||
///
|
||||
/// This completely ignores the path stored in each replacement. If one or more
|
||||
/// replacements cannot be applied, this returns an empty \c string.
|
||||
std::string applyAllReplacements(StringRef Code, const Replacements &Replaces);
|
||||
|
||||
template <typename Node>
|
||||
Replacement::Replacement(const SourceManager &Sources,
|
||||
const Node &NodeToReplace, StringRef ReplacementText) {
|
||||
const CharSourceRange Range =
|
||||
CharSourceRange::getTokenRange(NodeToReplace->getSourceRange());
|
||||
setFromSourceRange(Sources, Range, ReplacementText);
|
||||
}
|
||||
|
||||
} // end namespace tooling
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
|
|
@ -19,180 +19,16 @@
|
|||
#ifndef LLVM_CLANG_TOOLING_REFACTORING_H
|
||||
#define LLVM_CLANG_TOOLING_REFACTORING_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Tooling/Core/Replacement.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class Rewriter;
|
||||
class SourceLocation;
|
||||
|
||||
namespace tooling {
|
||||
|
||||
/// \brief A source range independent of the \c SourceManager.
|
||||
class Range {
|
||||
public:
|
||||
Range() : Offset(0), Length(0) {}
|
||||
Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {}
|
||||
|
||||
/// \brief Accessors.
|
||||
/// @{
|
||||
unsigned getOffset() const { return Offset; }
|
||||
unsigned getLength() const { return Length; }
|
||||
/// @}
|
||||
|
||||
/// \name Range Predicates
|
||||
/// @{
|
||||
/// \brief Whether this range overlaps with \p RHS or not.
|
||||
bool overlapsWith(Range RHS) const {
|
||||
return Offset + Length > RHS.Offset && Offset < RHS.Offset + RHS.Length;
|
||||
}
|
||||
|
||||
/// \brief Whether this range contains \p RHS or not.
|
||||
bool contains(Range RHS) const {
|
||||
return RHS.Offset >= Offset &&
|
||||
(RHS.Offset + RHS.Length) <= (Offset + Length);
|
||||
}
|
||||
/// @}
|
||||
|
||||
private:
|
||||
unsigned Offset;
|
||||
unsigned Length;
|
||||
};
|
||||
|
||||
/// \brief A text replacement.
|
||||
///
|
||||
/// Represents a SourceManager independent replacement of a range of text in a
|
||||
/// specific file.
|
||||
class Replacement {
|
||||
public:
|
||||
/// \brief Creates an invalid (not applicable) replacement.
|
||||
Replacement();
|
||||
|
||||
/// \brief Creates a replacement of the range [Offset, Offset+Length) in
|
||||
/// FilePath with ReplacementText.
|
||||
///
|
||||
/// \param FilePath A source file accessible via a SourceManager.
|
||||
/// \param Offset The byte offset of the start of the range in the file.
|
||||
/// \param Length The length of the range in bytes.
|
||||
Replacement(StringRef FilePath, unsigned Offset,
|
||||
unsigned Length, StringRef ReplacementText);
|
||||
|
||||
/// \brief Creates a Replacement of the range [Start, Start+Length) with
|
||||
/// ReplacementText.
|
||||
Replacement(const SourceManager &Sources, SourceLocation Start, unsigned Length,
|
||||
StringRef ReplacementText);
|
||||
|
||||
/// \brief Creates a Replacement of the given range with ReplacementText.
|
||||
Replacement(const SourceManager &Sources, const CharSourceRange &Range,
|
||||
StringRef ReplacementText);
|
||||
|
||||
/// \brief Creates a Replacement of the node with ReplacementText.
|
||||
template <typename Node>
|
||||
Replacement(const SourceManager &Sources, const Node &NodeToReplace,
|
||||
StringRef ReplacementText);
|
||||
|
||||
/// \brief Returns whether this replacement can be applied to a file.
|
||||
///
|
||||
/// Only replacements that are in a valid file can be applied.
|
||||
bool isApplicable() const;
|
||||
|
||||
/// \brief Accessors.
|
||||
/// @{
|
||||
StringRef getFilePath() const { return FilePath; }
|
||||
unsigned getOffset() const { return ReplacementRange.getOffset(); }
|
||||
unsigned getLength() const { return ReplacementRange.getLength(); }
|
||||
StringRef getReplacementText() const { return ReplacementText; }
|
||||
/// @}
|
||||
|
||||
/// \brief Applies the replacement on the Rewriter.
|
||||
bool apply(Rewriter &Rewrite) const;
|
||||
|
||||
/// \brief Returns a human readable string representation.
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
void setFromSourceLocation(const SourceManager &Sources, SourceLocation Start,
|
||||
unsigned Length, StringRef ReplacementText);
|
||||
void setFromSourceRange(const SourceManager &Sources,
|
||||
const CharSourceRange &Range,
|
||||
StringRef ReplacementText);
|
||||
|
||||
std::string FilePath;
|
||||
Range ReplacementRange;
|
||||
std::string ReplacementText;
|
||||
};
|
||||
|
||||
/// \brief Less-than operator between two Replacements.
|
||||
bool operator<(const Replacement &LHS, const Replacement &RHS);
|
||||
|
||||
/// \brief Equal-to operator between two Replacements.
|
||||
bool operator==(const Replacement &LHS, const Replacement &RHS);
|
||||
|
||||
/// \brief A set of Replacements.
|
||||
/// FIXME: Change to a vector and deduplicate in the RefactoringTool.
|
||||
typedef std::set<Replacement> Replacements;
|
||||
|
||||
/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
|
||||
///
|
||||
/// Replacement applications happen independently of the success of
|
||||
/// other applications.
|
||||
///
|
||||
/// \returns true if all replacements apply. false otherwise.
|
||||
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
|
||||
|
||||
/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
|
||||
///
|
||||
/// Replacement applications happen independently of the success of
|
||||
/// other applications.
|
||||
///
|
||||
/// \returns true if all replacements apply. false otherwise.
|
||||
bool applyAllReplacements(const std::vector<Replacement> &Replaces,
|
||||
Rewriter &Rewrite);
|
||||
|
||||
/// \brief Applies all replacements in \p Replaces to \p Code.
|
||||
///
|
||||
/// This completely ignores the path stored in each replacement. If one or more
|
||||
/// replacements cannot be applied, this returns an empty \c string.
|
||||
std::string applyAllReplacements(StringRef Code, const Replacements &Replaces);
|
||||
|
||||
/// \brief Calculates how a code \p Position is shifted when \p Replaces are
|
||||
/// applied.
|
||||
unsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position);
|
||||
|
||||
/// \brief Calculates how a code \p Position is shifted when \p Replaces are
|
||||
/// applied.
|
||||
///
|
||||
/// \pre Replaces[i].getOffset() <= Replaces[i+1].getOffset().
|
||||
unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
|
||||
unsigned Position);
|
||||
|
||||
/// \brief Removes duplicate Replacements and reports if Replacements conflict
|
||||
/// with one another. All Replacements are assumed to be in the same file.
|
||||
///
|
||||
/// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset().
|
||||
///
|
||||
/// This function sorts \p Replaces so that conflicts can be reported simply by
|
||||
/// offset into \p Replaces and number of elements in the conflict.
|
||||
void deduplicate(std::vector<Replacement> &Replaces,
|
||||
std::vector<Range> &Conflicts);
|
||||
|
||||
/// \brief Collection of Replacements generated from a single translation unit.
|
||||
struct TranslationUnitReplacements {
|
||||
/// Name of the main source for the translation unit.
|
||||
std::string MainSourceFile;
|
||||
|
||||
/// A freeform chunk of text to describe the context of the replacements.
|
||||
/// Will be printed, for example, when detecting conflicts during replacement
|
||||
/// deduplication.
|
||||
std::string Context;
|
||||
|
||||
std::vector<Replacement> Replacements;
|
||||
};
|
||||
|
||||
/// \brief A tool to run refactorings.
|
||||
///
|
||||
/// This is a refactoring specific version of \see ClangTool. FrontendActions
|
||||
|
@ -230,14 +66,6 @@ private:
|
|||
Replacements Replace;
|
||||
};
|
||||
|
||||
template <typename Node>
|
||||
Replacement::Replacement(const SourceManager &Sources,
|
||||
const Node &NodeToReplace, StringRef ReplacementText) {
|
||||
const CharSourceRange Range =
|
||||
CharSourceRange::getTokenRange(NodeToReplace->getSourceRange());
|
||||
setFromSourceRange(Sources, Range, ReplacementText);
|
||||
}
|
||||
|
||||
} // end namespace tooling
|
||||
} // end namespace clang
|
||||
|
||||
|
|
|
@ -12,5 +12,5 @@ add_clang_library(clangFormat
|
|||
LINK_LIBS
|
||||
clangBasic
|
||||
clangLex
|
||||
clangTooling
|
||||
clangToolingCore
|
||||
)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
set(LLVM_LINK_COMPONENTS support)
|
||||
|
||||
add_subdirectory(Core)
|
||||
|
||||
add_clang_library(clangTooling
|
||||
ArgumentsAdjusters.cpp
|
||||
CommonOptionsParser.cpp
|
||||
|
@ -18,4 +20,5 @@ add_clang_library(clangTooling
|
|||
clangFrontend
|
||||
clangLex
|
||||
clangRewrite
|
||||
clangToolingCore
|
||||
)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
set(LLVM_LINK_COMPONENTS support)
|
||||
|
||||
add_clang_library(clangToolingCore
|
||||
Replacement.cpp
|
||||
|
||||
LINK_LIBS
|
||||
clangBasic
|
||||
clangDriver
|
||||
clangRewrite
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
##===- clang/lib/Tooling/Core/Makefile ---------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
CLANG_LEVEL := ../../..
|
||||
LIBRARYNAME := clangToolingCore
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
|
@ -0,0 +1,289 @@
|
|||
//===--- Replacement.cpp - Framework for clang refactoring tools ----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements classes to support/store refactorings.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/DiagnosticIDs.h"
|
||||
#include "clang/Basic/DiagnosticOptions.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
#include "clang/Rewrite/Core/Rewriter.h"
|
||||
#include "clang/Tooling/Core/Replacement.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_os_ostream.h"
|
||||
|
||||
namespace clang {
|
||||
namespace tooling {
|
||||
|
||||
static const char * const InvalidLocation = "";
|
||||
|
||||
Replacement::Replacement()
|
||||
: FilePath(InvalidLocation) {}
|
||||
|
||||
Replacement::Replacement(StringRef FilePath, unsigned Offset, unsigned Length,
|
||||
StringRef ReplacementText)
|
||||
: FilePath(FilePath), ReplacementRange(Offset, Length),
|
||||
ReplacementText(ReplacementText) {}
|
||||
|
||||
Replacement::Replacement(const SourceManager &Sources, SourceLocation Start,
|
||||
unsigned Length, StringRef ReplacementText) {
|
||||
setFromSourceLocation(Sources, Start, Length, ReplacementText);
|
||||
}
|
||||
|
||||
Replacement::Replacement(const SourceManager &Sources,
|
||||
const CharSourceRange &Range,
|
||||
StringRef ReplacementText) {
|
||||
setFromSourceRange(Sources, Range, ReplacementText);
|
||||
}
|
||||
|
||||
bool Replacement::isApplicable() const {
|
||||
return FilePath != InvalidLocation;
|
||||
}
|
||||
|
||||
bool Replacement::apply(Rewriter &Rewrite) const {
|
||||
SourceManager &SM = Rewrite.getSourceMgr();
|
||||
const FileEntry *Entry = SM.getFileManager().getFile(FilePath);
|
||||
if (!Entry)
|
||||
return false;
|
||||
FileID ID;
|
||||
// FIXME: Use SM.translateFile directly.
|
||||
SourceLocation Location = SM.translateFileLineCol(Entry, 1, 1);
|
||||
ID = Location.isValid() ?
|
||||
SM.getFileID(Location) :
|
||||
SM.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
|
||||
// FIXME: We cannot check whether Offset + Length is in the file, as
|
||||
// the remapping API is not public in the RewriteBuffer.
|
||||
const SourceLocation Start =
|
||||
SM.getLocForStartOfFile(ID).
|
||||
getLocWithOffset(ReplacementRange.getOffset());
|
||||
// ReplaceText returns false on success.
|
||||
// ReplaceText only fails if the source location is not a file location, in
|
||||
// which case we already returned false earlier.
|
||||
bool RewriteSucceeded = !Rewrite.ReplaceText(
|
||||
Start, ReplacementRange.getLength(), ReplacementText);
|
||||
assert(RewriteSucceeded);
|
||||
return RewriteSucceeded;
|
||||
}
|
||||
|
||||
std::string Replacement::toString() const {
|
||||
std::string result;
|
||||
llvm::raw_string_ostream stream(result);
|
||||
stream << FilePath << ": " << ReplacementRange.getOffset() << ":+"
|
||||
<< ReplacementRange.getLength() << ":\"" << ReplacementText << "\"";
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator<(const Replacement &LHS, const Replacement &RHS) {
|
||||
if (LHS.getOffset() != RHS.getOffset())
|
||||
return LHS.getOffset() < RHS.getOffset();
|
||||
if (LHS.getLength() != RHS.getLength())
|
||||
return LHS.getLength() < RHS.getLength();
|
||||
if (LHS.getFilePath() != RHS.getFilePath())
|
||||
return LHS.getFilePath() < RHS.getFilePath();
|
||||
return LHS.getReplacementText() < RHS.getReplacementText();
|
||||
}
|
||||
|
||||
bool operator==(const Replacement &LHS, const Replacement &RHS) {
|
||||
return LHS.getOffset() == RHS.getOffset() &&
|
||||
LHS.getLength() == RHS.getLength() &&
|
||||
LHS.getFilePath() == RHS.getFilePath() &&
|
||||
LHS.getReplacementText() == RHS.getReplacementText();
|
||||
}
|
||||
|
||||
void Replacement::setFromSourceLocation(const SourceManager &Sources,
|
||||
SourceLocation Start, unsigned Length,
|
||||
StringRef ReplacementText) {
|
||||
const std::pair<FileID, unsigned> DecomposedLocation =
|
||||
Sources.getDecomposedLoc(Start);
|
||||
const FileEntry *Entry = Sources.getFileEntryForID(DecomposedLocation.first);
|
||||
if (Entry) {
|
||||
// Make FilePath absolute so replacements can be applied correctly when
|
||||
// relative paths for files are used.
|
||||
llvm::SmallString<256> FilePath(Entry->getName());
|
||||
std::error_code EC = llvm::sys::fs::make_absolute(FilePath);
|
||||
this->FilePath = EC ? FilePath.c_str() : Entry->getName();
|
||||
} else {
|
||||
this->FilePath = InvalidLocation;
|
||||
}
|
||||
this->ReplacementRange = Range(DecomposedLocation.second, Length);
|
||||
this->ReplacementText = ReplacementText;
|
||||
}
|
||||
|
||||
// FIXME: This should go into the Lexer, but we need to figure out how
|
||||
// to handle ranges for refactoring in general first - there is no obvious
|
||||
// good way how to integrate this into the Lexer yet.
|
||||
static int getRangeSize(const SourceManager &Sources,
|
||||
const CharSourceRange &Range) {
|
||||
SourceLocation SpellingBegin = Sources.getSpellingLoc(Range.getBegin());
|
||||
SourceLocation SpellingEnd = Sources.getSpellingLoc(Range.getEnd());
|
||||
std::pair<FileID, unsigned> Start = Sources.getDecomposedLoc(SpellingBegin);
|
||||
std::pair<FileID, unsigned> End = Sources.getDecomposedLoc(SpellingEnd);
|
||||
if (Start.first != End.first) return -1;
|
||||
if (Range.isTokenRange())
|
||||
End.second += Lexer::MeasureTokenLength(SpellingEnd, Sources,
|
||||
LangOptions());
|
||||
return End.second - Start.second;
|
||||
}
|
||||
|
||||
void Replacement::setFromSourceRange(const SourceManager &Sources,
|
||||
const CharSourceRange &Range,
|
||||
StringRef ReplacementText) {
|
||||
setFromSourceLocation(Sources, Sources.getSpellingLoc(Range.getBegin()),
|
||||
getRangeSize(Sources, Range), ReplacementText);
|
||||
}
|
||||
|
||||
unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) {
|
||||
unsigned NewPosition = Position;
|
||||
for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E;
|
||||
++I) {
|
||||
if (I->getOffset() >= Position)
|
||||
break;
|
||||
if (I->getOffset() + I->getLength() > Position)
|
||||
NewPosition += I->getOffset() + I->getLength() - Position;
|
||||
NewPosition += I->getReplacementText().size() - I->getLength();
|
||||
}
|
||||
return NewPosition;
|
||||
}
|
||||
|
||||
// FIXME: Remove this function when Replacements is implemented as std::vector
|
||||
// instead of std::set.
|
||||
unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
|
||||
unsigned Position) {
|
||||
unsigned NewPosition = Position;
|
||||
for (std::vector<Replacement>::const_iterator I = Replaces.begin(),
|
||||
E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
if (I->getOffset() >= Position)
|
||||
break;
|
||||
if (I->getOffset() + I->getLength() > Position)
|
||||
NewPosition += I->getOffset() + I->getLength() - Position;
|
||||
NewPosition += I->getReplacementText().size() - I->getLength();
|
||||
}
|
||||
return NewPosition;
|
||||
}
|
||||
|
||||
void deduplicate(std::vector<Replacement> &Replaces,
|
||||
std::vector<Range> &Conflicts) {
|
||||
if (Replaces.empty())
|
||||
return;
|
||||
|
||||
auto LessNoPath = [](const Replacement &LHS, const Replacement &RHS) {
|
||||
if (LHS.getOffset() != RHS.getOffset())
|
||||
return LHS.getOffset() < RHS.getOffset();
|
||||
if (LHS.getLength() != RHS.getLength())
|
||||
return LHS.getLength() < RHS.getLength();
|
||||
return LHS.getReplacementText() < RHS.getReplacementText();
|
||||
};
|
||||
|
||||
auto EqualNoPath = [](const Replacement &LHS, const Replacement &RHS) {
|
||||
return LHS.getOffset() == RHS.getOffset() &&
|
||||
LHS.getLength() == RHS.getLength() &&
|
||||
LHS.getReplacementText() == RHS.getReplacementText();
|
||||
};
|
||||
|
||||
// Deduplicate. We don't want to deduplicate based on the path as we assume
|
||||
// that all replacements refer to the same file (or are symlinks).
|
||||
std::sort(Replaces.begin(), Replaces.end(), LessNoPath);
|
||||
Replaces.erase(std::unique(Replaces.begin(), Replaces.end(), EqualNoPath),
|
||||
Replaces.end());
|
||||
|
||||
// Detect conflicts
|
||||
Range ConflictRange(Replaces.front().getOffset(),
|
||||
Replaces.front().getLength());
|
||||
unsigned ConflictStart = 0;
|
||||
unsigned ConflictLength = 1;
|
||||
for (unsigned i = 1; i < Replaces.size(); ++i) {
|
||||
Range Current(Replaces[i].getOffset(), Replaces[i].getLength());
|
||||
if (ConflictRange.overlapsWith(Current)) {
|
||||
// Extend conflicted range
|
||||
ConflictRange = Range(ConflictRange.getOffset(),
|
||||
std::max(ConflictRange.getLength(),
|
||||
Current.getOffset() + Current.getLength() -
|
||||
ConflictRange.getOffset()));
|
||||
++ConflictLength;
|
||||
} else {
|
||||
if (ConflictLength > 1)
|
||||
Conflicts.push_back(Range(ConflictStart, ConflictLength));
|
||||
ConflictRange = Current;
|
||||
ConflictStart = i;
|
||||
ConflictLength = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConflictLength > 1)
|
||||
Conflicts.push_back(Range(ConflictStart, ConflictLength));
|
||||
}
|
||||
|
||||
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite) {
|
||||
bool Result = true;
|
||||
for (Replacements::const_iterator I = Replaces.begin(),
|
||||
E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
if (I->isApplicable()) {
|
||||
Result = I->apply(Rewrite) && Result;
|
||||
} else {
|
||||
Result = false;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
// FIXME: Remove this function when Replacements is implemented as std::vector
|
||||
// instead of std::set.
|
||||
bool applyAllReplacements(const std::vector<Replacement> &Replaces,
|
||||
Rewriter &Rewrite) {
|
||||
bool Result = true;
|
||||
for (std::vector<Replacement>::const_iterator I = Replaces.begin(),
|
||||
E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
if (I->isApplicable()) {
|
||||
Result = I->apply(Rewrite) && Result;
|
||||
} else {
|
||||
Result = false;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::string applyAllReplacements(StringRef Code, const Replacements &Replaces) {
|
||||
FileManager Files((FileSystemOptions()));
|
||||
DiagnosticsEngine Diagnostics(
|
||||
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
|
||||
new DiagnosticOptions);
|
||||
SourceManager SourceMgr(Diagnostics, Files);
|
||||
Rewriter Rewrite(SourceMgr, LangOptions());
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buf =
|
||||
llvm::MemoryBuffer::getMemBuffer(Code, "<stdin>");
|
||||
const clang::FileEntry *Entry =
|
||||
Files.getVirtualFile("<stdin>", Buf->getBufferSize(), 0);
|
||||
SourceMgr.overrideFileContents(Entry, std::move(Buf));
|
||||
FileID ID =
|
||||
SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
|
||||
for (Replacements::const_iterator I = Replaces.begin(), E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
Replacement Replace("<stdin>", I->getOffset(), I->getLength(),
|
||||
I->getReplacementText());
|
||||
if (!Replace.apply(Rewrite))
|
||||
return "";
|
||||
}
|
||||
std::string Result;
|
||||
llvm::raw_string_ostream OS(Result);
|
||||
Rewrite.getEditBuffer(ID).write(OS);
|
||||
OS.flush();
|
||||
return Result;
|
||||
}
|
||||
|
||||
} // end namespace tooling
|
||||
} // end namespace clang
|
||||
|
|
@ -9,5 +9,6 @@
|
|||
|
||||
CLANG_LEVEL := ../..
|
||||
LIBRARYNAME := clangTooling
|
||||
PARALLEL_DIRS := Core
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
|
|
@ -25,267 +25,6 @@
|
|||
namespace clang {
|
||||
namespace tooling {
|
||||
|
||||
static const char * const InvalidLocation = "";
|
||||
|
||||
Replacement::Replacement()
|
||||
: FilePath(InvalidLocation) {}
|
||||
|
||||
Replacement::Replacement(StringRef FilePath, unsigned Offset, unsigned Length,
|
||||
StringRef ReplacementText)
|
||||
: FilePath(FilePath), ReplacementRange(Offset, Length),
|
||||
ReplacementText(ReplacementText) {}
|
||||
|
||||
Replacement::Replacement(const SourceManager &Sources, SourceLocation Start,
|
||||
unsigned Length, StringRef ReplacementText) {
|
||||
setFromSourceLocation(Sources, Start, Length, ReplacementText);
|
||||
}
|
||||
|
||||
Replacement::Replacement(const SourceManager &Sources,
|
||||
const CharSourceRange &Range,
|
||||
StringRef ReplacementText) {
|
||||
setFromSourceRange(Sources, Range, ReplacementText);
|
||||
}
|
||||
|
||||
bool Replacement::isApplicable() const {
|
||||
return FilePath != InvalidLocation;
|
||||
}
|
||||
|
||||
bool Replacement::apply(Rewriter &Rewrite) const {
|
||||
SourceManager &SM = Rewrite.getSourceMgr();
|
||||
const FileEntry *Entry = SM.getFileManager().getFile(FilePath);
|
||||
if (!Entry)
|
||||
return false;
|
||||
FileID ID;
|
||||
// FIXME: Use SM.translateFile directly.
|
||||
SourceLocation Location = SM.translateFileLineCol(Entry, 1, 1);
|
||||
ID = Location.isValid() ?
|
||||
SM.getFileID(Location) :
|
||||
SM.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
|
||||
// FIXME: We cannot check whether Offset + Length is in the file, as
|
||||
// the remapping API is not public in the RewriteBuffer.
|
||||
const SourceLocation Start =
|
||||
SM.getLocForStartOfFile(ID).
|
||||
getLocWithOffset(ReplacementRange.getOffset());
|
||||
// ReplaceText returns false on success.
|
||||
// ReplaceText only fails if the source location is not a file location, in
|
||||
// which case we already returned false earlier.
|
||||
bool RewriteSucceeded = !Rewrite.ReplaceText(
|
||||
Start, ReplacementRange.getLength(), ReplacementText);
|
||||
assert(RewriteSucceeded);
|
||||
return RewriteSucceeded;
|
||||
}
|
||||
|
||||
std::string Replacement::toString() const {
|
||||
std::string result;
|
||||
llvm::raw_string_ostream stream(result);
|
||||
stream << FilePath << ": " << ReplacementRange.getOffset() << ":+"
|
||||
<< ReplacementRange.getLength() << ":\"" << ReplacementText << "\"";
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator<(const Replacement &LHS, const Replacement &RHS) {
|
||||
if (LHS.getOffset() != RHS.getOffset())
|
||||
return LHS.getOffset() < RHS.getOffset();
|
||||
if (LHS.getLength() != RHS.getLength())
|
||||
return LHS.getLength() < RHS.getLength();
|
||||
if (LHS.getFilePath() != RHS.getFilePath())
|
||||
return LHS.getFilePath() < RHS.getFilePath();
|
||||
return LHS.getReplacementText() < RHS.getReplacementText();
|
||||
}
|
||||
|
||||
bool operator==(const Replacement &LHS, const Replacement &RHS) {
|
||||
return LHS.getOffset() == RHS.getOffset() &&
|
||||
LHS.getLength() == RHS.getLength() &&
|
||||
LHS.getFilePath() == RHS.getFilePath() &&
|
||||
LHS.getReplacementText() == RHS.getReplacementText();
|
||||
}
|
||||
|
||||
void Replacement::setFromSourceLocation(const SourceManager &Sources,
|
||||
SourceLocation Start, unsigned Length,
|
||||
StringRef ReplacementText) {
|
||||
const std::pair<FileID, unsigned> DecomposedLocation =
|
||||
Sources.getDecomposedLoc(Start);
|
||||
const FileEntry *Entry = Sources.getFileEntryForID(DecomposedLocation.first);
|
||||
if (Entry) {
|
||||
// Make FilePath absolute so replacements can be applied correctly when
|
||||
// relative paths for files are used.
|
||||
llvm::SmallString<256> FilePath(Entry->getName());
|
||||
std::error_code EC = llvm::sys::fs::make_absolute(FilePath);
|
||||
this->FilePath = EC ? FilePath.c_str() : Entry->getName();
|
||||
} else {
|
||||
this->FilePath = InvalidLocation;
|
||||
}
|
||||
this->ReplacementRange = Range(DecomposedLocation.second, Length);
|
||||
this->ReplacementText = ReplacementText;
|
||||
}
|
||||
|
||||
// FIXME: This should go into the Lexer, but we need to figure out how
|
||||
// to handle ranges for refactoring in general first - there is no obvious
|
||||
// good way how to integrate this into the Lexer yet.
|
||||
static int getRangeSize(const SourceManager &Sources,
|
||||
const CharSourceRange &Range) {
|
||||
SourceLocation SpellingBegin = Sources.getSpellingLoc(Range.getBegin());
|
||||
SourceLocation SpellingEnd = Sources.getSpellingLoc(Range.getEnd());
|
||||
std::pair<FileID, unsigned> Start = Sources.getDecomposedLoc(SpellingBegin);
|
||||
std::pair<FileID, unsigned> End = Sources.getDecomposedLoc(SpellingEnd);
|
||||
if (Start.first != End.first) return -1;
|
||||
if (Range.isTokenRange())
|
||||
End.second += Lexer::MeasureTokenLength(SpellingEnd, Sources,
|
||||
LangOptions());
|
||||
return End.second - Start.second;
|
||||
}
|
||||
|
||||
void Replacement::setFromSourceRange(const SourceManager &Sources,
|
||||
const CharSourceRange &Range,
|
||||
StringRef ReplacementText) {
|
||||
setFromSourceLocation(Sources, Sources.getSpellingLoc(Range.getBegin()),
|
||||
getRangeSize(Sources, Range), ReplacementText);
|
||||
}
|
||||
|
||||
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite) {
|
||||
bool Result = true;
|
||||
for (Replacements::const_iterator I = Replaces.begin(),
|
||||
E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
if (I->isApplicable()) {
|
||||
Result = I->apply(Rewrite) && Result;
|
||||
} else {
|
||||
Result = false;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
// FIXME: Remove this function when Replacements is implemented as std::vector
|
||||
// instead of std::set.
|
||||
bool applyAllReplacements(const std::vector<Replacement> &Replaces,
|
||||
Rewriter &Rewrite) {
|
||||
bool Result = true;
|
||||
for (std::vector<Replacement>::const_iterator I = Replaces.begin(),
|
||||
E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
if (I->isApplicable()) {
|
||||
Result = I->apply(Rewrite) && Result;
|
||||
} else {
|
||||
Result = false;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::string applyAllReplacements(StringRef Code, const Replacements &Replaces) {
|
||||
FileManager Files((FileSystemOptions()));
|
||||
DiagnosticsEngine Diagnostics(
|
||||
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
|
||||
new DiagnosticOptions);
|
||||
Diagnostics.setClient(new TextDiagnosticPrinter(
|
||||
llvm::outs(), &Diagnostics.getDiagnosticOptions()));
|
||||
SourceManager SourceMgr(Diagnostics, Files);
|
||||
Rewriter Rewrite(SourceMgr, LangOptions());
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buf =
|
||||
llvm::MemoryBuffer::getMemBuffer(Code, "<stdin>");
|
||||
const clang::FileEntry *Entry =
|
||||
Files.getVirtualFile("<stdin>", Buf->getBufferSize(), 0);
|
||||
SourceMgr.overrideFileContents(Entry, std::move(Buf));
|
||||
FileID ID =
|
||||
SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
|
||||
for (Replacements::const_iterator I = Replaces.begin(), E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
Replacement Replace("<stdin>", I->getOffset(), I->getLength(),
|
||||
I->getReplacementText());
|
||||
if (!Replace.apply(Rewrite))
|
||||
return "";
|
||||
}
|
||||
std::string Result;
|
||||
llvm::raw_string_ostream OS(Result);
|
||||
Rewrite.getEditBuffer(ID).write(OS);
|
||||
OS.flush();
|
||||
return Result;
|
||||
}
|
||||
|
||||
unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) {
|
||||
unsigned NewPosition = Position;
|
||||
for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E;
|
||||
++I) {
|
||||
if (I->getOffset() >= Position)
|
||||
break;
|
||||
if (I->getOffset() + I->getLength() > Position)
|
||||
NewPosition += I->getOffset() + I->getLength() - Position;
|
||||
NewPosition += I->getReplacementText().size() - I->getLength();
|
||||
}
|
||||
return NewPosition;
|
||||
}
|
||||
|
||||
// FIXME: Remove this function when Replacements is implemented as std::vector
|
||||
// instead of std::set.
|
||||
unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
|
||||
unsigned Position) {
|
||||
unsigned NewPosition = Position;
|
||||
for (std::vector<Replacement>::const_iterator I = Replaces.begin(),
|
||||
E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
if (I->getOffset() >= Position)
|
||||
break;
|
||||
if (I->getOffset() + I->getLength() > Position)
|
||||
NewPosition += I->getOffset() + I->getLength() - Position;
|
||||
NewPosition += I->getReplacementText().size() - I->getLength();
|
||||
}
|
||||
return NewPosition;
|
||||
}
|
||||
|
||||
void deduplicate(std::vector<Replacement> &Replaces,
|
||||
std::vector<Range> &Conflicts) {
|
||||
if (Replaces.empty())
|
||||
return;
|
||||
|
||||
auto LessNoPath = [](const Replacement &LHS, const Replacement &RHS) {
|
||||
if (LHS.getOffset() != RHS.getOffset())
|
||||
return LHS.getOffset() < RHS.getOffset();
|
||||
if (LHS.getLength() != RHS.getLength())
|
||||
return LHS.getLength() < RHS.getLength();
|
||||
return LHS.getReplacementText() < RHS.getReplacementText();
|
||||
};
|
||||
|
||||
auto EqualNoPath = [](const Replacement &LHS, const Replacement &RHS) {
|
||||
return LHS.getOffset() == RHS.getOffset() &&
|
||||
LHS.getLength() == RHS.getLength() &&
|
||||
LHS.getReplacementText() == RHS.getReplacementText();
|
||||
};
|
||||
|
||||
// Deduplicate. We don't want to deduplicate based on the path as we assume
|
||||
// that all replacements refer to the same file (or are symlinks).
|
||||
std::sort(Replaces.begin(), Replaces.end(), LessNoPath);
|
||||
Replaces.erase(std::unique(Replaces.begin(), Replaces.end(), EqualNoPath),
|
||||
Replaces.end());
|
||||
|
||||
// Detect conflicts
|
||||
Range ConflictRange(Replaces.front().getOffset(),
|
||||
Replaces.front().getLength());
|
||||
unsigned ConflictStart = 0;
|
||||
unsigned ConflictLength = 1;
|
||||
for (unsigned i = 1; i < Replaces.size(); ++i) {
|
||||
Range Current(Replaces[i].getOffset(), Replaces[i].getLength());
|
||||
if (ConflictRange.overlapsWith(Current)) {
|
||||
// Extend conflicted range
|
||||
ConflictRange = Range(ConflictRange.getOffset(),
|
||||
std::max(ConflictRange.getLength(),
|
||||
Current.getOffset() + Current.getLength() -
|
||||
ConflictRange.getOffset()));
|
||||
++ConflictLength;
|
||||
} else {
|
||||
if (ConflictLength > 1)
|
||||
Conflicts.push_back(Range(ConflictStart, ConflictLength));
|
||||
ConflictRange = Current;
|
||||
ConflictStart = i;
|
||||
ConflictLength = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConflictLength > 1)
|
||||
Conflicts.push_back(Range(ConflictStart, ConflictLength));
|
||||
}
|
||||
|
||||
|
||||
RefactoringTool::RefactoringTool(const CompilationDatabase &Compilations,
|
||||
ArrayRef<std::string> SourcePaths)
|
||||
: ClangTool(Compilations, SourcePaths) {}
|
||||
|
|
|
@ -9,7 +9,6 @@ target_link_libraries(clang-format
|
|||
clangFormat
|
||||
clangLex
|
||||
clangRewrite
|
||||
clangTooling
|
||||
)
|
||||
|
||||
install(TARGETS clang-format RUNTIME DESTINATION bin)
|
||||
|
|
|
@ -16,9 +16,7 @@ TOOL_NO_EXPORTS = 1
|
|||
|
||||
include $(CLANG_LEVEL)/../../Makefile.config
|
||||
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
|
||||
USEDLIBS = clangFormat.a clangTooling.a clangFrontend.a clangSerialization.a \
|
||||
clangDriver.a clangParse.a clangSema.a clangAnalysis.a \
|
||||
clangRewriteFrontend.a clangRewrite.a clangEdit.a clangAST.a \
|
||||
USEDLIBS = clangFormat.a clangToolingCore.a clangDriver.a clangRewrite.a \
|
||||
clangLex.a clangBasic.a
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
|
|
@ -20,7 +20,7 @@ LINK_COMPONENTS := AsmParser BitReader Core MC MCParser Option Support
|
|||
USEDLIBS = clangIndex.a clangARCMigrate.a \
|
||||
clangRewriteFrontend.a \
|
||||
clangFormat.a \
|
||||
clangTooling.a \
|
||||
clangTooling.a clangToolingCore.a \
|
||||
clangFrontend.a clangDriver.a \
|
||||
clangSerialization.a \
|
||||
clangParse.a clangSema.a \
|
||||
|
|
|
@ -11,5 +11,5 @@ add_clang_unittest(FormatTests
|
|||
|
||||
target_link_libraries(FormatTests
|
||||
clangFormat
|
||||
clangTooling
|
||||
clangToolingCore
|
||||
)
|
||||
|
|
|
@ -11,8 +11,8 @@ CLANG_LEVEL = ../..
|
|||
TESTNAME = Format
|
||||
include $(CLANG_LEVEL)/../../Makefile.config
|
||||
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
|
||||
USEDLIBS = clangFormat.a clangTooling.a clangFrontend.a clangSerialization.a \
|
||||
clangDriver.a clangParse.a clangRewrite.a \
|
||||
USEDLIBS = clangFormat.a clangTooling.a clangToolingCore.a clangFrontend.a \
|
||||
clangSerialization.a clangDriver.a clangParse.a clangRewrite.a \
|
||||
clangRewriteFrontend.a clangSema.a clangAnalysis.a clangEdit.a \
|
||||
clangAST.a clangASTMatchers.a clangLex.a clangBasic.a
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ CLANG_LEVEL = ../..
|
|||
TESTNAME = Tooling
|
||||
include $(CLANG_LEVEL)/../../Makefile.config
|
||||
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
|
||||
USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
|
||||
USEDLIBS = clangTooling.a clangToolingCore.a clangFrontend.a \
|
||||
clangSerialization.a clangDriver.a \
|
||||
clangParse.a clangRewrite.a clangRewriteFrontend.a \
|
||||
clangSema.a clangAnalysis.a clangEdit.a \
|
||||
clangAST.a clangASTMatchers.a clangLex.a clangBasic.a
|
||||
|
|
Loading…
Reference in New Issue