mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-07-16 15:52:55 +03:00
More LSP work.
This commit is contained in:
@@ -195,7 +195,7 @@ class EE_API Process {
|
||||
void* mProcess{ nullptr };
|
||||
bool mShuttingDown{ false };
|
||||
bool mIsAsync{ false };
|
||||
size_t mBufferSize{ 131072 };
|
||||
ssize_t mBufferSize{ 131072 };
|
||||
std::thread mStdOutThread;
|
||||
std::thread mStdErrThread;
|
||||
Mutex mStdInMutex;
|
||||
|
||||
@@ -27,7 +27,8 @@ class EE_API ThreadPool : NonCopyable {
|
||||
|
||||
virtual ~ThreadPool();
|
||||
|
||||
void run( const std::function<void()>& func, const std::function<void()>& doneCallback );
|
||||
void run(
|
||||
const std::function<void()>& func, const std::function<void()>& doneCallback = []() {} );
|
||||
|
||||
Uint32 numThreads() const;
|
||||
|
||||
|
||||
@@ -188,26 +188,32 @@ void Process::startAsyncRead( ReadFn readStdOut, ReadFn readStdErr ) {
|
||||
if ( stdOutFd ) {
|
||||
mStdOutThread = std::thread( [this, stdOutFd]() {
|
||||
DWORD n;
|
||||
std::unique_ptr<char[]> buffer( new char[mBufferSize] );
|
||||
std::string buffer;
|
||||
buffer.resize( mBufferSize );
|
||||
while ( !mShuttingDown ) {
|
||||
BOOL bSuccess = ReadFile( stdOutFd, static_cast<CHAR*>( buffer.get() ),
|
||||
BOOL bSuccess = ReadFile( stdOutFd, static_cast<CHAR*>( &buffer[0] ),
|
||||
static_cast<DWORD>( mBufferSize ), &n, nullptr );
|
||||
if ( !bSuccess || n == 0 )
|
||||
break;
|
||||
mReadStdOutFn( buffer.get(), static_cast<size_t>( n ) );
|
||||
if ( n < mBufferSize - 1 )
|
||||
buffer[n] = '\0';
|
||||
mReadStdOutFn( buffer.c_str(), static_cast<size_t>( n ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
if ( stdErrFd ) {
|
||||
mStdErrThread = std::thread( [this, stdErrFd]() {
|
||||
DWORD n;
|
||||
std::unique_ptr<char[]> buffer( new char[mBufferSize] );
|
||||
std::string buffer;
|
||||
buffer.resize( mBufferSize );
|
||||
while ( !mShuttingDown ) {
|
||||
BOOL bSuccess = ReadFile( stdErrFd, static_cast<CHAR*>( buffer.get() ),
|
||||
BOOL bSuccess = ReadFile( stdErrFd, static_cast<CHAR*>( &buffer[0] ),
|
||||
static_cast<DWORD>( mBufferSize ), &n, nullptr );
|
||||
if ( !bSuccess || n == 0 )
|
||||
break;
|
||||
mReadStdErrFn( buffer.get(), static_cast<size_t>( n ) );
|
||||
if ( n < mBufferSize - 1 )
|
||||
buffer[n] = '\0';
|
||||
mReadStdErrFn( buffer.c_str(), static_cast<size_t>( n ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
@@ -232,7 +238,8 @@ void Process::startAsyncRead( ReadFn readStdOut, ReadFn readStdErr ) {
|
||||
: -1;
|
||||
pollfds.back().events = POLLIN;
|
||||
}
|
||||
auto buffer = std::unique_ptr<char[]>( new char[mBufferSize] );
|
||||
std::string buffer;
|
||||
buffer.resize( mBufferSize );
|
||||
bool anyOpen = !pollfds.empty();
|
||||
while ( anyOpen && !mShuttingDown && errno != EINTR ) {
|
||||
int res = poll( pollfds.data(), static_cast<nfds_t>( pollfds.size() ), 100 );
|
||||
@@ -241,12 +248,14 @@ void Process::startAsyncRead( ReadFn readStdOut, ReadFn readStdErr ) {
|
||||
for ( size_t i = 0; i < pollfds.size(); ++i ) {
|
||||
if ( pollfds[i].fd >= 0 ) {
|
||||
if ( pollfds[i].revents & POLLIN ) {
|
||||
const ssize_t n = read( pollfds[i].fd, buffer.get(), mBufferSize );
|
||||
const ssize_t n = read( pollfds[i].fd, &buffer[0], mBufferSize );
|
||||
if ( n > 0 ) {
|
||||
if ( n < mBufferSize - 1 )
|
||||
buffer[n] = '\0';
|
||||
if ( fdIsStdOut[i] )
|
||||
mReadStdOutFn( buffer.get(), static_cast<size_t>( n ) );
|
||||
mReadStdOutFn( buffer.c_str(), static_cast<size_t>( n ) );
|
||||
else
|
||||
mReadStdErrFn( buffer.get(), static_cast<size_t>( n ) );
|
||||
mReadStdErrFn( buffer.c_str(), static_cast<size_t>( n ) );
|
||||
} else if ( n < 0 && errno != EINTR && errno != EAGAIN &&
|
||||
errno != EWOULDBLOCK ) {
|
||||
pollfds[i].fd = -1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "plugins/autocomplete/autocompleteplugin.hpp"
|
||||
#include "plugins/formatter/formatterplugin.hpp"
|
||||
#include "plugins/linter/linterplugin.hpp"
|
||||
//#include "plugins/lsp/lspclientplugin.hpp"
|
||||
// #include "plugins/lsp/lspclientplugin.hpp"
|
||||
#include "version.hpp"
|
||||
#include <algorithm>
|
||||
#include <args/args.hxx>
|
||||
@@ -369,7 +369,7 @@ void App::initPluginManager() {
|
||||
mPluginManager->registerPlugin( LinterPlugin::Definition() );
|
||||
mPluginManager->registerPlugin( FormatterPlugin::Definition() );
|
||||
mPluginManager->registerPlugin( AutoCompletePlugin::Definition() );
|
||||
//mPluginManager->registerPlugin( LSPClientPlugin::Definition() );
|
||||
// mPluginManager->registerPlugin( LSPClientPlugin::Definition() );
|
||||
}
|
||||
|
||||
void App::loadConfig( const LogLevel& logLevel ) {
|
||||
|
||||
@@ -26,6 +26,10 @@ LSPClientPlugin::~LSPClientPlugin() {
|
||||
}
|
||||
}
|
||||
|
||||
void LSPClientPlugin::update( UICodeEditor* ) {
|
||||
mClientManager.updateDirty();
|
||||
}
|
||||
|
||||
void LSPClientPlugin::load( const PluginManager* pluginManager ) {
|
||||
std::vector<std::string> paths;
|
||||
std::string path( pluginManager->getResourcesPath() + "plugins/lspclient.json" );
|
||||
|
||||
@@ -33,6 +33,8 @@ class LSPClientPlugin : public UICodeEditorPlugin {
|
||||
|
||||
virtual ~LSPClientPlugin();
|
||||
|
||||
virtual void update( UICodeEditor* );
|
||||
|
||||
std::string getId() { return Definition().id; }
|
||||
|
||||
std::string getTitle() { return Definition().name; }
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
#include "lspclientserver.hpp"
|
||||
#include "lspclientservermanager.hpp"
|
||||
#include <algorithm>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/iostreamstring.hpp>
|
||||
#include <eepp/system/lock.hpp>
|
||||
#include <eepp/system/log.hpp>
|
||||
#include <eepp/system/sys.hpp>
|
||||
#include <eepp/ui/doc/textdocument.hpp>
|
||||
@@ -69,13 +74,14 @@ static json textDocumentParams( const URI& document, int version = -1 ) {
|
||||
return textDocumentParams( versionedTextDocumentIdentifier( document, version ) );
|
||||
}
|
||||
|
||||
LSPClientServer::LSPClientServer( const LSPDefinition& lsp, const std::string& rootPath ) :
|
||||
mLSP( lsp ), mRootPath( rootPath ) {}
|
||||
LSPClientServer::LSPClientServer( LSPClientServerManager* manager, const String::HashType& id,
|
||||
const LSPDefinition& lsp, const std::string& rootPath ) :
|
||||
mManager( manager ), mId( id ), mLSP( lsp ), mRootPath( rootPath ) {}
|
||||
|
||||
LSPClientServer::~LSPClientServer() {
|
||||
for ( const auto& client : mClients ) {
|
||||
Lock l( mClientsMutex );
|
||||
for ( const auto& client : mClients )
|
||||
client.first->unregisterClient( client.second.get() );
|
||||
}
|
||||
}
|
||||
|
||||
bool LSPClientServer::start() {
|
||||
@@ -91,8 +97,9 @@ bool LSPClientServer::start() {
|
||||
}
|
||||
|
||||
bool LSPClientServer::registerDoc( const std::shared_ptr<TextDocument>& doc ) {
|
||||
for ( auto& cdoc : mDocs ) {
|
||||
if ( cdoc.get() == doc.get() ) {
|
||||
Lock l( mClientsMutex );
|
||||
for ( TextDocument* cdoc : mDocs ) {
|
||||
if ( cdoc == doc.get() ) {
|
||||
if ( mClients.find( doc.get() ) == mClients.end() ) {
|
||||
mClients[doc.get()] = std::make_unique<LSPDocumentClient>( this, doc.get() );
|
||||
return true;
|
||||
@@ -102,11 +109,19 @@ bool LSPClientServer::registerDoc( const std::shared_ptr<TextDocument>& doc ) {
|
||||
}
|
||||
|
||||
mClients[doc.get()] = std::make_unique<LSPDocumentClient>( this, doc.get() );
|
||||
mDocs.emplace_back( doc );
|
||||
mDocs.emplace_back( doc.get() );
|
||||
doc->registerClient( mClients[doc.get()].get() );
|
||||
return true;
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::cancel( int reqid ) {
|
||||
if ( mHandlers.erase( reqid ) > 0 ) {
|
||||
auto params = json{ MEMBER_ID, reqid };
|
||||
return write( newRequest( "$/cancelRequest", params ) );
|
||||
}
|
||||
return RequestHandle();
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::write( const json& msg,
|
||||
const GenericReplyHandler& h,
|
||||
const GenericReplyHandler& eh,
|
||||
@@ -157,6 +172,85 @@ LSPClientServer::RequestHandle LSPClientServer::didOpen( const URI& document,
|
||||
return send( newRequest( "textDocument/didOpen", params ) );
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::didOpen( TextDocument* doc, int version ) {
|
||||
if ( doc->isDirty() ) {
|
||||
IOStreamString text;
|
||||
doc->save( text, true );
|
||||
return didOpen( doc->getURI(), text.getStream(), version );
|
||||
} else {
|
||||
std::string text;
|
||||
FileSystem::fileGet( doc->getFilePath(), text );
|
||||
return didOpen( doc->getURI(), text, version );
|
||||
}
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::didSave( const URI& document,
|
||||
const std::string& text ) {
|
||||
auto params = textDocumentParams( document );
|
||||
if ( !text.empty() )
|
||||
params["text"] = text;
|
||||
return send( newRequest( "textDocument/didSave", params ) );
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::didSave( TextDocument* doc ) {
|
||||
return didSave( doc->getURI(), doc->getText( doc->getDocRange() ).toUtf8() );
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::didChange( const URI& document, int version,
|
||||
const std::string& text ) {
|
||||
auto params = textDocumentParams( document, version );
|
||||
if ( !text.empty() )
|
||||
params["contentChanges"] = { json{ MEMBER_TEXT, text } };
|
||||
return send( newRequest( "textDocument/didChange", params ) );
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::didChange( TextDocument* doc ) {
|
||||
Lock l( mClientsMutex );
|
||||
auto it = mClients.find( doc );
|
||||
if ( it != mClients.end() )
|
||||
return didChange( doc->getURI(), it->second->getVersion(),
|
||||
doc->getText( doc->getDocRange() ).toUtf8() );
|
||||
return RequestHandle();
|
||||
}
|
||||
|
||||
void LSPClientServer::updateDirty() {
|
||||
Lock l( mClientsMutex );
|
||||
for ( auto& client : mClients ) {
|
||||
if ( client.second->isDirty() ) {
|
||||
TextDocument* doc = client.first;
|
||||
mManager->getThreadPool()->run( [this, doc]() { didChange( doc ); } );
|
||||
client.second->resetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::didClose( const URI& document ) {
|
||||
auto params = textDocumentParams( document );
|
||||
return send( newRequest( "textDocument/didClose", params ) );
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::didClose( TextDocument* doc ) {
|
||||
auto ret = didClose( doc->getURI() );
|
||||
Lock l( mClientsMutex );
|
||||
if ( mClients.erase( doc ) > 0 ) {
|
||||
auto it = std::find( mDocs.begin(), mDocs.end(), doc );
|
||||
if ( it != mDocs.end() )
|
||||
mDocs.erase( it );
|
||||
// No more docs are being used, close the LSP
|
||||
if ( mDocs.empty() )
|
||||
mManager->notifyClose( mId );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
LSPClientServerManager* LSPClientServer::getManager() const {
|
||||
return mManager;
|
||||
}
|
||||
|
||||
const std::shared_ptr<ThreadPool>& LSPClientServer::getThreadPool() const {
|
||||
return mManager->getThreadPool();
|
||||
}
|
||||
|
||||
LSPClientServer::RequestHandle LSPClientServer::documentSymbols( const URI& document,
|
||||
const GenericReplyHandler& h,
|
||||
const GenericReplyHandler& eh ) {
|
||||
|
||||
@@ -18,6 +18,8 @@ using namespace EE::UI::Doc;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
class LSPClientServerManager;
|
||||
|
||||
class LSPClientServer {
|
||||
public:
|
||||
template <typename T> using ReplyHandler = std::function<void( const T& )>;
|
||||
@@ -37,7 +39,8 @@ class LSPClientServer {
|
||||
}
|
||||
};
|
||||
|
||||
LSPClientServer( const LSPDefinition& lsp, const std::string& rootPath );
|
||||
LSPClientServer( LSPClientServerManager* manager, const String::HashType& id,
|
||||
const LSPDefinition& lsp, const std::string& rootPath );
|
||||
|
||||
~LSPClientServer();
|
||||
|
||||
@@ -45,27 +48,52 @@ class LSPClientServer {
|
||||
|
||||
bool registerDoc( const std::shared_ptr<TextDocument>& doc );
|
||||
|
||||
int cancel( int id ) { return id; }
|
||||
LSPClientServerManager* getManager() const;
|
||||
|
||||
const std::shared_ptr<ThreadPool>& getThreadPool() const;
|
||||
|
||||
LSPClientServer::RequestHandle cancel( int id );
|
||||
|
||||
RequestHandle send( const json& msg, const GenericReplyHandler& h = nullptr,
|
||||
const GenericReplyHandler& eh = nullptr );
|
||||
|
||||
LSPClientServer::RequestHandle didOpen( const URI& document, const std::string& text,
|
||||
int version );
|
||||
|
||||
const LSPDefinition& getDefinition() const { return mLSP; }
|
||||
|
||||
LSPClientServer::RequestHandle documentSymbols( const URI& document,
|
||||
const GenericReplyHandler& h,
|
||||
const GenericReplyHandler& eh );
|
||||
|
||||
LSPClientServer::RequestHandle didOpen( const URI& document, const std::string& text,
|
||||
int version );
|
||||
|
||||
LSPClientServer::RequestHandle didOpen( TextDocument* doc, int version );
|
||||
|
||||
LSPClientServer::RequestHandle didSave( const URI& document, const std::string& text );
|
||||
|
||||
LSPClientServer::RequestHandle didSave( TextDocument* doc );
|
||||
|
||||
LSPClientServer::RequestHandle didClose( const URI& document );
|
||||
|
||||
LSPClientServer::RequestHandle didClose( TextDocument* document );
|
||||
|
||||
LSPClientServer::RequestHandle didChange( const URI& document, int version,
|
||||
const std::string& text );
|
||||
|
||||
LSPClientServer::RequestHandle didChange( TextDocument* doc );
|
||||
|
||||
void updateDirty();
|
||||
|
||||
protected:
|
||||
LSPClientServerManager* mManager{ nullptr };
|
||||
String::HashType mId;
|
||||
LSPDefinition mLSP;
|
||||
std::string mRootPath;
|
||||
Process mProcess;
|
||||
std::vector<std::shared_ptr<TextDocument>> mDocs;
|
||||
std::vector<TextDocument*> mDocs;
|
||||
std::map<TextDocument*, std::unique_ptr<LSPDocumentClient>> mClients;
|
||||
std::map<int, std::pair<GenericReplyHandler, GenericReplyHandler>> mHandlers;
|
||||
Mutex mClientsMutex;
|
||||
|
||||
int mLastMsgId{ 0 };
|
||||
|
||||
void readStdOut( const char* bytes, size_t n );
|
||||
|
||||
@@ -39,9 +39,10 @@ LSPClientServerManager::supportsLSP( const std::shared_ptr<TextDocument>& doc )
|
||||
return lsps;
|
||||
}
|
||||
|
||||
std::shared_ptr<LSPClientServer>
|
||||
LSPClientServerManager::runLSPServer( const LSPDefinition& lsp, const std::string& rootPath ) {
|
||||
auto server = std::make_shared<LSPClientServer>( lsp, rootPath );
|
||||
std::unique_ptr<LSPClientServer>
|
||||
LSPClientServerManager::runLSPServer( const String::HashType& id, const LSPDefinition& lsp,
|
||||
const std::string& rootPath ) {
|
||||
auto server = std::make_unique<LSPClientServer>( this, id, lsp, rootPath );
|
||||
server->start();
|
||||
return server;
|
||||
}
|
||||
@@ -76,17 +77,23 @@ void LSPClientServerManager::tryRunServer( const std::shared_ptr<TextDocument>&
|
||||
auto lspName = lsp.name.empty() ? lsp.command : lsp.name;
|
||||
String::HashType id = String::hash( lspName + "|" + lsp.language + "|" + rootPath );
|
||||
auto clientIt = mClients.find( id );
|
||||
std::shared_ptr<LSPClientServer> server;
|
||||
LSPClientServer* server = nullptr;
|
||||
if ( clientIt == mClients.end() ) {
|
||||
server = runLSPServer( lsp, rootPath );
|
||||
if ( server.use_count() )
|
||||
mClients[id] = server;
|
||||
std::unique_ptr<LSPClientServer> serverUP = runLSPServer( id, lsp, rootPath );
|
||||
if ( ( server = serverUP.get() ) )
|
||||
mClients[id] = std::move( serverUP );
|
||||
} else {
|
||||
server = clientIt->second;
|
||||
server = clientIt->second.get();
|
||||
}
|
||||
if ( server.use_count() ) {
|
||||
if ( server )
|
||||
server->registerDoc( doc );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LSPClientServerManager::notifyClose( const String::HashType& id ) {
|
||||
auto it = mClients.find( id );
|
||||
if ( it != mClients.end() ) {
|
||||
mClients.erase( it );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,4 +105,13 @@ size_t LSPClientServerManager::clientCount() const {
|
||||
return mClients.size();
|
||||
}
|
||||
|
||||
const std::shared_ptr<ThreadPool>& LSPClientServerManager::getThreadPool() const {
|
||||
return mPool;
|
||||
}
|
||||
|
||||
void LSPClientServerManager::updateDirty() {
|
||||
for ( auto& server : mClients )
|
||||
server.second->updateDirty();
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -20,19 +20,28 @@ class LSPClientServerManager {
|
||||
|
||||
size_t clientCount() const;
|
||||
|
||||
const std::shared_ptr<ThreadPool>& getThreadPool() const;
|
||||
|
||||
void updateDirty();
|
||||
|
||||
protected:
|
||||
friend class LSPClientServer;
|
||||
|
||||
std::shared_ptr<ThreadPool> mPool;
|
||||
std::map<String::HashType, std::shared_ptr<LSPClientServer>> mClients;
|
||||
std::map<String::HashType, std::unique_ptr<LSPClientServer>> mClients;
|
||||
std::vector<LSPDefinition> mLSPs;
|
||||
|
||||
std::vector<LSPDefinition> supportsLSP( const std::shared_ptr<TextDocument>& doc );
|
||||
|
||||
std::shared_ptr<LSPClientServer> runLSPServer( const LSPDefinition& lsp,
|
||||
std::unique_ptr<LSPClientServer> runLSPServer( const String::HashType& id,
|
||||
const LSPDefinition& lsp,
|
||||
const std::string& rootPath );
|
||||
|
||||
std::string findRootPath( const LSPDefinition& lsp, const std::shared_ptr<TextDocument>& doc );
|
||||
|
||||
void tryRunServer( const std::shared_ptr<TextDocument>& doc );
|
||||
|
||||
void notifyClose( const String::HashType& id );
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -10,17 +10,13 @@ namespace ecode {
|
||||
LSPDocumentClient::LSPDocumentClient( LSPClientServer* server, TextDocument* doc ) :
|
||||
mServer( server ), mDoc( doc ) {
|
||||
notifyOpen();
|
||||
mServer->documentSymbols(
|
||||
mDoc->getURI(),
|
||||
[&]( const json& ) {
|
||||
|
||||
},
|
||||
[&]( const json& ) {
|
||||
|
||||
} );
|
||||
}
|
||||
|
||||
void LSPDocumentClient::onDocumentTextChanged() {}
|
||||
void LSPDocumentClient::onDocumentTextChanged() {
|
||||
mModified = true;
|
||||
++mVersion;
|
||||
mLastModified.restart();
|
||||
}
|
||||
|
||||
void LSPDocumentClient::onDocumentUndoRedo( const TextDocument::UndoRedo& /*eventType*/ ) {}
|
||||
|
||||
@@ -33,24 +29,42 @@ void LSPDocumentClient::onDocumentLineCountChange( const size_t& /*lastCount*/,
|
||||
|
||||
void LSPDocumentClient::onDocumentLineChanged( const Int64& /*lineIndex*/ ) {}
|
||||
|
||||
void LSPDocumentClient::onDocumentSaved( TextDocument* ) {}
|
||||
void LSPDocumentClient::onDocumentSaved( TextDocument* ) {
|
||||
mServer->getThreadPool()->run( [&]() { mServer->didSave( mDoc ); } );
|
||||
}
|
||||
|
||||
void LSPDocumentClient::onDocumentClosed( TextDocument* ) {}
|
||||
void LSPDocumentClient::onDocumentClosed( TextDocument* ) {
|
||||
mServer->didClose( mDoc );
|
||||
mDoc = nullptr;
|
||||
}
|
||||
|
||||
void LSPDocumentClient::onDocumentDirtyOnFileSystem( TextDocument* ) {}
|
||||
|
||||
void LSPDocumentClient::onDocumentMoved( TextDocument* ) {}
|
||||
|
||||
bool LSPDocumentClient::isDirty() const {
|
||||
return mModified && mLastModified.getElapsedTime() > Milliseconds( 250.f );
|
||||
}
|
||||
|
||||
void LSPDocumentClient::resetDirty() {
|
||||
mModified = false;
|
||||
}
|
||||
|
||||
TextDocument* LSPDocumentClient::getDoc() const {
|
||||
return mDoc;
|
||||
}
|
||||
|
||||
LSPClientServer* LSPDocumentClient::getServer() const {
|
||||
return mServer;
|
||||
}
|
||||
|
||||
int LSPDocumentClient::getVersion() const {
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
void LSPDocumentClient::notifyOpen() {
|
||||
if ( mDoc->isDirty() ) {
|
||||
IOStreamString text;
|
||||
mDoc->save( text, true );
|
||||
mServer->didOpen( mDoc->getURI(), text.getStream(), mVersion );
|
||||
} else {
|
||||
std::string text;
|
||||
FileSystem::fileGet( mDoc->getFilePath(), text );
|
||||
mServer->didOpen( mDoc->getURI(), text, mVersion );
|
||||
}
|
||||
eeASSERT( mDoc );
|
||||
mServer->didOpen( mDoc, ++mVersion );
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#ifndef ECODE_LSPDOCUMENTCLIENT_HPP
|
||||
#define ECODE_LSPDOCUMENTCLIENT_HPP
|
||||
|
||||
#include <eepp/system/clock.hpp>
|
||||
#include <eepp/ui/doc/textdocument.hpp>
|
||||
|
||||
using namespace EE;
|
||||
using namespace EE::System;
|
||||
using namespace EE::UI::Doc;
|
||||
|
||||
namespace ecode {
|
||||
@@ -25,11 +27,24 @@ class LSPDocumentClient : public TextDocument::Client {
|
||||
virtual void onDocumentDirtyOnFileSystem( TextDocument* );
|
||||
virtual void onDocumentMoved( TextDocument* );
|
||||
|
||||
bool isDirty() const;
|
||||
|
||||
void notifyOpen();
|
||||
|
||||
void resetDirty();
|
||||
|
||||
TextDocument* getDoc() const;
|
||||
|
||||
LSPClientServer* getServer() const;
|
||||
|
||||
int getVersion() const;
|
||||
|
||||
protected:
|
||||
LSPClientServer* mServer{ nullptr };
|
||||
TextDocument* mDoc{ nullptr };
|
||||
bool mModified{ false };
|
||||
int mVersion{ 0 };
|
||||
Clock mLastModified;
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
Reference in New Issue
Block a user