sammccall added a comment.

Thanks for sending this! Broadly looks good, a few details to work out. I think 
the biggest one is multiple symbols which you've flagged.

> I'd like to ask for early feedback - what's still missing is relevant client 
> capability.

I'm actually not 100% sure that's necessary for custom LSP methods.

- a server capability would suffice at least, unless we're worried clients are 
going to call it "by mistake"?
- even that doesn't seem much better than just allowing the call where other 
servers would return an error. Keep it simple?

I'd suggest leaving it out unless others feel strongly.

> Couple things that I'd love to hear opinions about are:
> 
> - conditional return in `getCursorInfo` - Should we return for example data 
> with empty `USR`?

Please return a symbol unless it has no SymbolID (we don't treat those as 
symbols in clangd).
In practice this amounts to the same thing for now (SymbolID is derived from 
USR). May change in the future though.

> - `containerName` of local variables - It's currently empty even if semantic 
> parent has a name (say it's a function). (Please search for local.cpp in the 
> test.) Is that what we want?

good question, no idea.

> - For now I used `getSymbolAtPosition()` as it's simpler and fits the context 
> better. However I assume I could use this optimization from 
> `tooling::getNamedDeclAt()` (in a separate patch): 
> https://github.com/llvm-mirror/clang/blob/master/lib/Tooling/Refactoring/Rename/#L82

Yes, though at least for C++ this optimization won't usually buy anything, as 
the top-level decl will just be a namespace decl I think.
We could plumb this deeper if we want to win more here.

- One thing I am wondering about is whether we could use (and whether it's a 
significant improvement) some early return in `indexTopLevelDecls` (using 
`DeclarationAndMacrosFinder`) also for hover and definition use-cases. Is it 
correct to assume that at a given `Location` there can be maximum of one 
declaration and one definition?

There can be multiple and we should return them all. (Not sure what we do for 
hover, but defs handles this correctly).
I can't remember which are the important cases, but one we handle like this is 
implicit constructor calls:

  class Foo { Foo(const char*); }
  void g(Foo);
  const char* str = "abc";
  g(str);

completion on the `s` in the last line finds both the Foo constructor and the 
definition of `str`.

Maybe it's worth revisiting this if we can't find any really important 
examples. That would involve digging up the historical context (I don't 
remember it right now).

> P. S. Alex and Ben have thanksgiving break now so they'll probably add any 
> feedback next week.

Hope they're having a good break!



================
Comment at: ClangdLSPServer.cpp:728
   MsgHandler->bind("workspace/didChangeConfiguration", 
&ClangdLSPServer::onChangeConfiguration);
+  MsgHandler->bind("textDocument/cursorInfo", &ClangdLSPServer::onCursorInfo);
   // clang-format on
----------------
I'd suggest `textDocument/symbolInfo` for consistency with LSP (and similar 
with internal names).
The term "symbol" is used throughout LSP to describe roughly what we're using 
it to mean here.

Conversely I guess "cursor" refers to the editor cursor, but LSP seems to 
prefer just talking about positions.


================
Comment at: ClangdServer.h:205
+  /// Get cursor info for given position.
+  void getCursorInfo(PathRef File, Position Pos,
+                     Callback<llvm::Optional<IdentifierData>> CB);
----------------
nit: just `cursorInfo` (or `symbolInfo` etc) for consistency with other where 
there isn't a specific verb.


