[clang-tools-extra] [clangd] Add tweak to abbreviate function templates (PR #74710)
https://github.com/jeremystucki created https://github.com/llvm/llvm-project/pull/74710 # Description This introduces a new refactoring for function templates. It converts them to their abbreviated form using auto parameters. Here is an example of what it does: **Before** ```cpp template void foo(T, U, V... params); ``` **After** ```cpp void foo(auto, std::integral auto, auto... params); ``` # Demo [Screencast from 2023-12-07 10-44-46.webm](https://github.com/sa-concept-refactoring/llvm-project/assets/7629727/8d5f2bf1-03ce-4644-9311-1b3942594adc) >From b0507f05e5b2fa4d840757b8d7fce1b60df626ec Mon Sep 17 00:00:00 2001 From: Jeremy Stucki Date: Fri, 27 Oct 2023 16:33:13 +0200 Subject: [PATCH] [clangd] Add tweak to abbreviate function templates Co-authored-by: Vina Zahnd --- .../tweaks/AbbreviateFunctionTemplate.cpp | 352 ++ .../clangd/refactor/tweaks/CMakeLists.txt | 1 + .../clangd/unittests/CMakeLists.txt | 1 + .../AbbreviateFunctionTemplateTests.cpp | 76 clang-tools-extra/docs/ReleaseNotes.rst | 3 + 5 files changed, 433 insertions(+) create mode 100644 clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp create mode 100644 clang-tools-extra/clangd/unittests/tweaks/AbbreviateFunctionTemplateTests.cpp diff --git a/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp b/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp new file mode 100644 index 0..a2cfc6e13b01f --- /dev/null +++ b/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp @@ -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 "FindTarget.h" +#include "SourceCode.h" +#include "XRefs.h" +#include "refactor/Tweak.h" +#include "support/Logger.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExprConcepts.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" +#include + +namespace clang { +namespace clangd { +namespace { +/// Converts a function template to its abbreviated form using auto parameters. +/// Before: +/// template +/// auto foo(T param) { } +/// ^^^ +/// After: +/// auto foo(std::integral auto param) { } +class AbbreviateFunctionTemplate : public Tweak { +public: + const char *id() const final; + + auto prepare(const Selection &Inputs) -> bool override; + auto apply(const Selection &Inputs) -> Expected override; + + auto title() const -> std::string override { +return llvm::formatv("Abbreviate function template"); + } + + auto kind() const -> llvm::StringLiteral override { +return CodeAction::REFACTOR_KIND; + } + +private: + static const char *AutoKeywordSpelling; + const FunctionTemplateDecl *FunctionTemplateDeclaration; + + struct TemplateParameterInfo { +const TypeConstraint *Constraint; +unsigned int FunctionParameterIndex; +std::vector FunctionParameterQualifiers; +std::vector FunctionParameterTypeQualifiers; + }; + + std::vector TemplateParameterInfoList; + + auto traverseFunctionParameters(size_t NumberOfTemplateParameters) -> bool; + + auto generateFunctionParameterReplacements(const ASTContext &Context) + -> llvm::Expected; + + auto generateFunctionParameterReplacement( + const TemplateParameterInfo &TemplateParameterInfo, + const ASTContext &Context) -> llvm::Expected; + + auto generateTemplateDeclarationReplacement(const ASTContext &Context) + -> llvm::Expected; + + static auto deconstructType(QualType Type) + -> std::tuple, +std::vector>; +}; + +REGISTER_TWEAK(AbbreviateFunctionTemplate) + +const char *AbbreviateFunctionTemplate::AutoKeywordSpelling = +getKeywordSpelling(tok::kw_auto); + +template +auto findDeclaration(const SelectionTree::Node &Root) -> const T * { + for (const auto *Node = &Root; Node; Node = Node->Parent) { +if (const T *Result = dyn_cast_or_null(Node->ASTNode.get())) + return Result; + } + + return nullptr; +} + +auto getSpellingForQualifier(tok::TokenKind const &Qualifier) -> const char * { + 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(*CommonAncestor); + + if (!Function
[clang-tools-extra] [clangd] Add tweak to abbreviate function templates (PR #74710)
https://github.com/jeremystucki updated https://github.com/llvm/llvm-project/pull/74710 >From b3ae4235ccca0b2c859b33f7d12ee7940daabd1a Mon Sep 17 00:00:00 2001 From: Jeremy Stucki Date: Fri, 27 Oct 2023 16:33:13 +0200 Subject: [PATCH] [clangd] Add tweak to abbreviate function templates Co-authored-by: Vina Zahnd --- .../tweaks/AbbreviateFunctionTemplate.cpp | 352 ++ .../clangd/refactor/tweaks/CMakeLists.txt | 1 + .../clangd/unittests/CMakeLists.txt | 1 + .../AbbreviateFunctionTemplateTests.cpp | 76 clang-tools-extra/docs/ReleaseNotes.rst | 3 + 5 files changed, 433 insertions(+) create mode 100644 clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp create mode 100644 clang-tools-extra/clangd/unittests/tweaks/AbbreviateFunctionTemplateTests.cpp diff --git a/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp b/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp new file mode 100644 index 0..a2cfc6e13b01f --- /dev/null +++ b/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp @@ -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 "FindTarget.h" +#include "SourceCode.h" +#include "XRefs.h" +#include "refactor/Tweak.h" +#include "support/Logger.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExprConcepts.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" +#include + +namespace clang { +namespace clangd { +namespace { +/// Converts a function template to its abbreviated form using auto parameters. +/// Before: +/// template +/// auto foo(T param) { } +/// ^^^ +/// After: +/// auto foo(std::integral auto param) { } +class AbbreviateFunctionTemplate : public Tweak { +public: + const char *id() const final; + + auto prepare(const Selection &Inputs) -> bool override; + auto apply(const Selection &Inputs) -> Expected override; + + auto title() const -> std::string override { +return llvm::formatv("Abbreviate function template"); + } + + auto kind() const -> llvm::StringLiteral override { +return CodeAction::REFACTOR_KIND; + } + +private: + static const char *AutoKeywordSpelling; + const FunctionTemplateDecl *FunctionTemplateDeclaration; + + struct TemplateParameterInfo { +const TypeConstraint *Constraint; +unsigned int FunctionParameterIndex; +std::vector FunctionParameterQualifiers; +std::vector FunctionParameterTypeQualifiers; + }; + + std::vector TemplateParameterInfoList; + + auto traverseFunctionParameters(size_t NumberOfTemplateParameters) -> bool; + + auto generateFunctionParameterReplacements(const ASTContext &Context) + -> llvm::Expected; + + auto generateFunctionParameterReplacement( + const TemplateParameterInfo &TemplateParameterInfo, + const ASTContext &Context) -> llvm::Expected; + + auto generateTemplateDeclarationReplacement(const ASTContext &Context) + -> llvm::Expected; + + static auto deconstructType(QualType Type) + -> std::tuple, +std::vector>; +}; + +REGISTER_TWEAK(AbbreviateFunctionTemplate) + +const char *AbbreviateFunctionTemplate::AutoKeywordSpelling = +getKeywordSpelling(tok::kw_auto); + +template +auto findDeclaration(const SelectionTree::Node &Root) -> const T * { + for (const auto *Node = &Root; Node; Node = Node->Parent) { +if (const T *Result = dyn_cast_or_null(Node->ASTNode.get())) + return Result; + } + + return nullptr; +} + +auto getSpellingForQualifier(tok::TokenKind const &Qualifier) -> const char * { + 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(*CommonAncestor); + + if (!FunctionTemplateDeclaration) +return false; + + auto *TemplateParameters = + FunctionTemplateDeclaration->getTemplateParameters(); + + auto NumberOfTemplateParameters = TemplateParameters->size(); + TemplateParameterInfoList = + std::vector(NumberOfTemplateParameters); + + // Check how many times each template parameter is referenced. + // Depending on the number of references it can be checked + // if the refactoring is possible: + // - exactly one: The tem
[clang-tools-extra] [clangd] Add tweak to abbreviate function templates (PR #74710)
https://github.com/jeremystucki updated https://github.com/llvm/llvm-project/pull/74710 >From b0b22b716bfc60274814cedc82c237d13477869c Mon Sep 17 00:00:00 2001 From: Jeremy Stucki Date: Fri, 27 Oct 2023 16:33:13 +0200 Subject: [PATCH] [clangd] Add tweak to abbreviate function templates Co-authored-by: Vina Zahnd --- .../tweaks/AbbreviateFunctionTemplate.cpp | 352 ++ .../clangd/refactor/tweaks/CMakeLists.txt | 1 + .../clangd/unittests/CMakeLists.txt | 1 + .../AbbreviateFunctionTemplateTests.cpp | 76 clang-tools-extra/docs/ReleaseNotes.rst | 3 + 5 files changed, 433 insertions(+) create mode 100644 clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp create mode 100644 clang-tools-extra/clangd/unittests/tweaks/AbbreviateFunctionTemplateTests.cpp diff --git a/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp b/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp new file mode 100644 index 0..a2cfc6e13b01f --- /dev/null +++ b/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp @@ -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 "FindTarget.h" +#include "SourceCode.h" +#include "XRefs.h" +#include "refactor/Tweak.h" +#include "support/Logger.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExprConcepts.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" +#include + +namespace clang { +namespace clangd { +namespace { +/// Converts a function template to its abbreviated form using auto parameters. +/// Before: +/// template +/// auto foo(T param) { } +/// ^^^ +/// After: +/// auto foo(std::integral auto param) { } +class AbbreviateFunctionTemplate : public Tweak { +public: + const char *id() const final; + + auto prepare(const Selection &Inputs) -> bool override; + auto apply(const Selection &Inputs) -> Expected override; + + auto title() const -> std::string override { +return llvm::formatv("Abbreviate function template"); + } + + auto kind() const -> llvm::StringLiteral override { +return CodeAction::REFACTOR_KIND; + } + +private: + static const char *AutoKeywordSpelling; + const FunctionTemplateDecl *FunctionTemplateDeclaration; + + struct TemplateParameterInfo { +const TypeConstraint *Constraint; +unsigned int FunctionParameterIndex; +std::vector FunctionParameterQualifiers; +std::vector FunctionParameterTypeQualifiers; + }; + + std::vector TemplateParameterInfoList; + + auto traverseFunctionParameters(size_t NumberOfTemplateParameters) -> bool; + + auto generateFunctionParameterReplacements(const ASTContext &Context) + -> llvm::Expected; + + auto generateFunctionParameterReplacement( + const TemplateParameterInfo &TemplateParameterInfo, + const ASTContext &Context) -> llvm::Expected; + + auto generateTemplateDeclarationReplacement(const ASTContext &Context) + -> llvm::Expected; + + static auto deconstructType(QualType Type) + -> std::tuple, +std::vector>; +}; + +REGISTER_TWEAK(AbbreviateFunctionTemplate) + +const char *AbbreviateFunctionTemplate::AutoKeywordSpelling = +getKeywordSpelling(tok::kw_auto); + +template +auto findDeclaration(const SelectionTree::Node &Root) -> const T * { + for (const auto *Node = &Root; Node; Node = Node->Parent) { +if (const T *Result = dyn_cast_or_null(Node->ASTNode.get())) + return Result; + } + + return nullptr; +} + +auto getSpellingForQualifier(tok::TokenKind const &Qualifier) -> const char * { + 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(*CommonAncestor); + + if (!FunctionTemplateDeclaration) +return false; + + auto *TemplateParameters = + FunctionTemplateDeclaration->getTemplateParameters(); + + auto NumberOfTemplateParameters = TemplateParameters->size(); + TemplateParameterInfoList = + std::vector(NumberOfTemplateParameters); + + // Check how many times each template parameter is referenced. + // Depending on the number of references it can be checked + // if the refactoring is possible: + // - exactly one: The tem
[clang-tools-extra] [clangd] Add tweak to abbreviate function templates (PR #74710)
https://github.com/jeremystucki updated https://github.com/llvm/llvm-project/pull/74710 >From 64573476024103cf94f6cfc690e5396a368fc3df Mon Sep 17 00:00:00 2001 From: Jeremy Stucki Date: Fri, 27 Oct 2023 16:33:13 +0200 Subject: [PATCH] [clangd] Add tweak to abbreviate function templates Co-authored-by: Vina Zahnd --- .../tweaks/AbbreviateFunctionTemplate.cpp | 352 ++ .../clangd/refactor/tweaks/CMakeLists.txt | 1 + .../clangd/unittests/CMakeLists.txt | 1 + .../AbbreviateFunctionTemplateTests.cpp | 76 clang-tools-extra/docs/ReleaseNotes.rst | 3 + 5 files changed, 433 insertions(+) create mode 100644 clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp create mode 100644 clang-tools-extra/clangd/unittests/tweaks/AbbreviateFunctionTemplateTests.cpp diff --git a/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp b/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp new file mode 100644 index 0..a2cfc6e13b01f --- /dev/null +++ b/clang-tools-extra/clangd/refactor/tweaks/AbbreviateFunctionTemplate.cpp @@ -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 "FindTarget.h" +#include "SourceCode.h" +#include "XRefs.h" +#include "refactor/Tweak.h" +#include "support/Logger.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExprConcepts.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" +#include + +namespace clang { +namespace clangd { +namespace { +/// Converts a function template to its abbreviated form using auto parameters. +/// Before: +/// template +/// auto foo(T param) { } +/// ^^^ +/// After: +/// auto foo(std::integral auto param) { } +class AbbreviateFunctionTemplate : public Tweak { +public: + const char *id() const final; + + auto prepare(const Selection &Inputs) -> bool override; + auto apply(const Selection &Inputs) -> Expected override; + + auto title() const -> std::string override { +return llvm::formatv("Abbreviate function template"); + } + + auto kind() const -> llvm::StringLiteral override { +return CodeAction::REFACTOR_KIND; + } + +private: + static const char *AutoKeywordSpelling; + const FunctionTemplateDecl *FunctionTemplateDeclaration; + + struct TemplateParameterInfo { +const TypeConstraint *Constraint; +unsigned int FunctionParameterIndex; +std::vector FunctionParameterQualifiers; +std::vector FunctionParameterTypeQualifiers; + }; + + std::vector TemplateParameterInfoList; + + auto traverseFunctionParameters(size_t NumberOfTemplateParameters) -> bool; + + auto generateFunctionParameterReplacements(const ASTContext &Context) + -> llvm::Expected; + + auto generateFunctionParameterReplacement( + const TemplateParameterInfo &TemplateParameterInfo, + const ASTContext &Context) -> llvm::Expected; + + auto generateTemplateDeclarationReplacement(const ASTContext &Context) + -> llvm::Expected; + + static auto deconstructType(QualType Type) + -> std::tuple, +std::vector>; +}; + +REGISTER_TWEAK(AbbreviateFunctionTemplate) + +const char *AbbreviateFunctionTemplate::AutoKeywordSpelling = +getKeywordSpelling(tok::kw_auto); + +template +auto findDeclaration(const SelectionTree::Node &Root) -> const T * { + for (const auto *Node = &Root; Node; Node = Node->Parent) { +if (const T *Result = dyn_cast_or_null(Node->ASTNode.get())) + return Result; + } + + return nullptr; +} + +auto getSpellingForQualifier(tok::TokenKind const &Qualifier) -> const char * { + 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(*CommonAncestor); + + if (!FunctionTemplateDeclaration) +return false; + + auto *TemplateParameters = + FunctionTemplateDeclaration->getTemplateParameters(); + + auto NumberOfTemplateParameters = TemplateParameters->size(); + TemplateParameterInfoList = + std::vector(NumberOfTemplateParameters); + + // Check how many times each template parameter is referenced. + // Depending on the number of references it can be checked + // if the refactoring is possible: + // - exactly one: The tem