11#include "clang/AST/Type.h"
12#include "clang/AST/TypeLoc.h"
13#include "clang/Basic/LLVM.h"
14#include "llvm/Support/Error.h"
39class ExpandDeducedType :
public Tweak {
41 const char *id() const final;
42 llvm::StringLiteral kind()
const override {
45 bool prepare(
const Selection &Inputs)
override;
46 Expected<Effect> apply(
const Selection &Inputs)
override;
47 std::string title()
const override;
55std::string ExpandDeducedType::title()
const {
56 return "Replace with deduced type";
61bool isStructuredBindingType(
const SelectionTree::Node *N) {
63 while (N && N->ASTNode.get<TypeLoc>())
66 return N && N->ASTNode.get<DecompositionDecl>();
69bool isLambda(QualType QT) {
71 if (
const auto *RD = QT->getAsRecordDecl())
72 return RD->isLambda();
78bool isDeducedAsLambda(
const SelectionTree::Node *Node, SourceLocation
Loc) {
83 for (
const auto *It = Node; It; It = It->Parent) {
84 if (
const auto *DD = It->ASTNode.get<DeclaratorDecl>()) {
85 if (DD->getTypeSourceInfo() &&
86 DD->getTypeSourceInfo()->getTypeLoc().getBeginLoc() ==
Loc &&
87 isLambda(DD->getType()))
96bool isTemplateParam(
const SelectionTree::Node *Node) {
98 if (
Node->Parent->ASTNode.get<NonTypeTemplateParmDecl>())
103bool ExpandDeducedType::prepare(
const Selection &Inputs) {
104 if (
auto *Node = Inputs.ASTSelection.commonAncestor()) {
105 if (
auto *TypeNode =
Node->ASTNode.get<TypeLoc>()) {
106 if (
const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
107 if (!isStructuredBindingType(Node) &&
108 !isDeducedAsLambda(Node, Result.getBeginLoc()) &&
109 !isTemplateParam(Node))
110 Range = Result.getSourceRange();
112 if (
auto TTPAuto = TypeNode->getAs<TemplateTypeParmTypeLoc>()) {
117 if (TTPAuto.getDecl()->isImplicit() &&
118 !TTPAuto.getDecl()->hasTypeConstraint())
119 Range = TTPAuto.getSourceRange();
122 if (
auto DTTL = TypeNode->getAs<DecltypeTypeLoc>()) {
123 if (!isLambda(cast<DecltypeType>(DTTL.getType())->getUnderlyingType()))
124 Range = DTTL.getSourceRange();
129 return Range.isValid();
132Expected<Tweak::Effect> ExpandDeducedType::apply(
const Selection &Inputs) {
133 auto &SrcMgr = Inputs.AST->getSourceManager();
139 if (
DeducedType == std::nullopt || (*DeducedType)->isUndeducedAutoType())
140 return error(
"Could not deduce type for 'auto' type");
149 if ((*DeducedType)->isDependentType())
150 return error(
"Could not expand a dependent type");
157 std::string PrettyDeclarator =
printType(
158 *
DeducedType, Inputs.ASTSelection.commonAncestor()->getDeclContext(),
160 llvm::StringRef PrettyTypeName = PrettyDeclarator;
161 if (!PrettyTypeName.consume_back(
"DECLARATOR_ID"))
162 return error(
"Could not expand type that isn't a simple string");
163 PrettyTypeName = PrettyTypeName.rtrim();
165 tooling::Replacement Expansion(SrcMgr, CharSourceRange(Range,
true),
168 return Effect::mainFileEdit(SrcMgr, tooling::Replacements(Expansion));
CharSourceRange Range
SourceRange for the file name.
::clang::DynTypedNode Node
#define REGISTER_TWEAK(Subclass)
std::string printType(const QualType QT, const DeclContext &CurContext, const llvm::StringRef Placeholder)
Returns a QualType as string.
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
std::optional< QualType > getDeducedType(ASTContext &ASTCtx, SourceLocation Loc)
Retrieves the deduced type at a given location (auto, decltype).
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Some operations such as code completion produce a set of candidates.
static const llvm::StringLiteral REFACTOR_KIND