11#include "clang/AST/DeclTemplate.h"
12#include "clang/AST/Type.h"
13#include "clang/AST/TypeLoc.h"
14#include "clang/Basic/LLVM.h"
15#include "llvm/Support/Error.h"
40class ExpandDeducedType :
public Tweak {
42 const char *id() const final;
43 llvm::StringLiteral kind()
const override {
46 bool prepare(
const Selection &Inputs)
override;
47 Expected<Effect> apply(
const Selection &Inputs)
override;
48 std::string title()
const override;
56std::string ExpandDeducedType::title()
const {
57 return "Replace with deduced type";
62bool isStructuredBindingType(
const SelectionTree::Node *N) {
64 while (N && N->ASTNode.get<TypeLoc>())
67 return N && N->ASTNode.get<DecompositionDecl>();
70bool isLambda(QualType QT) {
72 if (
const auto *RD = QT->getAsRecordDecl())
73 return RD->isLambda();
79bool isDeducedAsLambda(
const SelectionTree::Node *Node, SourceLocation Loc) {
84 for (
const auto *It = Node; It; It = It->Parent) {
85 if (
const auto *DD = It->ASTNode.get<DeclaratorDecl>()) {
86 if (DD->getTypeSourceInfo() &&
87 DD->getTypeSourceInfo()->getTypeLoc().getBeginLoc() == Loc &&
88 isLambda(DD->getType()))
97bool isTemplateParam(
const SelectionTree::Node *Node) {
99 if (Node->Parent->ASTNode.get<NonTypeTemplateParmDecl>())
104bool ExpandDeducedType::prepare(
const Selection &Inputs) {
105 if (
auto *Node = Inputs.ASTSelection.commonAncestor()) {
106 if (
auto *TypeNode = Node->ASTNode.get<TypeLoc>()) {
107 if (
const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
108 if (!isStructuredBindingType(Node) &&
109 !isDeducedAsLambda(Node, Result.getBeginLoc()) &&
110 !isTemplateParam(Node))
111 Range = Result.getSourceRange();
113 if (
auto TTPAuto = TypeNode->getAs<TemplateTypeParmTypeLoc>()) {
118 if (TTPAuto.getDecl()->isImplicit() &&
119 !TTPAuto.getDecl()->hasTypeConstraint())
120 Range = TTPAuto.getSourceRange();
123 if (
auto DTTL = TypeNode->getAs<DecltypeTypeLoc>()) {
124 if (!isLambda(cast<DecltypeType>(DTTL.getType())->getUnderlyingType()))
125 Range = DTTL.getSourceRange();
130 return Range.isValid();
133Expected<Tweak::Effect> ExpandDeducedType::apply(
const Selection &Inputs) {
134 auto &SrcMgr = Inputs.AST->getSourceManager();
136 std::optional<clang::QualType> DeducedType =
138 Inputs.AST->getHeuristicResolver(), Range.getBegin());
141 if (DeducedType == std::nullopt || (*DeducedType)->isUndeducedAutoType())
142 return error(
"Could not deduce type for 'auto' type");
151 if ((*DeducedType)->isDependentType())
152 return error(
"Could not expand a dependent type");
159 std::string PrettyDeclarator =
printType(
160 *DeducedType, Inputs.ASTSelection.commonAncestor()->getDeclContext(),
162 llvm::StringRef PrettyTypeName = PrettyDeclarator;
163 if (!PrettyTypeName.consume_back(
"DECLARATOR_ID"))
164 return error(
"Could not expand type that isn't a simple string");
165 PrettyTypeName = PrettyTypeName.rtrim();
167 tooling::Replacement Expansion(SrcMgr, CharSourceRange(Range,
true),
170 return Effect::mainFileEdit(SrcMgr, tooling::Replacements(Expansion));
#define REGISTER_TWEAK(Subclass)
An interface base for small context-sensitive refactoring actions.
llvm::Error error(std::error_code, std::string &&)
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
std::string printType(const QualType QT, const DeclContext &CurContext, const llvm::StringRef Placeholder, bool FullyQualify)
Returns a QualType as string.
std::optional< QualType > getDeducedType(ASTContext &ASTCtx, const HeuristicResolver *Resolver, SourceLocation Loc)
Retrieves the deduced type at a given location (auto, decltype).
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static const llvm::StringLiteral REFACTOR_KIND