[PATCH] D62855: [clangd] Implementation of auto type expansion.
Sam McCall via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 1 04:17:59 PDT 2019
sammccall added a comment.
Let's chat offline about how to land this.
Main points are:
- we may just be able to use the AutoTypeLoc instead of the separate RecursiveASTVisitor. (If so, we can do more checks in prepare())
- I have lots of questions about where to draw the line on pretty-printing, and whether the initial version here is a useful first step. Maybe we should just move this part to AST.h and stub it out, with a plan to incrementally improve later.
================
Comment at: clang-tools-extra/clangd/AST.h:20
#include "clang/Lex/MacroInfo.h"
+#include "clang/AST/RecursiveASTVisitor.h"
----------------
(can now revert this change)
================
Comment at: clang-tools-extra/clangd/XRefs.h:143
+/// Retrieves the deduced type at a given location (auto, decltype).
+/// SourceLocationBeg must point to the first character of the token
----------------
Can you elaborate slightly whether this returns the AutoType/DecltypeType or its underlying type?
================
Comment at: clang-tools-extra/clangd/XRefs.h:144
+/// Retrieves the deduced type at a given location (auto, decltype).
+/// SourceLocationBeg must point to the first character of the token
+llvm::Optional<QualType> getDeducedType(ParsedAST &AST,
----------------
nit: I'd change the second sentence to be "Retuns None unless SourceLocationBeg starts an auto/decltype token".
The current wording isn't totally specific about the token, or what happens in other cases (UB is common for preconditions)
================
Comment at: clang-tools-extra/clangd/XRefs.h:150
+/// SourceLocationBeg must point to the first character of the token
+bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg);
+
----------------
This appears to be unused, and isn't really worth having unless it's significantly more efficient than getDeducedType().hasValue() and we think that matters.
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:32
+ CachedLocation = findAutoType(Node);
+ return CachedLocation != llvm::None;
+}
----------------
&& `!CachedLocation->getTypePtr()->getDeducedType()->isNull()`?
to avoid triggering in e.g. dependent code like
```
template <typename T> void f() {
auto X = T::foo();
}
```
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:39
+ llvm::Optional<clang::QualType> DeductedType =
+ getDeducedType(Inputs.AST, CachedLocation->getBeginLoc());
+
----------------
is this ever not just `CachedLocation->getTypePtr()->getDeducedType()`?
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:47
+ // if it's a lambda expression, return an error message
+ if (isa<RecordType>(*DeductedType) and
+ dyn_cast<RecordType>(*DeductedType)->getDecl()->isLambda()) {
----------------
again, this is actually a cheap test (if we don't need to use the deduced type visitor), we can lift it into prepare
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:53
+
+ SourceRange OriginalRange(CachedLocation->getBeginLoc(),
+ CachedLocation->getEndLoc());
----------------
nit: this is just CachedLocation->getSourceRange()
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:55
+ CachedLocation->getEndLoc());
+ PrintingPolicy PP(Inputs.AST.getASTContext().getPrintingPolicy());
+ PP.SuppressTagKeyword = 1;
----------------
this logic around pretty-printing a type for insertion in code is going to be:
- eventually more complicated than this: (e.g. this won't trim the "clangd" from `std::vector<clangd::Tweak>`)
- needed in several places, like "extract expression" refactoring
- fairly easily isolated from the rest of the code here
Can we move this to AST.h, with some signature like:
`std::string printType(QualType, DeclContext &)`
Note that the namespace and (most) governing using decls/directives can be obtained from the DC (printNamespaceScope in AST.h).
The limitations in the current version are fine for now, but we should document them.
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:68
+const llvm::Optional<AutoTypeLoc>
+ExpandAutoType::findAutoType(const SelectionTree::Node* StartNode) {
+ auto Node = StartNode;
----------------
I'm confused about this - how can the user select the child of an AutoTypeLoc rather than the AutoTypeLoc itself? i.e. do we need the loop?
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:70
+ auto Node = StartNode;
+ while (Node != nullptr) {
+ auto TypeNode = Node->ASTNode.get<TypeLoc>();
----------------
(nit: for loop in disguise!)
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:108
+ const SelectionTree::Node* StartNode) {
+ auto Node = StartNode;
+ while (Node != nullptr) {
----------------
also a for loop in disguise
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:111
+ LLVM_DEBUG(Node->ASTNode.print());
+ if (const Decl* Current = Node->ASTNode.get<Decl>()) {
+ if (auto CurrentNameSpace = dyn_cast<NamespaceDecl>(Current)) {
----------------
nit: you can combine these with
`if (const auto* NSD = dyn_cast_or_null<NamespaceDecl>(Node->ASTNode.get<Decl>()))`
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:112
+ if (const Decl* Current = Node->ASTNode.get<Decl>()) {
+ if (auto CurrentNameSpace = dyn_cast<NamespaceDecl>(Current)) {
+ return CurrentNameSpace->getQualifiedNameAsString();
----------------
nit: prefer auto*
================
Comment at: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp:113
+ if (auto CurrentNameSpace = dyn_cast<NamespaceDecl>(Current)) {
+ return CurrentNameSpace->getQualifiedNameAsString();
+ }
----------------
with namespaces, both inline and (probably) anonymous namespaces should be ignored, which I don't think this function will do.
note there can also be non-namespace qualifiers like `MyClass::MyNestedClass`.
================
Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:396
+ )cpp";
+ checkTransform(ID, Input, Output);
+}
----------------
can we have one for function pointers?
```
int foo();
auto x = &foo;
```
The correct replacement would be `int (*x)() = &foo;` but I think we should just aim to produce no edits in such cases.
================
Comment at: clang-tools-extra/clangd/unittests/XRefsTests.cpp:2111
+TEST(GetDeductedType, KwAutoExpansion) {
+ struct Test {
----------------
(still "deducted" here)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D62855/new/
https://reviews.llvm.org/D62855
More information about the cfe-commits
mailing list