================ @@ -0,0 +1,352 @@ +//===-- AbbreviateFunctionTemplate.cpp ---------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "XRefs.h" +#include "refactor/Tweak.h" +#include "support/Logger.h" +#include "clang/AST/ASTContext.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include <numeric> + +namespace clang { +namespace clangd { +namespace { +/// Converts a function template to its abbreviated form using auto parameters. +/// Before: +/// template <std::integral T> +/// auto foo(T param) { } +/// ^^^^^^^^^^^ +/// After: +/// auto foo(std::integral auto param) { } +class AbbreviateFunctionTemplate : public Tweak { +public: + const char *id() const final; + + bool prepare(const Selection &Inputs) override; + Expected<Effect> apply(const Selection &Inputs) override; + + std::string title() const override { + return llvm::formatv("Abbreviate function template"); + } + + llvm::StringLiteral kind() const override { + return CodeAction::REFACTOR_KIND; + } + +private: + static const char *AutoKeywordSpelling; + const FunctionTemplateDecl *FunctionTemplateDeclaration; + + struct TemplateParameterInfo { + const TypeConstraint *Constraint; + unsigned int FunctionParameterIndex; + llvm::SmallVector<tok::TokenKind> FunctionParameterQualifiers; + llvm::SmallVector<tok::TokenKind> FunctionParameterTypeQualifiers; + }; + + llvm::SmallVector<TemplateParameterInfo> TemplateParameterInfoList; + + bool traverseFunctionParameters(size_t NumberOfTemplateParameters); + + llvm::Expected<tooling::Replacements> + generateFunctionParameterReplacements(const ASTContext &Context); + + llvm::Expected<tooling::Replacement> generateFunctionParameterReplacement( + const TemplateParameterInfo &TemplateParameterInfo, + const ASTContext &Context); + + llvm::Expected<tooling::Replacement> + generateTemplateDeclarationReplacement(const ASTContext &Context); + + static std::tuple<QualType, llvm::SmallVector<tok::TokenKind>, + llvm::SmallVector<tok::TokenKind>> + deconstructType(QualType Type); +}; + +REGISTER_TWEAK(AbbreviateFunctionTemplate) + +const char *AbbreviateFunctionTemplate::AutoKeywordSpelling = + getKeywordSpelling(tok::kw_auto); + +template <typename T> +const T *findDeclaration(const SelectionTree::Node &Root) { + for (const auto *Node = &Root; Node; Node = Node->Parent) { + if (const T *Result = dyn_cast_or_null<T>(Node->ASTNode.get<Decl>())) + return Result; + } + + return nullptr; +} + +const char *getSpellingForQualifier(tok::TokenKind const &Qualifier) { + if (const auto *Spelling = getKeywordSpelling(Qualifier)) + return Spelling; + + if (const auto *Spelling = getPunctuatorSpelling(Qualifier)) + return Spelling; + + return nullptr; +} + +bool AbbreviateFunctionTemplate::prepare(const Selection &Inputs) { + const auto *CommonAncestor = Inputs.ASTSelection.commonAncestor(); + if (!CommonAncestor) + return false; + + FunctionTemplateDeclaration = + findDeclaration<FunctionTemplateDecl>(*CommonAncestor); ---------------- timon-ul wrote:
Yeah I think it is just time to make a header file in this folder, don't know why this hasn't benn done before but now's a good time to do so. https://github.com/llvm/llvm-project/pull/74710 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
