1:- module(lsp_methods,[
    2
    3  ]).    4
    5:- use_module(library(log4p)).    6:- use_module(jsonrpc/server).    7:- use_module(capabilities).    8:- use_module(errors).    9:- use_module(hover).   10:- use_module(symbols).   11:- use_module(pls_index).   12
   13% Initialization
   14:- server_method(prolog_language_server, initialize, pls_initialize).   15:- server_method(prolog_language_server, initialized, pls_initialized).   16
   17% Utility
   18:- server_method(prolog_language_server, echo, pls_echo).   19:- server_method(prolog_language_server, crash, pls_crash).   20:- server_method(prolog_language_server, methods, pls_methods).   21:- server_method(prolog_language_server, '$/setTrace', pls_trace).   22
   23% Text Document Synchronization
   24:- server_method(prolog_language_server, 'textDocument/didOpen', pls_text_document_did_open).   25:- server_method(prolog_language_server, 'textDocument/didChange', pls_text_document_did_change).   26:- server_method(prolog_language_server, 'textDocument/didClose', pls_text_document_did_close).   27
   28% Language features
   29:- server_method(prolog_language_server, 'textDocument/documentSymbol', pls_document_document_symbol).   30:- server_method(prolog_language_server, 'textDocument/hover', pls_text_document_hover).   31:- server_method(prolog_language_server, 'textDocument/references', pls_text_document_references).   32:- server_method(prolog_language_server, 'textDocument/definition', pls_text_document_definition).   33:- server_method(prolog_language_server, 'textDocument/completion', pls_text_document_completion).   34:- server_method(prolog_language_server, 'textDocument/resolve', pls_text_document_resolve).   35
   36% Shutdown
   37:- server_method(prolog_language_server, shutdown, pls_shutdown).   38:- server_method(prolog_language_server, exit, pls_exit).   39
   40:- server_method(prolog_language_server, 'workspace/symbol', pls_workspace_symbols).   41
   42% 
   43% State
   44% 
   45
   46% language_server_state(Server, State)
   47:- dynamic language_server_state/2.   48
   49get_server_state(Server, State) :-
   50  language_server_state(Server, State).
   51
   52set_server_state(Server, State) :-
   53  retractall(language_server_state(Server, _)),
   54  debug("Setting server %w state to %w", [Server, State]),
   55  assertz(language_server_state(Server, State)),
   56  debug("Server %w state set to %w", [Server, State]).
   57
   58require_server_state(Server, Required) :-
   59  get_server_state(Server, Required), 
   60  debug('for %w required state of %w is met', [Server, Required]),
   61  !.
   62
   63require_server_state(Server, Required) :-
   64  get_server_state(Server, State),
   65  debug('for %w required state of %w but is %w', [Server, Required, State]),
   66  throw(invalid_state(Required, State)).
   67
   68% -------------------
   69% 
   70% Methods
   71% 
   72% - - - - - - - - - -
   73
   74%
   75% Initialization
   76% 
   77
   78pls_initialize(Server, Params, Result) :-
   79  TraceLevel = Params.get(trace, "off"),
   80  set_trace_level(TraceLevel),
   81  \+ get_server_state(Server, _),
   82  server_capabilities(Capabilities),
   83  Result = _{
   84    capabilities: Capabilities,
   85    serverInfo: _{name: "Prolog"}
   86    },
   87  set_server_state(Server, initializing),
   88  begin_indexing(Params).
   89
   90pls_initialized(Server, _Params) :-
   91  require_server_state(Server, initializing),
   92  set_server_state(Server, initialized).
   93
   94% 
   95% Utility
   96% 
   97
   98pls_echo(Server, Params, Result) :-
   99  require_server_state(Server, initialized),
  100  jsonrpc_server:echo(Server, Params, Result).
  101
  102pls_crash(Server, Result, Params) :-
  103  require_server_state(Server, initialized),
  104  jsonrpc_server:crash(Server, Result, Params).
  105
  106pls_methods(Server, _Params, Result) :-
  107  % require_server_state(Server, initialized),
  108  findall(
  109    Method, 
  110    clause(jsonrpc_methods:declared_server_method(_:Server, _:Method, _:_),_),
  111    Methods
  112    ),
  113  Result = Methods.
  114
  115pls_trace(_Server, Params) :-
  116  TraveLevel = Params.value,
  117  set_trace_level(TraveLevel).
  118
  119% Text Document sync
  120pls_text_document_did_open(_Server, Params) :-
  121  Document = Params.textDocument,
  122  Document = _{
  123    uri: URI,
  124    languageId: Language,
  125    version: Version,
  126    text: Content
  127  },
  128  % Check its a prolog document
  129  store_document(URI, Language, Version, Content),
  130  index_text(URI).
  131
  132pls_text_document_did_change(_Server, Params) :-
  133  Document = Params.textDocument,
  134  Changes = Params.contentChanges,
  135  URI = Document.uri,
  136  get_document_property(URI, language(Language)),
  137  forall(
  138    member(Change, Changes),
  139    store_document(URI, Language, Document.version, Change.text)  
  140    ),
  141  index_text(URI).
  142
  143pls_text_document_did_close(_Server, Params) :-
  144  Document = Params.textDocument,
  145  URI = Document.uri,
  146  clear_document_content(URI).
  147
  148% Other text document
  149
  150pls_document_document_symbol(_Server, Params, Result) :-
  151  Document = Params.textDocument,
  152  URI = Document.uri,
  153  document_symbols(URI, Result).
  154
  155pls_text_document_hover(_Server, Params, Result) :-
  156  Document = Params.textDocument,
  157  URI = Document.uri,
  158  Position = Params.position,
  159  debug("Looking in %w for hover at %q",[URI, Position]),
  160  ( hover_for_position(URI, Position, Hover)
  161    -> Result = Hover
  162    ; Result = null
  163    ).
  164
  165pls_text_document_definition(_Server, Params, Result) :-
  166  Document = Params.textDocument,
  167  URI = Document.uri,
  168  Position = Params.position,
  169  debug("Looking in %w for definition at %q",[URI, Position]),
  170  ( definition_for_position(URI, Position, Definitions)
  171    -> Result = Definitions
  172    ; Result = null
  173    ).
  174
  175% Find references for defined predicates
  176pls_text_document_references(_Server, Params, Result) :-
  177  Document = Params.textDocument,
  178  URI = Document.uri,
  179  Position = Params.position,
  180  debug("Looking in %w for references at %q",[URI, Position]),
  181  ( references_for_position(URI, Position, References)
  182    -> Result = References
  183    ; Result = null
  184    ).
  185
  186pls_text_document_completion(_Server, Params, Result) :-
  187  Document = Params.textDocument,
  188  URI = Document.uri,
  189  Position = Params.position,
  190  completions_for_position(URI, Position, Completions),
  191  Result = Completions.
  192
  193pls_text_document_resolve(_Server, Params, Result) :-
  194  Result = Params.
  195
  196% Shutdown
  197
  198pls_shutdown(Server, _Params, Result) :-  
  199  require_server_state(Server, initialized),
  200  % we don't actually shut anything down right now
  201  Result = _{},
  202  set_server_state(Server, shutting_down).
  203
  204pls_exit(Server, _Params) :-
  205  require_server_state(Server, shutting_down),
  206  % we don't actually exit anything down right now
  207  request_exit_server(Server).
  208
  209pls_workspace_symbols(_Server, Params, Result) :-
  210  workspace_symbols(Params.query, Symbols),
  211  Result = Symbols.
  212
  213% --- helpers ---
  214
  215set_trace_level("off") :-
  216  log4p:set_global_log_level(info),
  217  jsonrpc_logging:disable_jsonrpc_tracing.
  218
  219set_trace_level("messages") :-
  220  log4p:set_global_log_level(debug),
  221  jsonrpc_logging:disable_jsonrpc_tracing.
  222
  223set_trace_level("verbose") :-
  224  log4p:set_global_log_level(trace),
  225  jsonrpc_logging:enable_jsonrpc_tracing