[clang-tools-extra] r365792 - [clangd] Implementation of auto type expansion.
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 11 09:04:18 PDT 2019
Author: sammccall
Date: Thu Jul 11 09:04:18 2019
New Revision: 365792
URL: http://llvm.org/viewvc/llvm-project?rev=365792&view=rev
Log:
[clangd] Implementation of auto type expansion.
Add a tweak for clangd to replace an auto keyword to the deduced type.
This way a user can declare something with auto and then have the
IDE/clangd replace auto with whatever type clangd thinks it is. In case
of long/complext types this makes is reduces writing effort for the
user.
The functionality is similar to the hover over the auto keyword.
Example (from the header):
```
/// Before:
/// auto x = Something();
/// ^^^^
/// After:
/// MyClass x = Something();
/// ^^^^^^^
```
Patch by kuhnel! (Christian Kühnel)
Differential Revision: https://reviews.llvm.org/D62855
Added:
clang-tools-extra/trunk/clangd/refactor/tweaks/ExpandAutoType.cpp
clang-tools-extra/trunk/clangd/test/code-action-request.test
clang-tools-extra/trunk/clangd/unittests/ASTTests.cpp
Modified:
clang-tools-extra/trunk/clangd/AST.cpp
clang-tools-extra/trunk/clangd/AST.h
clang-tools-extra/trunk/clangd/Selection.cpp
clang-tools-extra/trunk/clangd/Selection.h
clang-tools-extra/trunk/clangd/XRefs.cpp
clang-tools-extra/trunk/clangd/XRefs.h
clang-tools-extra/trunk/clangd/refactor/tweaks/CMakeLists.txt
clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt
clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp
Modified: clang-tools-extra/trunk/clangd/AST.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/AST.cpp?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/AST.cpp (original)
+++ clang-tools-extra/trunk/clangd/AST.cpp Thu Jul 11 09:04:18 2019
@@ -169,5 +169,35 @@ llvm::Optional<SymbolID> getSymbolID(con
return SymbolID(USR);
}
+std::string shortenNamespace(const llvm::StringRef OriginalName,
+ const llvm::StringRef CurrentNamespace) {
+ llvm::SmallVector<llvm::StringRef, 8> OriginalParts;
+ llvm::SmallVector<llvm::StringRef, 8> CurrentParts;
+ llvm::SmallVector<llvm::StringRef, 8> Result;
+ OriginalName.split(OriginalParts, "::");
+ CurrentNamespace.split(CurrentParts, "::");
+ auto MinLength = std::min(CurrentParts.size(), OriginalParts.size());
+
+ unsigned DifferentAt = 0;
+ while (DifferentAt < MinLength &&
+ CurrentParts[DifferentAt] == OriginalParts[DifferentAt]) {
+ DifferentAt++;
+ }
+
+ for (u_int i = DifferentAt; i < OriginalParts.size(); ++i) {
+ Result.push_back(OriginalParts[i]);
+ }
+ return join(Result, "::");
+}
+
+std::string printType(const QualType QT, const DeclContext & Context){
+ PrintingPolicy PP(Context.getParentASTContext().getPrintingPolicy());
+ PP.SuppressTagKeyword = 1;
+ return shortenNamespace(
+ QT.getAsString(PP),
+ printNamespaceScope(Context) );
+}
+
+
} // namespace clangd
} // namespace clang
Modified: clang-tools-extra/trunk/clangd/AST.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/AST.h?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/AST.h (original)
+++ clang-tools-extra/trunk/clangd/AST.h Thu Jul 11 09:04:18 2019
@@ -67,6 +67,22 @@ llvm::Optional<SymbolID> getSymbolID(con
const MacroInfo *MI,
const SourceManager &SM);
+/// Returns a QualType as string.
+std::string printType(const QualType QT, const DeclContext & Context);
+
+/// Try to shorten the OriginalName by removing namespaces from the left of
+/// the string that are redundant in the CurrentNamespace. This way the type
+/// idenfier become shorter and easier to read.
+/// Limitation: It only handles the qualifier of the type itself, not that of
+/// templates.
+/// FIXME: change type of parameter CurrentNamespace to DeclContext ,
+/// take in to account using directives etc
+/// Example: shortenNamespace("ns1::MyClass<ns1::OtherClass>", "ns1")
+/// --> "MyClass<ns1::OtherClass>"
+std::string shortenNamespace(const llvm::StringRef OriginalName,
+ const llvm::StringRef CurrentNamespace);
+
+
} // namespace clangd
} // namespace clang
Modified: clang-tools-extra/trunk/clangd/Selection.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Selection.cpp?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Selection.cpp (original)
+++ clang-tools-extra/trunk/clangd/Selection.cpp Thu Jul 11 09:04:18 2019
@@ -364,5 +364,18 @@ const Node *SelectionTree::commonAncesto
return Ancestor;
}
+const DeclContext& SelectionTree::Node::getDeclContext() const {
+ for (const Node* CurrentNode = this; CurrentNode != nullptr;
+ CurrentNode = CurrentNode->Parent) {
+ if (const Decl* Current = CurrentNode->ASTNode.get<Decl>()) {
+ if (CurrentNode != this)
+ if (auto *DC = dyn_cast<DeclContext>(Current))
+ return *DC;
+ return *Current->getDeclContext();
+ }
+ }
+ llvm_unreachable("A tree must always be rooted at TranslationUnitDecl.");
+}
+
} // namespace clangd
} // namespace clang
Modified: clang-tools-extra/trunk/clangd/Selection.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Selection.h?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Selection.h (original)
+++ clang-tools-extra/trunk/clangd/Selection.h Thu Jul 11 09:04:18 2019
@@ -93,6 +93,9 @@ public:
ast_type_traits::DynTypedNode ASTNode;
// The extent to which this node is covered by the selection.
Selection Selected;
+ // Walk up the AST to get the DeclContext of this Node,
+ // which is not the node itself.
+ const DeclContext& getDeclContext() const;
};
// The most specific common ancestor of all the selected nodes.
Modified: clang-tools-extra/trunk/clangd/XRefs.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.cpp?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/XRefs.cpp (original)
+++ clang-tools-extra/trunk/clangd/XRefs.cpp Thu Jul 11 09:04:18 2019
@@ -870,7 +870,9 @@ public:
} // namespace
/// Retrieves the deduced type at a given location (auto, decltype).
-bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg) {
+/// SourceLocationBeg must point to the first character of the token
+llvm::Optional<QualType> getDeducedType(ParsedAST &AST,
+ SourceLocation SourceLocationBeg) {
Token Tok;
auto &ASTCtx = AST.getASTContext();
// Only try to find a deduced type if the token is auto or decltype.
@@ -878,12 +880,20 @@ bool hasDeducedType(ParsedAST &AST, Sour
Lexer::getRawToken(SourceLocationBeg, Tok, ASTCtx.getSourceManager(),
ASTCtx.getLangOpts(), false) ||
!Tok.is(tok::raw_identifier)) {
- return false;
+ return {};
}
AST.getPreprocessor().LookUpIdentifierInfo(Tok);
if (!(Tok.is(tok::kw_auto) || Tok.is(tok::kw_decltype)))
- return false;
- return true;
+ return {};
+
+ DeducedTypeVisitor V(SourceLocationBeg);
+ V.TraverseAST(AST.getASTContext());
+ return V.DeducedType;
+}
+
+/// Retrieves the deduced type at a given location (auto, decltype).
+bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg) {
+ return (bool) getDeducedType(AST, SourceLocationBeg);
}
llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
Modified: clang-tools-extra/trunk/clangd/XRefs.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.h?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/XRefs.h (original)
+++ clang-tools-extra/trunk/clangd/XRefs.h Thu Jul 11 09:04:18 2019
@@ -141,6 +141,16 @@ llvm::Optional<TypeHierarchyItem> getTyp
ParsedAST &AST, Position Pos, int Resolve, TypeHierarchyDirection Direction,
const SymbolIndex *Index = nullptr, PathRef TUPath = PathRef{});
+/// Retrieves the deduced type at a given location (auto, decltype).
+/// Retuns None unless SourceLocationBeg starts an auto/decltype token.
+/// It will return the underlying type.
+llvm::Optional<QualType> getDeducedType(ParsedAST &AST,
+ SourceLocation SourceLocationBeg);
+
+/// Check if there is a deduced type at a given location (auto, decltype).
+/// SourceLocationBeg must point to the first character of the token
+bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg);
+
} // namespace clangd
} // namespace clang
Modified: clang-tools-extra/trunk/clangd/refactor/tweaks/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/refactor/tweaks/CMakeLists.txt?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/refactor/tweaks/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clangd/refactor/tweaks/CMakeLists.txt Thu Jul 11 09:04:18 2019
@@ -18,6 +18,7 @@ add_clang_library(clangDaemonTweaks OBJE
RawStringLiteral.cpp
SwapIfBranches.cpp
ExtractVariable.cpp
+ ExpandAutoType.cpp
LINK_LIBS
clangAST
Added: clang-tools-extra/trunk/clangd/refactor/tweaks/ExpandAutoType.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/refactor/tweaks/ExpandAutoType.cpp?rev=365792&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/refactor/tweaks/ExpandAutoType.cpp (added)
+++ clang-tools-extra/trunk/clangd/refactor/tweaks/ExpandAutoType.cpp Thu Jul 11 09:04:18 2019
@@ -0,0 +1,119 @@
+//===--- ReplaceAutoType.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 "refactor/Tweak.h"
+
+#include "Logger.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
+#include <climits>
+#include <memory>
+#include <string>
+#include <AST.h>
+#include "XRefs.h"
+#include "llvm/ADT/StringExtras.h"
+
+namespace clang {
+namespace clangd {
+
+/// Expand the "auto" type to the derived type
+/// Before:
+/// auto x = Something();
+/// ^^^^
+/// After:
+/// MyClass x = Something();
+/// ^^^^^^^
+/// FIXME: Handle decltype as well
+class ExpandAutoType : public Tweak {
+public:
+ const char *id() const final;
+ Intent intent() const override { return Intent::Refactor;}
+ bool prepare(const Selection &Inputs) override;
+ Expected<Effect> apply(const Selection &Inputs) override;
+ std::string title() const override;
+
+private:
+ /// Cache the AutoTypeLoc, so that we do not need to search twice.
+ llvm::Optional<clang::AutoTypeLoc> CachedLocation;
+
+ /// Create an error message with filename and line number in it
+ llvm::Error createErrorMessage(const std::string& Message,
+ const Selection &Inputs);
+
+};
+
+REGISTER_TWEAK(ExpandAutoType)
+
+std::string ExpandAutoType::title() const { return "expand auto type"; }
+
+bool ExpandAutoType::prepare(const Selection& Inputs) {
+ CachedLocation = llvm::None;
+ if (auto *Node = Inputs.ASTSelection.commonAncestor()) {
+ if (auto *TypeNode = Node->ASTNode.get<TypeLoc>()) {
+ if (const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
+ CachedLocation = Result;
+ }
+ }
+ }
+ return (bool) CachedLocation;
+}
+
+Expected<Tweak::Effect> ExpandAutoType::apply(const Selection& Inputs) {
+ auto& SrcMgr = Inputs.AST.getASTContext().getSourceManager();
+
+ llvm::Optional<clang::QualType> DeducedType =
+ getDeducedType(Inputs.AST, CachedLocation->getBeginLoc());
+
+ // if we can't resolve the type, return an error message
+ if (DeducedType == llvm::None || DeducedType->isNull()) {
+ return createErrorMessage("Could not deduce type for 'auto' type", Inputs);
+ }
+
+ // if it's a lambda expression, return an error message
+ if (isa<RecordType>(*DeducedType) and
+ dyn_cast<RecordType>(*DeducedType)->getDecl()->isLambda()) {
+ return createErrorMessage("Could not expand type of lambda expression",
+ Inputs);
+ }
+
+ // if it's a function expression, return an error message
+ // naively replacing 'auto' with the type will break declarations.
+ // FIXME: there are other types that have similar problems
+ if (DeducedType->getTypePtr()->isFunctionPointerType()) {
+ return createErrorMessage("Could not expand type of function pointer",
+ Inputs);
+ }
+
+ std::string PrettyTypeName = printType(*DeducedType,
+ Inputs.ASTSelection.commonAncestor()->getDeclContext());
+
+ tooling::Replacement
+ Expansion(SrcMgr, CharSourceRange(CachedLocation->getSourceRange(), true),
+ PrettyTypeName);
+
+ return Tweak::Effect::applyEdit(tooling::Replacements(Expansion));
+}
+
+llvm::Error ExpandAutoType::createErrorMessage(const std::string& Message,
+ const Selection& Inputs) {
+ auto& SrcMgr = Inputs.AST.getASTContext().getSourceManager();
+ std::string ErrorMessage =
+ Message + ": " +
+ SrcMgr.getFilename(Inputs.Cursor).str() + " Line " +
+ std::to_string(SrcMgr.getExpansionLineNumber(Inputs.Cursor));
+
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ ErrorMessage.c_str());
+}
+
+} // namespace clangd
+} // namespace clang
Added: clang-tools-extra/trunk/clangd/test/code-action-request.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/test/code-action-request.test?rev=365792&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/test/code-action-request.test (added)
+++ clang-tools-extra/trunk/clangd/test/code-action-request.test Thu Jul 11 09:04:18 2019
@@ -0,0 +1,70 @@
+# RUN: clangd -log=verbose -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"auto i = 0;"}}}
+---
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "textDocument/codeAction",
+ "params": {
+ "textDocument": {
+ "uri": "test:///main.cpp"
+ },
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 0
+ },
+ "end": {
+ "line": 0,
+ "character": 4
+ }
+ },
+ "context": {
+ "diagnostics": []
+ }
+ }
+}
+# CHECK: "id": 1,
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "arguments": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "file": "file:///clangd-test/main.cpp",
+# CHECK-NEXT: "selection": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 4,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "tweakID": "ExpandAutoType"
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "command": "clangd.applyTweak",
+# CHECK-NEXT: "title": "expand auto type"
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+---
+{"jsonrpc":"2.0","id":4,"method":"workspace/executeCommand","params":{"command":"clangd.applyTweak","arguments":[{"file":"file:///clangd-test/main.cpp","selection":{"end":{"character":4,"line":0},"start":{"character":0,"line":0}},"tweakID":"ExpandAutoType"}]}}
+# CHECK: "newText": "int",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 4,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":4,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
+---
\ No newline at end of file
Added: clang-tools-extra/trunk/clangd/unittests/ASTTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/ASTTests.cpp?rev=365792&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/ASTTests.cpp (added)
+++ clang-tools-extra/trunk/clangd/unittests/ASTTests.cpp Thu Jul 11 09:04:18 2019
@@ -0,0 +1,42 @@
+//===-- ASTTests.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 "AST.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(ExpandAutoType, ShortenNamespace) {
+ ASSERT_EQ("TestClass", shortenNamespace("TestClass", ""));
+
+ ASSERT_EQ("TestClass", shortenNamespace(
+ "testnamespace::TestClass", "testnamespace"));
+
+ ASSERT_EQ(
+ "namespace1::TestClass",
+ shortenNamespace("namespace1::TestClass", "namespace2"));
+
+ ASSERT_EQ("TestClass",
+ shortenNamespace("testns1::testns2::TestClass",
+ "testns1::testns2"));
+
+ ASSERT_EQ(
+ "testns2::TestClass",
+ shortenNamespace("testns1::testns2::TestClass", "testns1"));
+
+ ASSERT_EQ("TestClass<testns1::OtherClass>",
+ shortenNamespace(
+ "testns1::TestClass<testns1::OtherClass>", "testns1"));
+}
+
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Modified: clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt Thu Jul 11 09:04:18 2019
@@ -23,6 +23,7 @@ endif()
add_custom_target(ClangdUnitTests)
add_unittest(ClangdUnitTests ClangdTests
Annotations.cpp
+ ASTTests.cpp
BackgroundIndexTests.cpp
CancellationTests.cpp
CanonicalIncludesTests.cpp
Modified: clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp Thu Jul 11 09:04:18 2019
@@ -11,6 +11,7 @@
#include "TestTU.h"
#include "refactor/Tweak.h"
#include "clang/AST/Expr.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/Core/Replacement.h"
#include "llvm/ADT/StringRef.h"
@@ -126,6 +127,19 @@ void checkTransform(llvm::StringRef ID,
EXPECT_EQ(Output, std::string(*Result)) << Input;
}
+/// Check if apply returns an error and that the @ErrorMessage is contained
+/// in that error
+void checkApplyContainsError(llvm::StringRef ID, llvm::StringRef Input,
+ const std::string& ErrorMessage) {
+ auto Result = apply(ID, Input);
+ ASSERT_FALSE(Result) << "expected error message:\n " << ErrorMessage <<
+ "\non input:" << Input;
+ EXPECT_NE(std::string::npos,
+ llvm::toString(Result.takeError()).find(ErrorMessage))
+ << "Wrong error message:\n " << llvm::toString(Result.takeError())
+ << "\nexpected:\n " << ErrorMessage;
+}
+
TEST(TweakTest, SwapIfBranches) {
llvm::StringLiteral ID = "SwapIfBranches";
@@ -517,6 +531,140 @@ int a = 123 EMPTY_FN(1) ;
)cpp");
}
+TEST(TweakTest, ExpandAutoType) {
+ llvm::StringLiteral ID = "ExpandAutoType";
+
+ checkAvailable(ID, R"cpp(
+ ^a^u^t^o^ i = 0;
+ )cpp");
+
+ checkNotAvailable(ID, R"cpp(
+ auto ^i^ ^=^ ^0^;^
+ )cpp");
+
+ llvm::StringLiteral Input = R"cpp(
+ [[auto]] i = 0;
+ )cpp";
+ llvm::StringLiteral Output = R"cpp(
+ int i = 0;
+ )cpp";
+ checkTransform(ID, Input, Output);
+
+ // check primitive type
+ Input = R"cpp(
+ au^to i = 0;
+ )cpp";
+ Output = R"cpp(
+ int i = 0;
+ )cpp";
+ checkTransform(ID, Input, Output);
+
+ // check classes and namespaces
+ Input = R"cpp(
+ namespace testns {
+ class TestClass {
+ class SubClass {};
+ };
+ }
+ ^auto C = testns::TestClass::SubClass();
+ )cpp";
+ Output = R"cpp(
+ namespace testns {
+ class TestClass {
+ class SubClass {};
+ };
+ }
+ testns::TestClass::SubClass C = testns::TestClass::SubClass();
+ )cpp";
+ checkTransform(ID, Input, Output);
+
+ // check that namespaces are shortened
+ Input = R"cpp(
+ namespace testns {
+ class TestClass {
+ };
+ void func() { ^auto C = TestClass(); }
+ }
+ )cpp";
+ Output = R"cpp(
+ namespace testns {
+ class TestClass {
+ };
+ void func() { TestClass C = TestClass(); }
+ }
+ )cpp";
+ checkTransform(ID, Input, Output);
+
+ // unknown types in a template should not be replaced
+ Input = R"cpp(
+ template <typename T> void x() {
+ ^auto y = T::z();
+ }
+ )cpp";
+ checkApplyContainsError(ID, Input, "Could not deduce type for 'auto' type");
+
+ // undefined functions should not be replaced
+ Input = R"cpp(
+ a^uto x = doesnt_exist();
+ )cpp";
+ checkApplyContainsError(ID, Input, "Could not deduce type for 'auto' type");
+
+ // function pointers should not be replaced
+ Input = R"cpp(
+ int foo();
+ au^to x = &foo;
+ )cpp";
+ checkApplyContainsError(ID, Input,
+ "Could not expand type of function pointer");
+
+ // lambda types are not replaced
+ Input = R"cpp(
+ au^to x = []{};
+ )cpp";
+ checkApplyContainsError(ID, Input,
+ "Could not expand type of lambda expression");
+
+ // inline namespaces
+ Input = R"cpp(
+ inline namespace x {
+ namespace { struct S; }
+ }
+ au^to y = S();
+ )cpp";
+ Output = R"cpp(
+ inline namespace x {
+ namespace { struct S; }
+ }
+ S y = S();
+ )cpp";
+
+ // local class
+ Input = R"cpp(
+ namespace x {
+ void y() {
+ struct S{};
+ a^uto z = S();
+ }}
+ )cpp";
+ Output = R"cpp(
+ namespace x {
+ void y() {
+ struct S{};
+ S z = S();
+ }}
+ )cpp";
+ checkTransform(ID, Input, Output);
+
+ // replace array types
+ Input = R"cpp(
+ au^to x = "test";
+ )cpp";
+ Output = R"cpp(
+ const char * x = "test";
+ )cpp";
+ checkTransform(ID, Input, Output);
+}
+
} // namespace
} // namespace clangd
} // namespace clang
Modified: clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp?rev=365792&r1=365791&r2=365792&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp Thu Jul 11 09:04:18 2019
@@ -2139,6 +2139,28 @@ TEST(FindReferences, NoQueryForLocalSymb
}
}
+TEST(GetDeducedType, KwAutoExpansion) {
+ struct Test {
+ StringRef AnnotatedCode;
+ const char *DeducedType;
+ } Tests[] = {
+ {"^auto i = 0;", "int"},
+ {"^auto f(){ return 1;};", "int"}
+ };
+ for (Test T : Tests) {
+ Annotations File(T.AnnotatedCode);
+ auto AST = TestTU::withCode(File.code()).build();
+ ASSERT_TRUE(AST.getDiagnostics().empty()) << AST.getDiagnostics().begin()->Message;
+ SourceManagerForFile SM("foo.cpp", File.code());
+
+ for (Position Pos : File.points()) {
+ auto Location = sourceLocationInMainFile(SM.get(), Pos);
+ auto DeducedType = getDeducedType(AST, *Location);
+ EXPECT_EQ(DeducedType->getAsString(), T.DeducedType);
+ }
+ }
+}
+
} // namespace
} // namespace clangd
} // namespace clang
More information about the cfe-commits
mailing list