summaryrefslogtreecommitdiff
path: root/graphics/asymptote/lspserv.h
blob: 74a21659a34d82bdb7bdc1648738eb1bef63f1ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#pragma once
#include "common.h"
#include "symbolmaps.h"

#include "LibLsp/lsp/ProtocolJsonHandler.h"
#include "LibLsp/lsp/AbsolutePath.h"

#include "LibLsp/JsonRpc/Endpoint.h"
#include "LibLsp/JsonRpc/TcpServer.h"
#include "LibLsp/JsonRpc/Condition.h"

// header for requests
#include "LibLsp/lsp/textDocument/hover.h"
#include "LibLsp/lsp/general/initialize.h"
#include "LibLsp/lsp/general/shutdown.h"
#include "LibLsp/lsp/textDocument/declaration_definition.h"
#include "LibLsp/lsp/textDocument/colorPresentation.h"

//header for notifs
#include "LibLsp/lsp/general/exit.h"
#include "LibLsp/lsp/general/initialized.h"
#include "LibLsp/lsp/textDocument/did_open.h"
#include "LibLsp/lsp/textDocument/did_change.h"
#include "LibLsp/lsp/textDocument/did_save.h"
#include "LibLsp/lsp/textDocument/did_close.h"

//everything else
#include <functional>
#include <cctype>
#include <unordered_map>
#include "LibLsp/JsonRpc/stream.h"

namespace absyntax
{
  class block;
}

namespace AsymptoteLsp
{
  class istream : public lsp::base_istream<std::istream>
  {
  public:
    istream(std::istream& ist) : lsp::base_istream<std::istream>(ist)
    {
    }

    std::string what() override
    {
      return "AsymptoteLSP_istream";
    }
  };

  class ostream : public lsp::base_ostream<std::ostream>
  {
  public:
    ostream(std::ostream& ost) : lsp::base_ostream<std::ostream>(ost)
    {
    }

    std::string what() override
    {
      return "AsymptoteLSP_ostream";
    }
  };

  template<typename TLeft, typename TRight>
  inline optional<std::pair<optional<TLeft>, optional<TRight>>> opt_left(TLeft const& opt)
  {
    return boost::make_optional(std::make_pair(optional<TLeft>(opt), optional<TRight>()));
  }

  template<typename TLeft, typename TRight>
  inline optional<std::pair<optional<TLeft>, optional<TRight>>> opt_right(TRight const& opt)
  {
    return boost::make_optional(std::make_pair(optional<TLeft>(), optional<TRight>(opt)));
  }

  TextDocumentHover::Either fromString(std::string const &str);
  TextDocumentHover::Either fromMarkedStr(lsMarkedString const& markedString);
  TextDocumentHover::Either fromMarkedStr(std::string const& str, std::string const& language="asymptote");
  TextDocumentHover::Either fromMarkedStr(std::vector<std::string> const& stringList,
                                          std::string const& language="asymptote");

  std::string wslDos2Unix(std::string const& dosPath);
  std::string wslUnix2Dos(std::string const& unixPath);
  std::string getDocIdentifierRawPath(lsTextDocumentIdentifier const&);

  typedef std::unordered_map<std::string, std::unique_ptr<SymbolContext>> SymContextFilemap;

  class LspLog: public lsp::Log
  {
  public:
    void log(Level level, std::string&& msg) override;
    void log(Level level, const std::string& msg) override;
    void log(Level level, std::wstring&& msg) override;
    void log(Level level, const std::wstring& msg) override;
  };


  class AsymptoteLspServer
  {
  public:
    AsymptoteLspServer(shared_ptr<lsp::ProtocolJsonHandler> const& jsonHandler,
                       shared_ptr<GenericEndpoint> const& endpoint, LspLog& log);
    AsymptoteLspServer(RemoteEndPoint* remoteEndPt,
                       shared_ptr<lsp::ProtocolJsonHandler> const& jsonHandler,
                       shared_ptr<GenericEndpoint> const& endpoint, LspLog& log);
    virtual ~AsymptoteLspServer();

    // copy constructors + copy assignment op
    AsymptoteLspServer(AsymptoteLspServer& sv) = delete;
    AsymptoteLspServer& operator=(AsymptoteLspServer const& sv) = delete;

    // move constructors and move assignment op
    AsymptoteLspServer(AsymptoteLspServer&& sv) = delete;
    AsymptoteLspServer& operator=(AsymptoteLspServer&& sv) = delete;

    virtual void start();
    void startIO(std::istream& in=cin, std::ostream& out=cout);

  protected:
    td_hover::response handleHoverRequest(td_hover::request const&);
    virtual td_initialize::response handleInitailizeRequest(td_initialize::request const&);
    virtual td_shutdown::response handleShutdownRequest(td_shutdown::request const&);
    td_definition::response handleDefnRequest(td_definition::request const&);
    td_documentColor::response handleDocColorRequest(td_documentColor::request const&);
    td_colorPresentation::response handleColorPresRequest(td_colorPresentation::request const&);


    virtual void onInitialized(Notify_InitializedNotification::notify& notify);
    virtual void onExit(Notify_Exit::notify& notify);
    void onChange(Notify_TextDocumentDidChange::notify& notify);
    void onOpen(Notify_TextDocumentDidOpen::notify& notify);
    void onSave(Notify_TextDocumentDidSave::notify& notify);
    void onClose(Notify_TextDocumentDidClose::notify& notify);

    void generateMissingTrees(std::string const& inputFile);

    void initializeRequestFn();
    void initializeNotifyFn();

    void reloadFile(std::string const&);
    void updateFileContentsTable(std::string const& filename);
    void updateFileContentsTable(std::string const& filename, std::istream& in);

    // logging functions
    void log(lsp::Log::Level const& level, std::string const& message);
    void logInfo(std::string const& message);
    void logWarning(std::string const& message);
    void logError(std::string const& message);

    SymbolContext* reloadFileRaw(std::string const&, bool const& fillTree=true);
    SymbolContext* fromRawPath(lsTextDocumentIdentifier const& identifier);
    SymbolContext* reloadFileRaw(absyntax::block* blk, std::string const& rawPath, bool const& fillTree=true);
    virtual void clearVariables();
    Condition<bool> serverClosed;

  private:
    unique_ptr<RemoteEndPoint> internalREP;
  protected:
    // [owned, ptr]
    RemoteEndPoint* const remoteEndPoint;

  private:
    shared_ptr<lsp::ProtocolJsonHandler> pjh;
    shared_ptr<GenericEndpoint> ep;
    SymbolContext* plainCtx=NULL;
    LspLog& _log;

    unique_ptr<SymContextFilemap> symmapContextsPtr;
    unique_ptr<unordered_map<std::string, std::vector<std::string>>> fileContentsPtr;
    std::string plainFile;
  };

  class TCPAsymptoteLSPServer : public lsp::TcpServer, public AsymptoteLspServer
  {
  public:
    TCPAsymptoteLSPServer(
            std::string const& addr, std::string const& port,
            shared_ptr<lsp::ProtocolJsonHandler> const& jsonHandler,
            shared_ptr<GenericEndpoint> const& endpoint, LspLog& log);
    ~TCPAsymptoteLSPServer() override;

  protected:
    void start() override;
    Condition<bool> serverInitialized;
  };
}