================
Comment at: Protocol.cpp:436
+                              const IdentifierData &SUCI) {
+  O << SUCI.containerName << "::" << SUCI.name << " - " << toJSON(SUCI);
+  return O;
----------------
(you only want containername if non-empty, right?)


================
Comment at: Protocol.h:676
 
+/// Represents information about identifier.
+struct IdentifierData {
----------------
Unless I'm misunderstanding, this is about a symbol, not an identifier. (e.g. 
overloads of C++ functions are distinct symbols). Maybe `SymbolDetails` would 
be a useful name.

There's a question of scope here: `getCursorInfo` seems to return a single 
instance of these, but there can be 0, 1, or many symbols at a given location. 
These could be `vector<SymbolDetails>` or so, or if this struct is intended to 
encapsulate them all, it could be named `SymbolsAtLocation` or so.


================
Comment at: Protocol.h:676
 
+/// Represents information about identifier.
+struct IdentifierData {
----------------
sammccall wrote:
> Unless I'm misunderstanding, this is about a symbol, not an identifier. (e.g. 
> overloads of C++ functions are distinct symbols). Maybe `SymbolDetails` would 
> be a useful name.
> 
> There's a question of scope here: `getCursorInfo` seems to return a single 
> instance of these, but there can be 0, 1, or many symbols at a given 
> location. These could be `vector<SymbolDetails>` or so, or if this struct is 
> intended to encapsulate them all, it could be named `SymbolsAtLocation` or so.
/// This is returned from textDocument/cursorInfo, which is a clangd extension.


================
Comment at: Protocol.h:678
+struct IdentifierData {
+  /// The name of this symbol.
+  std::string name;
----------------
This comment doesn't really say anything. It can be omitted, or we could add 
additional information.
(Some of the existing comments are equally content-free, because we've copied 
the comments from LSP verbatim, but that's not the case here)


================
Comment at: Protocol.h:682
+  /// The name of the symbol containing this symbol.
+  std::string containerName;
+
----------------
If we're not going to merge, I'd suggest making this "scope" and allowing it to 
end with ::.
This makes it easier to compose (qname = scope + name), and makes it clearer 
what "contains" means. (LSP got this wrong IMO, at least for C++).


================
Comment at: Protocol.h:682
+  /// The name of the symbol containing this symbol.
+  std::string containerName;
+
----------------
sammccall wrote:
> If we're not going to merge, I'd suggest making this "scope" and allowing it 
> to end with ::.
> This makes it easier to compose (qname = scope + name), and makes it clearer 
> what "contains" means. (LSP got this wrong IMO, at least for C++).
what do you want this to do for objc methods and fields?
It'd be worth having a test if it's important, I'm guilty of not 
knowing/checking ObjC behavior.


================
Comment at: Protocol.h:684
+
+  /// The USR of this symbol.
+  llvm::SmallString<128> USR;
----------------
USR could use some definition/references.


================
Comment at: Protocol.h:685
+  /// The USR of this symbol.
+  llvm::SmallString<128> USR;
+
----------------
please don't micro-optimize with smallstring etc in this file.


================
Comment at: Protocol.h:689
+  /// Size is dependent on clang::clangd::SymbolID::RawValue.
+  llvm::SmallString<32> ID;
+};
----------------
can this just be SymbolID?


================
Comment at: Protocol.h:690
+  llvm::SmallString<32> ID;
+};
+llvm::json::Value toJSON(const IdentifierData &);
----------------
I think SymbolKind would be useful (in particular distinguishing macros might 
be important?)

This does point towards maybe adding to SymbolInformation rather than a new 
struct, but I'm not sure which is best.


================
Comment at: XRefs.cpp:95
   Preprocessor &PP;
+  const bool StopOnFirstDeclFound;
 
----------------
Please don't do this - it's inconsistent with the other XRefs features.
(If for some reason you *really* want just one result, then this is easy to do 
on the client side if we get the API right)


================
Comment at: XRefs.cpp:770
+
+  if (!Symbols.Decls.empty()) {
+    if (const NamedDecl *ND = dyn_cast<NamedDecl>(Symbols.Decls.front().D)) {
----------------
(as alluded to elsewhere, we should return all decls/macros, not just one)


================
Comment at: clangd/cursor-info.test:1
+# RUN: clangd -lit-test < %s | FileCheck %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
----------------
It's great to have a smoke test for features like this (probably just a trivial 
call), but we test the details in unit tests for easier maintenance.

XRefsTests has a bunch of tests for similar features. TestTU + Annotations 
should make these tests fairly easy to write.



Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D54799



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to