[PATCH] D48762: [clangd] codeComplete returns more structured completion items, LSP. NFC.

2018-06-29 Thread Sam McCall via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE335980: [clangd] codeComplete returns more structured 
completion items, LSP. NFC. (authored by sammccall, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D48762?vs=153493=153495#toc

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D48762

Files:
  clangd/ClangdServer.cpp
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Protocol.h

Index: clangd/ClangdServer.cpp
===
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -165,11 +165,15 @@
 
 // FIXME(ibiryukov): even if Preamble is non-null, we may want to check
 // both the old and the new version in case only one of them matches.
-CompletionList Result = clangd::codeComplete(
+CodeCompleteResult Result = clangd::codeComplete(
 File, IP->Command, PreambleData ? >Preamble : nullptr,
 PreambleData ? PreambleData->Inclusions : std::vector(),
 IP->Contents, Pos, FS, PCHs, CodeCompleteOpts);
-CB(std::move(Result));
+CompletionList LSPResult;
+LSPResult.isIncomplete = Result.HasMore;
+for (const auto  : Result.Completions)
+  LSPResult.items.push_back(Completion.render(CodeCompleteOpts));
+CB(std::move(LSPResult));
   };
 
   WorkScheduler.runWithPreamble("CodeComplete", File,
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -668,20 +668,6 @@
   Snippet = 2,
 };
 
-/// Provides details for how a completion item was scored.
-/// This can be used for client-side filtering of completion items as the
-/// user keeps typing.
-/// This is a clangd extension.
-struct CompletionItemScores {
-  /// The score that items are ranked by.
-  /// This is filterScore * symbolScore.
-  float finalScore = 0.f;
-  /// How the partial identifier matched filterText. [0-1]
-  float filterScore = 0.f;
-  /// How the symbol fits, ignoring the partial identifier.
-  float symbolScore = 0.f;
-};
-
 struct CompletionItem {
   /// The label of this completion item. By default also the text that is
   /// inserted when selecting this completion.
@@ -702,9 +688,6 @@
   /// When `falsy` the label is used.
   std::string sortText;
 
-  /// Details about the quality of this completion item. (clangd extension)
-  llvm::Optional scoreInfo;
-
   /// A string that should be used when filtering a set of completion items.
   /// When `falsy` the label is used.
   std::string filterText;
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -43,7 +43,7 @@
 #include 
 
 // We log detailed candidate here if you run with -debug-only=codecomplete.
-#define DEBUG_TYPE "codecomplete"
+#define DEBUG_TYPE "CodeComplete"
 
 namespace clang {
 namespace clangd {
@@ -237,138 +237,154 @@
 return IndexResult->Detail->IncludeHeader;
   }
 
-  // Builds an LSP completion item.
-  CompletionItem build(StringRef FileName, const CompletionItemScores ,
-   const CodeCompleteOptions ,
-   CodeCompletionString *SemaCCS,
-   const IncludeInserter ,
-   llvm::StringRef SemaDocComment) const {
-assert(bool(SemaResult) == bool(SemaCCS));
-assert(SemaResult || IndexResult);
-
-CompletionItem I;
-bool InsertingInclude = false; // Whether a new #include will be added.
-if (SemaResult) {
-  llvm::StringRef Name(SemaCCS->getTypedText());
-  std::string Signature, SnippetSuffix, Qualifiers;
-  getSignature(*SemaCCS, , , );
-  I.label = (Qualifiers + Name + Signature).str();
-  I.filterText = Name;
-  I.insertText = (Qualifiers + Name).str();
-  if (Opts.EnableSnippets)
-I.insertText += SnippetSuffix;
-  I.documentation = formatDocumentation(*SemaCCS, SemaDocComment);
-  I.detail = getReturnType(*SemaCCS);
-  if (SemaResult->Kind == CodeCompletionResult::RK_Declaration)
-if (const auto *D = SemaResult->getDeclaration())
-  if (const auto *ND = llvm::dyn_cast(D))
-I.SymbolScope = splitQualifiedName(printQualifiedName(*ND)).first;
-  I.kind = toCompletionItemKind(SemaResult->Kind, SemaResult->Declaration);
-}
-if (IndexResult) {
-  if (I.SymbolScope.empty())
-I.SymbolScope = IndexResult->Scope;
-  if (I.kind == CompletionItemKind::Missing)
-I.kind = toCompletionItemKind(IndexResult->SymInfo.Kind);
-  // FIXME: reintroduce a way to show the index source for debugging.
-  if (I.label.empty())
-I.label = (IndexResult->Name + IndexResult->Signature).str();
-  if (I.filterText.empty())
-I.filterText = IndexResult->Name;
-
-  // FIXME(ioeric): support inserting/replacing scope qualifiers.
-  if (I.insertText.empty()) {
-

[PATCH] D48762: [clangd] codeComplete returns more structured completion items, LSP. NFC.

2018-06-29 Thread Eric Liu via Phabricator via cfe-commits
ioeric accepted this revision.
ioeric added a comment.
This revision is now accepted and ready to land.

lgtm


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D48762



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


[PATCH] D48762: [clangd] codeComplete returns more structured completion items, LSP. NFC.

2018-06-29 Thread Sam McCall via Phabricator via cfe-commits
sammccall updated this revision to Diff 153493.
sammccall marked 11 inline comments as done.
sammccall added a comment.

Address review comments.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D48762

Files:
  clangd/ClangdServer.cpp
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Protocol.h

Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -668,20 +668,6 @@
   Snippet = 2,
 };
 
-/// Provides details for how a completion item was scored.
-/// This can be used for client-side filtering of completion items as the
-/// user keeps typing.
-/// This is a clangd extension.
-struct CompletionItemScores {
-  /// The score that items are ranked by.
-  /// This is filterScore * symbolScore.
-  float finalScore = 0.f;
-  /// How the partial identifier matched filterText. [0-1]
-  float filterScore = 0.f;
-  /// How the symbol fits, ignoring the partial identifier.
-  float symbolScore = 0.f;
-};
-
 struct CompletionItem {
   /// The label of this completion item. By default also the text that is
   /// inserted when selecting this completion.
@@ -702,9 +688,6 @@
   /// When `falsy` the label is used.
   std::string sortText;
 
-  /// Details about the quality of this completion item. (clangd extension)
-  llvm::Optional scoreInfo;
-
   /// A string that should be used when filtering a set of completion items.
   /// When `falsy` the label is used.
   std::string filterText;
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -75,15 +75,79 @@
   const SymbolIndex *Index = nullptr;
 };
 
+// Semi-structured representation of a code-complete suggestion for our C++ API.
+// We don't use the LSP structures here (unlike most features) as we want
+// to expose more data to allow for more precise testing and evaluation.
+struct CodeCompletion {
+  // The unqualified name of the symbol or other completion item.
+  std::string Name;
+  // The scope qualifier for the symbol name. e.g. "ns1::ns2::"
+  // Empty for non-symbol completions. Not inserted, but may be displayed.
+  std::string Scope;
+  // Text that must be inserted before the name, and displayed (e.g. base::).
+  std::string RequiredQualifier;
+  // Details to be displayed following the name. Not inserted.
+  std::string Signature;
+  // Text to be inserted following the name, in snippet format.
+  std::string SnippetSuffix;
+  // Type to be displayed for this completion.
+  std::string ReturnType;
+  std::string Documentation;
+  CompletionItemKind Kind = CompletionItemKind::Missing;
+  // This completion item may represent several symbols that can be inserted in
+  // the same way, such as function overloads. In this case BundleSize > 1, and
+  // the following fields are summaries:
+  //  - Signature is e.g. "(...)" for functions.
+  //  - SnippetSuffix is similarly e.g. "(${0})".
+  //  - ReturnType may be empty
+  //  - Documentation may be from one symbol, or a combination of several
+  // Other fields should apply equally to all bundled completions.
+  unsigned BundleSize;
+  // The header through which this symbol could be included.
+  // Quoted string as expected by an #include directive, e.g. "".
+  // Empty for non-symbol completions, or when not known.
+  std::string Header;
+  // Present if Header is set and should be inserted to use this item.
+  llvm::Optional HeaderInsertion;
+
+  // Scores are used to rank completion items.
+  struct Scores {
+// The score that items are ranked by.
+float Total = 0.f;
+
+// The finalScore with the fuzzy name match score excluded.
+// When filtering client-side, editors should calculate the new fuzzy score,
+// whose scale is 0-1 (with 1 = prefix match, special case 2 = exact match),
+// and recompute finalScore = fuzzyScore * symbolScore.
+float ExcludingName = 0.f;
+
+// Component scores that contributed to the final score:
+
+// Quality describes how important we think this candidate is,
+// independent of the query.
+// e.g. symbols with lots of incoming references have higher quality.
+float Quality = 0.f;
+// Relevance describes how well this candidate matched the query.
+// e.g. symbols from nearby files have higher relevance.
+float Relevance = 0.f;
+  };
+  Scores Score;
+
+  // Serialize this to an LSP completion item. This is a lossy operation.
+  CompletionItem render(const CodeCompleteOptions &) const;
+};
+struct CodeCompleteResult {
+  std::vector Completions;
+  bool HasMore = false;
+};
+
 /// Get code completions at a specified \p Pos in \p FileName.
-CompletionList codeComplete(PathRef FileName,
-const tooling::CompileCommand ,
-PrecompiledPreamble const *Preamble,
-const std::vector ,
-StringRef Contents, 

[PATCH] D48762: [clangd] codeComplete returns more structured completion items, LSP. NFC.

2018-06-29 Thread Sam McCall via Phabricator via cfe-commits
sammccall added inline comments.



Comment at: clangd/CodeComplete.cpp:259
+  : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments) {
+if (C.SemaResult) {
+  Completion.Name = llvm::StringRef(SemaCCS->getTypedText());

ioeric wrote:
> nit: shall we keep `assert(bool(SemaResult) == bool(SemaCCS));`?
Done (in `add()`, and hoisted the call to `add()` to the top here)



Comment at: clangd/CodeComplete.cpp:322
+}
+if (ExtractDocumentation && Completion.Documentation.empty()) {
+  if (C.IndexResult && C.IndexResult->Detail)

ioeric wrote:
> nit: the documentation for the bundling says `Documentation may contain a 
> combined docstring from all comments`. The implementation seems to take the 
> documentation from the last comment (which seems fine to me), but they should 
> be consistent.
This was meant to be ambiguous ("may") to allow a better implementation later. 
But rewrote it to mention the current behavior as a possibility :-)



Comment at: clangd/CodeComplete.cpp:1145
+Scores.ExcludingName = Relevance.NameMatch
+   ? Scores.Total / Relevance.NameMatch
+   : Scores.Quality;

ioeric wrote:
> nit: this seems to assume that `NameMatch` is a factor of the final score, 
> which seems to be changeable given the abstraction of 
> `evaluateSymbolAndRelevance`. Not sure if there is an alternative to the 
> current approach, but this probably deserves a comment.
Yeah, client-side filtering is the great abstraction-breaker :-(
Added the comment, not sure there's much more to be done.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D48762



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


[PATCH] D48762: [clangd] codeComplete returns more structured completion items, LSP. NFC.

2018-06-29 Thread Eric Liu via Phabricator via cfe-commits
ioeric added a comment.

Looks great! Mostly nits.




Comment at: clangd/CodeComplete.cpp:259
+  : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments) {
+if (C.SemaResult) {
+  Completion.Name = llvm::StringRef(SemaCCS->getTypedText());

nit: shall we keep `assert(bool(SemaResult) == bool(SemaCCS));`?



Comment at: clangd/CodeComplete.cpp:279
+if (auto Inserted = C.headerToInsertIfNotPresent()) {
+  llvm::errs() << "Inserted = " << *Inserted << "\n";
+  Completion.Header = *Inserted;

remove?



Comment at: clangd/CodeComplete.cpp:280
+  llvm::errs() << "Inserted = " << *Inserted << "\n";
+  Completion.Header = *Inserted;
+  // Turn absolute path into a literal string that can be #included.

`Inserted` can be an absolute path which might have long uninteresting prefix.  
It might make sense to use the result from `calculateIncludePath`? 



Comment at: clangd/CodeComplete.cpp:309
+
+  void add(const CompletionCandidate , CodeCompletionString *SemaCCS) {
+Bundled.emplace_back();

nit: It's unclear why `add` is a public interface given that the constructor 
also adds candidate. Might worth a comment. Also, it seems that the interface 
design has been driven by by the bundling logic, so it might also make sense to 
explain a bit on the class level.



Comment at: clangd/CodeComplete.cpp:322
+}
+if (ExtractDocumentation && Completion.Documentation.empty()) {
+  if (C.IndexResult && C.IndexResult->Detail)

nit: the documentation for the bundling says `Documentation may contain a 
combined docstring from all comments`. The implementation seems to take the 
documentation from the last comment (which seems fine to me), but they should 
be consistent.



Comment at: clangd/CodeComplete.cpp:346
+
+  template 
+  const std::string *onlyValue() const {

nit: this might worth a comment. it's unclear what this does by just looking at 
the name.



Comment at: clangd/CodeComplete.cpp:1145
+Scores.ExcludingName = Relevance.NameMatch
+   ? Scores.Total / Relevance.NameMatch
+   : Scores.Quality;

nit: this seems to assume that `NameMatch` is a factor of the final score, 
which seems to be changeable given the abstraction of 
`evaluateSymbolAndRelevance`. Not sure if there is an alternative to the 
current approach, but this probably deserves a comment.



Comment at: clangd/CodeComplete.cpp:1161
 
-  CompletionItem toCompletionItem(const CompletionCandidate::Bundle ,
-  const CompletionItemScores ) {
-CodeCompletionString *SemaCCS = nullptr;
-std::string FrontDocComment;
-if (auto *SR = Bundle.front().SemaResult) {
-  SemaCCS = Recorder->codeCompletionString(*SR);
-  if (Opts.IncludeComments) {
-assert(Recorder->CCSema);
-FrontDocComment = getDocComment(Recorder->CCSema->getASTContext(), *SR,
-/*CommentsFromHeader=*/false);
-  }
+  CodeCompletion toCompletionItem(const CompletionCandidate::Bundle ) {
+llvm::Optional Builder;

nit: toCompletionItem might be ambiguous now that this returns `CodeCompletion`.



Comment at: clangd/CodeComplete.h:88
+  // Qualifiers that must be inserted before the name (e.g. base::).
+  std::string Qualifiers;
+  // Details to be displayed following the name. Not inserted.

Give that this field has caused confusion before, would it make sense to make 
the name a bit more concrete like `RequiredQualifier` or `InsertedQualifier`?



Comment at: clangd/CodeComplete.h:106
+  unsigned BundleSize;
+  // The header through which this symbol should be included.
+  // Empty for non-symbol completions.

Would this be an absolute path or an include path?



Comment at: clangd/CodeComplete.h:140
+  std::vector Completions;
+  bool More = false;
+};

I found `Result.More` a bit not straightforward. Maybe `HasMore`?


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D48762



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


[PATCH] D48762: [clangd] codeComplete returns more structured completion items, LSP. NFC.

2018-06-29 Thread Sam McCall via Phabricator via cfe-commits
sammccall added a comment.

@jkorous FYI: this may be interesting from an XPC perspective - it'd be easy to 
serialize the LSP-style struct, or the more detailed one if that's useful.
LSP will be more stable of course :-)


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D48762



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


[PATCH] D48762: [clangd] codeComplete returns more structured completion items, LSP. NFC.

2018-06-29 Thread Sam McCall via Phabricator via cfe-commits
sammccall created this revision.
sammccall added a reviewer: ioeric.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.

LSP has some presentational fields with limited semantics (e.g. 'detail') and
doesn't provide a good place to return information like namespace.

Some places where more detailed information is useful:

- tools like quality analysis
- alternate frontends that aren't strictly LSP
- code completion unit tests

In this patch, ClangdServer::codeComplete still return LSP CompletionList, but
I plan to switch that soon (should be a no-op for ClangdLSPServer).

Deferring this makes it clear that we don't change behavior (tests stay the
same) and also keeps the API break to a small patch which can be reverted.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D48762

Files:
  clangd/ClangdServer.cpp
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Protocol.h

Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -668,20 +668,6 @@
   Snippet = 2,
 };
 
-/// Provides details for how a completion item was scored.
-/// This can be used for client-side filtering of completion items as the
-/// user keeps typing.
-/// This is a clangd extension.
-struct CompletionItemScores {
-  /// The score that items are ranked by.
-  /// This is filterScore * symbolScore.
-  float finalScore = 0.f;
-  /// How the partial identifier matched filterText. [0-1]
-  float filterScore = 0.f;
-  /// How the symbol fits, ignoring the partial identifier.
-  float symbolScore = 0.f;
-};
-
 struct CompletionItem {
   /// The label of this completion item. By default also the text that is
   /// inserted when selecting this completion.
@@ -702,9 +688,6 @@
   /// When `falsy` the label is used.
   std::string sortText;
 
-  /// Details about the quality of this completion item. (clangd extension)
-  llvm::Optional scoreInfo;
-
   /// A string that should be used when filtering a set of completion items.
   /// When `falsy` the label is used.
   std::string filterText;
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -75,15 +75,78 @@
   const SymbolIndex *Index = nullptr;
 };
 
+// Semi-structured representation of a code-complete suggestion for our C++ API.
+// We don't use the LSP structures here (unlike most features) as we want
+// to expose more data to allow for more precise testing and evaluation.
+struct CodeCompletion {
+  // The unqualified name of the symbol or other completion item.
+  std::string Name;
+  // The scope qualifier for the symbol name. e.g. "ns1::ns2::"
+  // Empty for non-symbol completions. Not inserted, but may be displayed.
+  std::string Scope;
+  // Qualifiers that must be inserted before the name (e.g. base::).
+  std::string Qualifiers;
+  // Details to be displayed following the name. Not inserted.
+  std::string Signature;
+  // Text to be inserted following the name, in snippet format.
+  std::string SnippetSuffix;
+  // Type to be displayed for this completion.
+  std::string ReturnType;
+  std::string Documentation;
+  CompletionItemKind Kind = CompletionItemKind::Missing;
+  // This completion item may represent several symbols that can be inserted in
+  // the same way, such as function overloads. In this case BundleSize > 1, and
+  // the following fields are summaries:
+  //  - Signature is e.g. "(...)" for functions.
+  //  - SnippetSuffix is similarly e.g. "(${0})".
+  //  - ReturnType may be empty
+  //  - Documentation may contain a combined docstring from all comments.
+  // Other fields should apply equally to all bundled completions.
+  unsigned BundleSize;
+  // The header through which this symbol should be included.
+  // Empty for non-symbol completions.
+  std::string Header;
+  // Present if Header is set and should be inserted to use this item.
+  llvm::Optional HeaderInsertion;
+
+  // Scores are used to rank completion items.
+  struct Scores {
+// The score that items are ranked by.
+float Total = 0.f;
+
+// The finalScore with the fuzzy name match score excluded.
+// When filtering client-side, editors should calculate the new fuzzy score,
+// whose scale is 0-1 (with 1 = prefix match, special case 2 = exact match),
+// and recompute finalScore = fuzzyScore * symbolScore.
+float ExcludingName = 0.f;
+
+// Component scores that contributed to the final score:
+
+// Quality describes how important we think this candidate is,
+// independent of the query.
+// e.g. symbols with lots of incoming references have higher quality.
+float Quality = 0.f;
+// Relevance describes how well this candidate matched the query.
+// e.g. symbols from nearby files have higher relevance.
+float Relevance = 0.f;
+  };
+  Scores Score;
+
+  // Serialize this to an LSP completion item. This is a lossy operation.
+