[PATCH] D34269: [clangd] Add "Go to Declaration" functionality
Ilya Biryukov via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 16 04:06:14 PDT 2017
ilya-biryukov added a comment.
Hi @malaperle-ericsson. Thanks for the patch.
IndexingAction has a very simple interface, exactly what clangd needs and nothing more.
BTW, we had a bug open for that: https://bugs.llvm.org/show_bug.cgi?id=33261, feel free to reassign to yourself.
================
Comment at: clangd/ClangdServer.cpp:275
+ auto TaggedFS = FSProvider.getTaggedFileSystem(File);
+ Units.runOnUnitWithoutReparse(
+ File, *FileContents.Draft, CDB, PCHs, TaggedFS.Value, [&](ClangdUnit &Unit) {
----------------
We must call **runOnUnit** here, calling **runOnUnitWithoutReparse** will result in an outdated AST.
(This can't happen if you use -run-synchronously, so tests don't catch it).
================
Comment at: clangd/ClangdUnit.cpp:303
+ // fo|o -> foo| good!
+ if (InputLocation == SourceLocationBeg && Pos.character > 0) {
+ SourceLocation PeekBeforeLocation = Unit->getLocation(FE, Pos.line + 1,
----------------
Minor: Maybe invert condition to reduce nesting, i.e. if (InputLocation != SourceLocationBeg || Pos.character == 0) return SourceLocationBeg;
PS. I'm perfectly fine if this comment is ignored, it's just a matter of preference.
================
Comment at: clangd/ClangdUnit.cpp:306
+ Pos.character);
+ SourceLocation PeekBeforeLocationEnd = Lexer::getLocForEndOfToken(
+ PeekBeforeLocation, 0, SourceMgr, Unit->getASTContext().getLangOpts());
----------------
Just wondering: is there a way to not do the lexing multiple times?
================
Comment at: clangd/DeclarationLocationsFinder.cpp:48
+ // This can happen when nodes in the AST are visited twice.
+ if (std::none_of(DeclarationLocations.begin(), DeclarationLocations.end(),
+ [&L](const Location& Loc) {
----------------
Is it possible for DeclarationLocation to become large, so that quadratic behavior is observed?
If not, maybe add an assert that it's smaller than some threshold?
If yes, maybe use std::set instead of std::vector or use vector and later std::sort and std::unique in the end?
================
Comment at: clangd/DeclarationLocationsFinder.cpp:48
+ // This can happen when nodes in the AST are visited twice.
+ if (std::none_of(DeclarationLocations.begin(), DeclarationLocations.end(),
+ [&L](const Location& Loc) {
----------------
ilya-biryukov wrote:
> Is it possible for DeclarationLocation to become large, so that quadratic behavior is observed?
>
> If not, maybe add an assert that it's smaller than some threshold?
> If yes, maybe use std::set instead of std::vector or use vector and later std::sort and std::unique in the end?
Maybe use std::find instead of std::none_of?
```
std::find(DeclarationLocations.begin(), DeclarationLocations.end(), L) == DeclarationLocations.end()
```
================
Comment at: clangd/DeclarationLocationsFinder.cpp:59
+ Token Result;
+ if (!Lexer::getRawToken(SearchedLocation, Result, Unit.getSourceManager(),
+ Unit.getASTContext().getLangOpts(), false)) {
----------------
Could we implement ` handleMacroOccurence` instead?
I suspect current code won't work if macro is undef'ed/redefined later:
```
#define FOO 123
int b = FO|O;
#define FOO 125
// or
// #undef FOO
```
Maybe also add this to tests?
================
Comment at: clangd/DeclarationLocationsFinder.h:24
+/// Finds declarations locations that a given source location refers to.
+class DeclarationLocationsFinder : public index::IndexDataConsumer {
+ std::vector<Location> DeclarationLocations;
----------------
Maybe put this into ClangdUnit.cpp inside an anonymous namespace?
As it's just an implementation detail.
================
Comment at: clangd/DeclarationLocationsFinder.h:34
+
+ std::vector<Location> getLocations() {
+ return DeclarationLocations;
----------------
Maybe have a takeLocations() method that 'std::move's the vector instead of copying?
================
Comment at: clangd/Protocol.cpp:57
std::string URI::unparse(const URI &U) {
- return U.uri;
+ return "\"" + U.uri + "\"";
}
----------------
Why this didn't require any changes to other code? This method hasn't been used before?
================
Comment at: clangd/Protocol.h:42
+
+ friend bool operator==(const URI &LHS, const URI &RHS) {
+ return LHS.uri == RHS.uri;
----------------
Maybe add 'operator != ' for consistency?
================
Comment at: clangd/Protocol.h:98
+
+ friend bool operator==(const Location &LHS, const Location &RHS) {
+ return LHS.uri == RHS.uri && LHS.range == RHS.range;
----------------
Maybe add 'operator != ' for consistency?
================
Comment at: test/clangd/definitions.test:1
+# RUN: clangd -run-synchronously < %s | FileCheck %s
+# It is absolutely vital that this file has CRLF line endings.
----------------
Could we also add more readable tests specifically for that?
I propose to have a tool that could read files like:
```
int aaa;
int b = a/*{l1}*/aa;
int c = /*{l2}*/b;
```
And have it output the resulting goto results:
```
l1 -> {main.cpp:0:4} int |aaa;
l2 -> {main.cpp:1:4} int |b;
```
And we could also have a tool that prints expected clangd input/output based on that to check that action actually works.
It's not directly relevant to this patch, though. Just random thoughts of what we should do for easier testing.
Repository:
rL LLVM
https://reviews.llvm.org/D34269
More information about the cfe-commits
mailing list