ConnectionFromClient.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "ConnectionFromClient.h"
  8. #include <AK/Debug.h>
  9. #include <AK/HashMap.h>
  10. #include <LibGUI/TextDocument.h>
  11. namespace LanguageServers {
  12. static HashMap<int, RefPtr<ConnectionFromClient>> s_connections;
  13. ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket)
  14. : IPC::ConnectionFromClient<LanguageClientEndpoint, LanguageServerEndpoint>(*this, move(socket), 1)
  15. {
  16. s_connections.set(1, *this);
  17. }
  18. void ConnectionFromClient::die()
  19. {
  20. s_connections.remove(client_id());
  21. exit(0);
  22. }
  23. void ConnectionFromClient::greet(DeprecatedString const& project_root)
  24. {
  25. m_filedb.set_project_root(project_root);
  26. if (unveil(project_root.characters(), "r") < 0) {
  27. perror("unveil");
  28. exit(1);
  29. }
  30. if (unveil(nullptr, nullptr) < 0) {
  31. perror("unveil");
  32. exit(1);
  33. }
  34. }
  35. void ConnectionFromClient::file_opened(DeprecatedString const& filename, IPC::File const& file)
  36. {
  37. if (m_filedb.is_open(filename)) {
  38. return;
  39. }
  40. m_filedb.add(filename, file.take_fd());
  41. m_autocomplete_engine->file_opened(filename);
  42. }
  43. void ConnectionFromClient::file_edit_insert_text(DeprecatedString const& filename, DeprecatedString const& text, i32 start_line, i32 start_column)
  44. {
  45. dbgln_if(LANGUAGE_SERVER_DEBUG, "InsertText for file: {}", filename);
  46. dbgln_if(LANGUAGE_SERVER_DEBUG, "Text: {}", text);
  47. dbgln_if(LANGUAGE_SERVER_DEBUG, "[{}:{}]", start_line, start_column);
  48. m_filedb.on_file_edit_insert_text(filename, text, start_line, start_column);
  49. m_autocomplete_engine->on_edit(filename);
  50. }
  51. void ConnectionFromClient::file_edit_remove_text(DeprecatedString const& filename, i32 start_line, i32 start_column, i32 end_line, i32 end_column)
  52. {
  53. dbgln_if(LANGUAGE_SERVER_DEBUG, "RemoveText for file: {}", filename);
  54. dbgln_if(LANGUAGE_SERVER_DEBUG, "[{}:{} - {}:{}]", start_line, start_column, end_line, end_column);
  55. m_filedb.on_file_edit_remove_text(filename, start_line, start_column, end_line, end_column);
  56. m_autocomplete_engine->on_edit(filename);
  57. }
  58. void ConnectionFromClient::auto_complete_suggestions(CodeComprehension::ProjectLocation const& location)
  59. {
  60. dbgln_if(LANGUAGE_SERVER_DEBUG, "AutoCompleteSuggestions for: {} {}:{}", location.file, location.line, location.column);
  61. auto document = m_filedb.get_document(location.file);
  62. if (!document) {
  63. dbgln("file {} has not been opened", location.file);
  64. return;
  65. }
  66. GUI::TextPosition autocomplete_position = { (size_t)location.line, (size_t)max(location.column, location.column - 1) };
  67. Vector<CodeComprehension::AutocompleteResultEntry> suggestions = m_autocomplete_engine->get_suggestions(location.file, autocomplete_position);
  68. async_auto_complete_suggestions(move(suggestions));
  69. }
  70. void ConnectionFromClient::set_file_content(DeprecatedString const& filename, DeprecatedString const& content)
  71. {
  72. dbgln_if(LANGUAGE_SERVER_DEBUG, "SetFileContent: {}", filename);
  73. auto document = m_filedb.get_document(filename);
  74. if (!document) {
  75. m_filedb.add(filename, content);
  76. VERIFY(m_filedb.is_open(filename));
  77. } else {
  78. document->set_text(content.view());
  79. }
  80. VERIFY(m_filedb.is_open(filename));
  81. m_autocomplete_engine->on_edit(filename);
  82. }
  83. void ConnectionFromClient::find_declaration(CodeComprehension::ProjectLocation const& location)
  84. {
  85. dbgln_if(LANGUAGE_SERVER_DEBUG, "FindDeclaration: {} {}:{}", location.file, location.line, location.column);
  86. auto document = m_filedb.get_document(location.file);
  87. if (!document) {
  88. dbgln("file {} has not been opened", location.file);
  89. return;
  90. }
  91. GUI::TextPosition identifier_position = { (size_t)location.line, (size_t)location.column };
  92. auto decl_location = m_autocomplete_engine->find_declaration_of(location.file, identifier_position);
  93. if (!decl_location.has_value()) {
  94. dbgln("could not find declaration");
  95. return;
  96. }
  97. dbgln_if(LANGUAGE_SERVER_DEBUG, "declaration location: {} {}:{}", decl_location.value().file, decl_location.value().line, decl_location.value().column);
  98. async_declaration_location(CodeComprehension::ProjectLocation { decl_location.value().file, decl_location.value().line, decl_location.value().column });
  99. }
  100. void ConnectionFromClient::get_parameters_hint(CodeComprehension::ProjectLocation const& location)
  101. {
  102. dbgln_if(LANGUAGE_SERVER_DEBUG, "GetParametersHint: {} {}:{}", location.file, location.line, location.column);
  103. auto document = m_filedb.get_document(location.file);
  104. if (!document) {
  105. dbgln("file {} has not been opened", location.file);
  106. return;
  107. }
  108. GUI::TextPosition identifier_position = { (size_t)location.line, (size_t)location.column };
  109. auto params = m_autocomplete_engine->get_function_params_hint(location.file, identifier_position);
  110. if (!params.has_value()) {
  111. dbgln("could not get parameters hint");
  112. return;
  113. }
  114. dbgln_if(LANGUAGE_SERVER_DEBUG, "parameters hint:");
  115. for (auto& param : params->params) {
  116. dbgln_if(LANGUAGE_SERVER_DEBUG, "{}", param);
  117. }
  118. dbgln_if(LANGUAGE_SERVER_DEBUG, "Parameter index: {}", params->current_index);
  119. async_parameters_hint_result(params->params, params->current_index);
  120. }
  121. void ConnectionFromClient::get_tokens_info(DeprecatedString const& filename)
  122. {
  123. dbgln_if(LANGUAGE_SERVER_DEBUG, "GetTokenInfo: {}", filename);
  124. auto document = m_filedb.get_document(filename);
  125. if (!document) {
  126. dbgln("file {} has not been opened", filename);
  127. return;
  128. }
  129. auto tokens_info = m_autocomplete_engine->get_tokens_info(filename);
  130. async_tokens_info_result(move(tokens_info));
  131. }
  132. }