blob: d54c49799e8211fc85a9b44f8d2e0a11613fa822 [file] [log] [blame]
//===--- RenamedSymbol.h - ---------------------------------*- C++ -*------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAMED_SYMBOL_H
#define LLVM_CLANG_TOOLING_REFACTOR_RENAMED_SYMBOL_H
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Tooling/Refactor/SymbolName.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSet.h"
namespace clang {
class NamedDecl;
namespace tooling {
namespace rename {
/// \brief A symbol that has to be renamed.
class Symbol {
public:
SymbolName Name;
/// The index of this symbol in a \c SymbolOperation.
unsigned SymbolIndex;
/// The declaration that was used to initiate a refactoring operation for this
/// symbol. May not be the most canonical declaration.
const NamedDecl *FoundDecl;
/// An optional Objective-C selector.
llvm::Optional<Selector> ObjCSelector;
Symbol(const NamedDecl *FoundDecl, unsigned SymbolIndex,
const LangOptions &LangOpts);
Symbol(Symbol &&) = default;
Symbol &operator=(Symbol &&) = default;
};
/// \brief An occurrence of a renamed symbol.
///
/// Provides information about an occurrence of symbol that helps renaming tools
/// determine if they can rename this symbol automatically and which source
/// ranges they have to replace.
///
/// A single occurrence of a symbol can span more than one source range to
/// account for things like Objective-C selectors.
// TODO: Rename
class SymbolOccurrence {
/// The source locations that correspond to the occurence of the symbol.
SmallVector<SourceLocation, 4> Locations;
public:
enum OccurrenceKind {
/// \brief This occurrence is an exact match and can be renamed
/// automatically.
MatchingSymbol,
/// \brief This is an occurrence of a matching selector. It can't be renamed
/// automatically unless the indexer proves that this selector refers only
/// to the declarations that correspond to the renamed symbol.
MatchingSelector,
/// \brief This is an occurrence of an implicit property that uses the
/// renamed method.
MatchingImplicitProperty,
/// \brief This is a textual occurrence of a symbol in a comment.
MatchingComment,
/// \brief This is a textual occurrence of a symbol in a doc comment.
MatchingDocComment,
/// \brief This is an occurrence of a symbol in an inclusion directive.
MatchingFilename
};
OccurrenceKind Kind;
/// Whether or not this occurrence is inside a macro. When this is true, the
/// locations of the occurrence contain just one location that points to
/// the location of the macro expansion.
bool IsMacroExpansion;
/// The index of the symbol stored in a \c SymbolOperation which matches this
/// occurrence.
unsigned SymbolIndex;
SymbolOccurrence()
: Kind(MatchingSymbol), IsMacroExpansion(false), SymbolIndex(0) {}
SymbolOccurrence(OccurrenceKind Kind, bool IsMacroExpansion,
unsigned SymbolIndex, ArrayRef<SourceLocation> Locations)
: Locations(Locations.begin(), Locations.end()), Kind(Kind),
IsMacroExpansion(IsMacroExpansion), SymbolIndex(SymbolIndex) {
assert(!Locations.empty() && "Renamed occurence without locations!");
}
SymbolOccurrence(SymbolOccurrence &&) = default;
SymbolOccurrence &operator=(SymbolOccurrence &&) = default;
ArrayRef<SourceLocation> locations() const {
if (Kind == MatchingImplicitProperty && Locations.size() == 2)
return llvm::makeArrayRef(Locations).drop_back();
return Locations;
}
/// Return the source range that corresponds to an individual source location
/// in this occurrence.
SourceRange getLocationRange(SourceLocation Loc, size_t OldNameSize) const {
SourceLocation EndLoc;
// Implicit property references might store the end as the second location
// to take into account the match for 'prop' when the old name is 'setProp'.
if (Kind == MatchingImplicitProperty && Locations.size() == 2) {
assert(Loc == Locations[0] && "invalid loc");
EndLoc = Locations[1];
} else
EndLoc = IsMacroExpansion ? Loc : Loc.getLocWithOffset(OldNameSize);
return SourceRange(Loc, EndLoc);
}
friend bool operator<(const SymbolOccurrence &LHS,
const SymbolOccurrence &RHS);
friend bool operator==(const SymbolOccurrence &LHS,
const SymbolOccurrence &RHS);
};
/// \brief Less-than operator between the two renamed symbol occurrences.
bool operator<(const SymbolOccurrence &LHS, const SymbolOccurrence &RHS);
/// \brief Equal-to operator between the two renamed symbol occurrences.
bool operator==(const SymbolOccurrence &LHS, const SymbolOccurrence &RHS);
} // end namespace rename
} // end namespace tooling
} // end namespace clang
#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAMED_SYMBOL_H