[clangd] ExpandAutoType: Do not offer code action on lambdas.

We can't expand lambda types anyway. Now we simply not offer the code
action instead of showing it and then returning an error in apply().

Differential Revision: https://reviews.llvm.org/D92847
This commit is contained in:
Adam Czachorowski 2020-12-01 16:53:21 +01:00
parent 5b5d3fa9d9
commit 3c5bed734f
3 changed files with 25 additions and 4 deletions

View File

@ -63,6 +63,25 @@ bool isStructuredBindingType(const SelectionTree::Node *N) {
return N && N->ASTNode.get<DecompositionDecl>();
}
// Returns true iff Node is a lambda, and thus should not be expanded. Loc is
// the location of the auto type.
bool isDeducedAsLambda(const SelectionTree::Node *Node, SourceLocation Loc) {
// getDeducedType() does a traversal, which we want to avoid in prepare().
// But at least check this isn't auto x = []{...};, which can't ever be
// expanded.
// (It would be nice if we had an efficient getDeducedType(), instead).
for (const auto *It = Node; It; It = It->Parent) {
if (const auto *DD = It->ASTNode.get<DeclaratorDecl>()) {
if (DD->getTypeSourceInfo() &&
DD->getTypeSourceInfo()->getTypeLoc().getBeginLoc() == Loc) {
if (auto *RD = DD->getType()->getAsRecordDecl())
return RD->isLambda();
}
}
}
return false;
}
bool ExpandAutoType::prepare(const Selection& Inputs) {
CachedLocation = llvm::None;
if (auto *Node = Inputs.ASTSelection.commonAncestor()) {
@ -70,11 +89,13 @@ bool ExpandAutoType::prepare(const Selection& Inputs) {
if (const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
// Code in apply() does handle 'decltype(auto)' yet.
if (!Result.getTypePtr()->isDecltypeAuto() &&
!isStructuredBindingType(Node))
!isStructuredBindingType(Node) &&
!isDeducedAsLambda(Node, Result.getBeginLoc()))
CachedLocation = Result;
}
}
}
return (bool) CachedLocation;
}

View File

@ -11,4 +11,5 @@
// CHECK: All checks completed, 2 errors
#include "missing.h"
auto x = []{};
void fun();
auto x = fun;

View File

@ -559,8 +559,7 @@ TEST_F(ExpandAutoTypeTest, Test) {
EXPECT_THAT(apply("au^to x = &ns::Func;"),
StartsWith("fail: Could not expand type of function pointer"));
// lambda types are not replaced
EXPECT_THAT(apply("au^to x = []{};"),
StartsWith("fail: Could not expand type of lambda expression"));
EXPECT_UNAVAILABLE("au^to x = []{};");
// inline namespaces
EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
"Visible x = inl_ns::Visible();");