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 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
#pragma once
#include "Core/Lock.h"
#include "Compiler/Thread.h"
#include "Connection.h"
#include "File.h"
#include "Test.h"
#include "Repl.h"
#include "WorkQueue.h"
#include "RangeSet.h"
#include "Core/Queue.h"
namespace storm {
namespace server {
STORM_PKG(core.lang.server);
// Since the preprocessor does not know ::String, we make a typedef.
typedef ::String CString;
/**
* Class encapsulating all state in the server communication.
*/
class Server : public ObjectOn<Compiler> {
STORM_CLASS;
public:
// Create.
STORM_CTOR Server(Connection *c);
// Run the server loop. Blocks until the server is detached.
void STORM_FN run();
// Run delayed work.
void runWork(WorkItem *item);
private:
// Connection.
Connection *conn;
// Open files.
Map<Nat, File *> *files;
// Keep track of some symbols we need.
Symbol *quit;
Symbol *supported;
Symbol *open;
Symbol *edit;
Symbol *point;
Symbol *close;
Symbol *error;
Symbol *indent;
Symbol *chunkSz;
Symbol *test;
Symbol *debug;
Symbol *recolor;
Symbol *color;
Symbol *level;
Symbol *as;
Symbol *t;
Symbol *completeName;
Symbol *documentation;
Symbol *replAvailable;
Symbol *replEval;
Symbol *runSym;
Symbol *reload;
// Any test state required now?
Test *testState;
// Work queue.
WorkQueue *work;
// Lock taken whenever we call into a file. This is needed since thread switches can
// occur when we call into code possibly implemented in Storm. Otherwise, background
// tasks could interfere with message processing.
Lock *lock;
// Keep track of the color symbols used.
Array<Symbol *> *colorSyms;
/**
* Task posted to a Repl.
*/
class ReplTask {
STORM_VALUE;
public:
// Create.
STORM_CTOR ReplTask(Str *input, Package *context)
: input(input), context(context) {}
// Input.
Str *input;
// Context.
Package *context;
};
/**
* Remember state for language REPLs.
*/
class RunningRepl : public ObjectOn<Compiler> {
STORM_CLASS;
public:
// Create.
STORM_CTOR RunningRepl(Server *server, Function *create);
// Owning Server.
Server *server;
// Function used to create the Repl.
Function *createFn;
// The Repl instance. Note: This might be null if the Repl was terminated.
Repl *repl;
// Work items that are pending. Whenever the array is non-empty, a thread is
// responsible for processing items for the queue.
Queue<ReplTask> *work;
// Main thread.
void CODECALL run();
};
// Keep track of REPL instances running.
Map<Str *, RunningRepl *> *repls;
// Find the symbol to be used for a specific color.
Symbol *colorSym(syntax::TokenColor color);
// Process a message.
Bool process(SExpr *msg);
// Handle specific messages.
void onSupported(SExpr *msg);
void onOpen(SExpr *msg);
void onEdit(SExpr *msg);
void onPoint(SExpr *msg);
void onClose(SExpr *msg);
void onError(SExpr *msg);
void onIndent(SExpr *msg);
void onChunkSz(SExpr *msg);
void onTest(SExpr *msg);
void onDebug(SExpr *msg);
void onColor(SExpr *msg);
void onComplete(SExpr *msg);
void onDocumentation(SExpr *msg);
void onReplAvailable(SExpr *msg);
void onReplEval(SExpr *msg);
void onRun(SExpr *msg);
void onReload(SExpr *msg);
// Execute a function on a separate UThread.
void CODECALL execThread(Function *fn, Bool sendResult);
// Send updates for 'range' in 'file'.
void update(File *file, Range range);
// Size of the chunks to send to the client.
static const Nat defaultChunkChars = 8000;
Nat chunkChars;
// Send updates for 'range' in 'file', sending one reasonabley-sized chunk now and
// scheduling the rest for later.
void updateLater(File *file, Range range);
// Convenience functions for printing things.
void print(Str *s);
void print(const wchar *s);
void print(const CString &s);
// Helpers for providing documentation.
void findDoc(Name *name, Scope scope, Array<SExpr *> *out);
SExpr *formatDoc(Named *entity);
SExpr *formatValue(Str *name, Named *entity, Bool ref);
SExpr *formatValue(Str *name, Value v);
SExpr *formatNote(const DocNote ¬e);
};
/**
* Schedule file updates.
*
* Stores a number of ranges to be updated so that multiple updaters do not interfere and
* cause too much data to be sent on each idle period.
*/
class UpdateFileRange : public WorkItem {
STORM_CLASS;
public:
STORM_CTOR UpdateFileRange(File *file);
STORM_CTOR UpdateFileRange(File *file, Range range);
// Add a range.
void STORM_FN add(Range range);
// Merge with another item.
Bool STORM_FN merge(WorkItem *o);
// Execute this item.
virtual Range STORM_FN run(WorkQueue *q);
private:
// Set to update.
RangeSet *update;
};
}
}
|