================ @@ -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:
I am not the most knowledgeable on this, but for example in DefineOutline.cpp next to this file there is a `getSelectedFunction()` function which seems to also "solve" the same problem (for `FunctionDecl`). I think we can do it the same way for `FunctionTemplateDecl` which I would prefer since it seems to be the desired way of checking for this (unless there is some reason as to why this does not work here). (Also not sure why in the comment of it they talked about not having a place where they can add a common header, what stops them from just adding one??) https://github.com/llvm/llvm-project/pull/74710 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
