mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-10-31 12:42:34 +00:00 
			
		
		
		
	Fix completion order: Sort after cache.
This commit is contained in:
		
							parent
							
								
									1109c486c6
								
							
						
					
					
						commit
						66af432946
					
				| @ -46,33 +46,6 @@ unsigned GetCompletionPriority(const CXCompletionString& str, | |||||||
|   return priority; |   return priority; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool CompareLsCompletionItem(const lsCompletionItem &item1, |  | ||||||
|                              const lsCompletionItem &item2) |  | ||||||
| { |  | ||||||
|   if (item1.pos_ != item2.pos_) |  | ||||||
|     return item1.pos_ < item2.pos_; |  | ||||||
|   if (item1.priority_ != item2.priority_) |  | ||||||
|     return item1.priority_ < item2.priority_; |  | ||||||
|   if (item1.label.length() != item2.label.length()) |  | ||||||
|     return item1.label.length() < item2.label.length(); |  | ||||||
|   return item1.label < item2.label; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <typename T> |  | ||||||
| char* tofixedbase64(T input, char* out) { |  | ||||||
|   const char* digits = |  | ||||||
|       "./0123456789" |  | ||||||
|       "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |  | ||||||
|       "abcdefghijklmnopqrstuvwxyz"; |  | ||||||
|   int len = (sizeof(T) * 8 - 1) / 6 + 1; |  | ||||||
|   for (int i = len - 1; i >= 0; i--) { |  | ||||||
|     out[i] = digits[input % 64]; |  | ||||||
|     input /= 64; |  | ||||||
|   } |  | ||||||
|   out[len] = '\0'; |  | ||||||
|   return out; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
| bool IsCallKind(CXCursorKind kind) { | bool IsCallKind(CXCursorKind kind) { | ||||||
|   switch (kind) { |   switch (kind) { | ||||||
| @ -476,9 +449,6 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { | |||||||
|             ls_completion_item.documentation = ToString( |             ls_completion_item.documentation = ToString( | ||||||
|                 clang_getCompletionBriefComment(result.CompletionString)); |                 clang_getCompletionBriefComment(result.CompletionString)); | ||||||
| 
 | 
 | ||||||
|             ls_completion_item.pos_ = |  | ||||||
|                 ls_completion_item.label.find(request->existing_text); |  | ||||||
| 
 |  | ||||||
|             ls_completion_item.priority_ = |             ls_completion_item.priority_ = | ||||||
|                 GetCompletionPriority(result.CompletionString, result.CursorKind, |                 GetCompletionPriority(result.CompletionString, result.CursorKind, | ||||||
|                                       ls_completion_item.label); |                                       ls_completion_item.label); | ||||||
| @ -486,12 +456,6 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { | |||||||
|             ls_result.push_back(ls_completion_item); |             ls_result.push_back(ls_completion_item); | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           // order all items and set |sortText|
 |  | ||||||
|           std::sort(ls_result.begin(), ls_result.end(), CompareLsCompletionItem); |  | ||||||
|           char buf[16]; |  | ||||||
|           for (size_t i = 0; i < ls_result.size(); ++i) |  | ||||||
|             ls_result[i].sortText = tofixedbase64(i, buf); |  | ||||||
| 
 |  | ||||||
|           timer.ResetAndPrint("[complete] Building " + |           timer.ResetAndPrint("[complete] Building " + | ||||||
|                               std::to_string(ls_result.size()) + |                               std::to_string(ls_result.size()) + | ||||||
|                               " completion results"); |                               " completion results"); | ||||||
| @ -588,7 +552,6 @@ ClangCompleteManager::~ClangCompleteManager() {} | |||||||
| 
 | 
 | ||||||
| void ClangCompleteManager::CodeComplete( | void ClangCompleteManager::CodeComplete( | ||||||
|     const lsTextDocumentPositionParams& completion_location, |     const lsTextDocumentPositionParams& completion_location, | ||||||
|     const std::string &existing_text, |  | ||||||
|     const OnComplete& on_complete) { |     const OnComplete& on_complete) { | ||||||
|   completion_request_.WithLock( |   completion_request_.WithLock( | ||||||
|       [&](std::unique_ptr<CompletionRequest>& request_storage) { |       [&](std::unique_ptr<CompletionRequest>& request_storage) { | ||||||
| @ -599,7 +562,6 @@ void ClangCompleteManager::CodeComplete( | |||||||
|         // Make the request send out code completion information.
 |         // Make the request send out code completion information.
 | ||||||
|         request_storage->document = completion_location.textDocument; |         request_storage->document = completion_location.textDocument; | ||||||
|         request_storage->position = completion_location.position; |         request_storage->position = completion_location.position; | ||||||
|         request_storage->existing_text = existing_text; |  | ||||||
|         request_storage->on_complete = on_complete; |         request_storage->on_complete = on_complete; | ||||||
|       }); |       }); | ||||||
| } | } | ||||||
|  | |||||||
| @ -57,7 +57,6 @@ struct ClangCompleteManager { | |||||||
|   struct CompletionRequest { |   struct CompletionRequest { | ||||||
|     lsTextDocumentIdentifier document; |     lsTextDocumentIdentifier document; | ||||||
|     optional<lsPosition> position; |     optional<lsPosition> position; | ||||||
|     std::string existing_text; |  | ||||||
|     OnComplete on_complete;  // May be null/empty.
 |     OnComplete on_complete;  // May be null/empty.
 | ||||||
|     bool emit_diagnostics = false; |     bool emit_diagnostics = false; | ||||||
|   }; |   }; | ||||||
| @ -72,7 +71,6 @@ struct ClangCompleteManager { | |||||||
|   // Start a code completion at the given location. |on_complete| will run when
 |   // Start a code completion at the given location. |on_complete| will run when
 | ||||||
|   // completion results are available. |on_complete| may run on any thread.
 |   // completion results are available. |on_complete| may run on any thread.
 | ||||||
|   void CodeComplete(const lsTextDocumentPositionParams& completion_location, |   void CodeComplete(const lsTextDocumentPositionParams& completion_location, | ||||||
|                     const std::string &existing_text, |  | ||||||
|                     const OnComplete& on_complete); |                     const OnComplete& on_complete); | ||||||
|   // Request a diagnostics update.
 |   // Request a diagnostics update.
 | ||||||
|   void DiagnosticsUpdate(const lsTextDocumentIdentifier& document); |   void DiagnosticsUpdate(const lsTextDocumentIdentifier& document); | ||||||
|  | |||||||
| @ -36,11 +36,39 @@ struct Out_TextDocumentComplete | |||||||
| }; | }; | ||||||
| MAKE_REFLECT_STRUCT(Out_TextDocumentComplete, jsonrpc, id, result); | MAKE_REFLECT_STRUCT(Out_TextDocumentComplete, jsonrpc, id, result); | ||||||
| 
 | 
 | ||||||
|  | bool CompareLsCompletionItem(const lsCompletionItem &item1, | ||||||
|  |                              const lsCompletionItem &item2) | ||||||
|  | { | ||||||
|  |   if (item1.pos_ != item2.pos_) | ||||||
|  |     return item1.pos_ < item2.pos_; | ||||||
|  |   if (item1.priority_ != item2.priority_) | ||||||
|  |     return item1.priority_ < item2.priority_; | ||||||
|  |   if (item1.label.length() != item2.label.length()) | ||||||
|  |     return item1.label.length() < item2.label.length(); | ||||||
|  |   return item1.label < item2.label; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <typename T> | ||||||
|  | char* tofixedbase64(T input, char* out) { | ||||||
|  |   const char* digits = | ||||||
|  |       "./0123456789" | ||||||
|  |       "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||||||
|  |       "abcdefghijklmnopqrstuvwxyz"; | ||||||
|  |   int len = (sizeof(T) * 8 - 1) / 6 + 1; | ||||||
|  |   for (int i = len - 1; i >= 0; i--) { | ||||||
|  |     out[i] = digits[input % 64]; | ||||||
|  |     input /= 64; | ||||||
|  |   } | ||||||
|  |   out[len] = '\0'; | ||||||
|  |   return out; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Pre-filters completion responses before sending to vscode. This results in a
 | // Pre-filters completion responses before sending to vscode. This results in a
 | ||||||
| // significantly snappier completion experience as vscode is easily overloaded
 | // significantly snappier completion experience as vscode is easily overloaded
 | ||||||
| // when given 1000+ completion items.
 | // when given 1000+ completion items.
 | ||||||
| void FilterCompletionResponse(Out_TextDocumentComplete* complete_response, | void SortAndFilterCompletionResponse( | ||||||
|                               const std::string& complete_text) { |     Out_TextDocumentComplete* complete_response, | ||||||
|  |     const std::string& complete_text) { | ||||||
| // Used to inject more completions.
 | // Used to inject more completions.
 | ||||||
| #if false | #if false | ||||||
|   const size_t kNumIterations = 250; |   const size_t kNumIterations = 250; | ||||||
| @ -57,32 +85,40 @@ void FilterCompletionResponse(Out_TextDocumentComplete* complete_response, | |||||||
| 
 | 
 | ||||||
|   auto& items = complete_response->result.items; |   auto& items = complete_response->result.items; | ||||||
| 
 | 
 | ||||||
|  |   // Find the appearance of |complete_text| in all candidates.
 | ||||||
|  |   bool found = false; | ||||||
|  |   for (auto &item : items) { | ||||||
|  |     item.pos_ = item.label.find(complete_text); | ||||||
|  |     if (item.pos_ == 0 && item.label.length() == complete_text.length()) | ||||||
|  |       found = true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // If found, remove all candidates that do not start with it.
 | ||||||
|  |   if (!complete_text.empty() && found) { | ||||||
|  |     auto filter = [](const lsCompletionItem& item) { | ||||||
|  |       return item.pos_ != 0; | ||||||
|  |     }; | ||||||
|  |     items.erase(std::remove_if(items.begin(), items.end(), filter), | ||||||
|  |                 items.end()); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   // If the text doesn't start with underscore,
 |   // If the text doesn't start with underscore,
 | ||||||
|   // remove all candidates that start with underscore.
 |   // remove all candidates that start with underscore.
 | ||||||
|   if (!complete_text.empty() && complete_text[0] != '_') { |   if (!complete_text.empty() && complete_text[0] != '_') { | ||||||
|     items.erase(std::remove_if(items.begin(), items.end(), |     auto filter = [](const lsCompletionItem& item) { | ||||||
|                                [](const lsCompletionItem& item) { |       return item.label[0] == '_'; | ||||||
|                                  return item.label[0] == '_'; |     }; | ||||||
|                                }), |     items.erase(std::remove_if(items.begin(), items.end(), filter), | ||||||
|                 items.end()); |                 items.end()); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // find the exact text
 |   // Order all items and set |sortText|.
 | ||||||
|   const bool found = !complete_text.empty() && |   std::sort(items.begin(), items.end(), CompareLsCompletionItem); | ||||||
|                      std::any_of(items.begin(), items.end(), |   char buf[16]; | ||||||
|                                  [&](const lsCompletionItem& item) { |   for (size_t i = 0; i < items.size(); ++i) | ||||||
|                                    return item.pos_ == 0 && |     items[i].sortText = tofixedbase64(i, buf); | ||||||
|                                        item.label.length() == complete_text.length(); |  | ||||||
|                                  }); |  | ||||||
|   // If found, remove all candidates that do not start with it.
 |  | ||||||
|   if (found) { |  | ||||||
|     items.erase(std::remove_if(items.begin(), items.end(), |  | ||||||
|                                [&](const lsCompletionItem& item) { |  | ||||||
|                                  return item.pos_ != 0; |  | ||||||
|                                }), |  | ||||||
|                 items.end()); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|  |   // If there are too many results...
 | ||||||
|   const size_t kMaxResultSize = 100u; |   const size_t kMaxResultSize = 100u; | ||||||
|   if (items.size() > kMaxResultSize) { |   if (items.size() > kMaxResultSize) { | ||||||
|     if (complete_text.empty()) { |     if (complete_text.empty()) { | ||||||
| @ -96,7 +132,7 @@ void FilterCompletionResponse(Out_TextDocumentComplete* complete_response, | |||||||
| 
 | 
 | ||||||
|       // Find literal matches first.
 |       // Find literal matches first.
 | ||||||
|       for (const auto& item : items) { |       for (const auto& item : items) { | ||||||
|         if (item.label.find(complete_text) != std::string::npos) { |         if (item.pos_ != std::string::npos) { | ||||||
|           // Don't insert the same completion entry.
 |           // Don't insert the same completion entry.
 | ||||||
|           if (!inserted.insert(item.InsertedContent()).second) |           if (!inserted.insert(item.InsertedContent()).second) | ||||||
|             continue; |             continue; | ||||||
| @ -178,7 +214,7 @@ struct TextDocumentCompletionHandler : MessageHandler { | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       FilterCompletionResponse(&out, buffer_line); |       SortAndFilterCompletionResponse(&out, buffer_line); | ||||||
|       QueueManager::WriteStdout(IpcId::TextDocumentCompletion, out); |       QueueManager::WriteStdout(IpcId::TextDocumentCompletion, out); | ||||||
|     } else { |     } else { | ||||||
|       bool is_global_completion = false; |       bool is_global_completion = false; | ||||||
| @ -198,7 +234,7 @@ struct TextDocumentCompletionHandler : MessageHandler { | |||||||
|             out.result.items = results; |             out.result.items = results; | ||||||
| 
 | 
 | ||||||
|             // Emit completion results.
 |             // Emit completion results.
 | ||||||
|             FilterCompletionResponse(&out, existing_completion); |             SortAndFilterCompletionResponse(&out, existing_completion); | ||||||
|             QueueManager::WriteStdout(IpcId::TextDocumentCompletion, out); |             QueueManager::WriteStdout(IpcId::TextDocumentCompletion, out); | ||||||
| 
 | 
 | ||||||
|             // Cache completion results.
 |             // Cache completion results.
 | ||||||
| @ -243,7 +279,7 @@ struct TextDocumentCompletionHandler : MessageHandler { | |||||||
|           callback(global_code_complete_cache->cached_results_, |           callback(global_code_complete_cache->cached_results_, | ||||||
|                    true /*is_cached_result*/); |                    true /*is_cached_result*/); | ||||||
|         }); |         }); | ||||||
|         clang_complete->CodeComplete(request->params, existing_completion, freshen_global); |         clang_complete->CodeComplete(request->params, freshen_global); | ||||||
|       } else if (non_global_code_complete_cache->IsCacheValid( |       } else if (non_global_code_complete_cache->IsCacheValid( | ||||||
|                      request->params)) { |                      request->params)) { | ||||||
|         non_global_code_complete_cache->WithLock([&]() { |         non_global_code_complete_cache->WithLock([&]() { | ||||||
| @ -251,7 +287,7 @@ struct TextDocumentCompletionHandler : MessageHandler { | |||||||
|                    true /*is_cached_result*/); |                    true /*is_cached_result*/); | ||||||
|         }); |         }); | ||||||
|       } else { |       } else { | ||||||
|         clang_complete->CodeComplete(request->params, existing_completion, callback); |         clang_complete->CodeComplete(request->params, callback); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -160,7 +160,7 @@ struct TextDocumentSignatureHelpHandler : MessageHandler { | |||||||
|         callback(signature_cache->cached_results_, true /*is_cached_result*/); |         callback(signature_cache->cached_results_, true /*is_cached_result*/); | ||||||
|       }); |       }); | ||||||
|     } else { |     } else { | ||||||
|       clang_complete->CodeComplete(params, search, std::move(callback)); |       clang_complete->CodeComplete(params, std::move(callback)); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user