diff --git a/include/eepp/system/process.hpp b/include/eepp/system/process.hpp index 570a6f6f5..679b409e6 100644 --- a/include/eepp/system/process.hpp +++ b/include/eepp/system/process.hpp @@ -215,6 +215,8 @@ class EE_API Process { Mutex mStdInMutex; ReadFn mReadStdOutFn; ReadFn mReadStdErrFn; + + size_t readAll( std::string& buffer, bool readErr ); }; }} // namespace EE::System diff --git a/include/eepp/ui/doc/syntaxdefinition.hpp b/include/eepp/ui/doc/syntaxdefinition.hpp index 18c2204e2..3bcd9a7cf 100644 --- a/include/eepp/ui/doc/syntaxdefinition.hpp +++ b/include/eepp/ui/doc/syntaxdefinition.hpp @@ -15,7 +15,7 @@ namespace EE { namespace UI { namespace Doc { template static auto toSyntaxStyleTypeV( const std::vector& s ) noexcept { if constexpr ( std::is_same_v && std::is_same_v ) { - return s; + return std::vector( s ); } else if constexpr ( std::is_same_v && std::is_same_v ) { std::vector v; @@ -34,18 +34,18 @@ struct EE_API SyntaxPattern { std::string syntax{ "" }; - SyntaxPattern( const std::vector& _patterns, const std::string& _type, + SyntaxPattern( std::vector&& _patterns, const std::string& _type, const std::string& _syntax = "" ) : - patterns( _patterns ), - types( toSyntaxStyleTypeV( std::vector{ _type } ) ), + patterns( std::move( _patterns ) ), + types( toSyntaxStyleTypeV( std::vector{ _type } ) ), typesNames( { _type } ), syntax( _syntax ) {} - SyntaxPattern( const std::vector& _patterns, - const std::vector& _types, const std::string& _syntax = "" ) : - patterns( _patterns ), + SyntaxPattern( std::vector&& _patterns, std::vector&& _types, + const std::string& _syntax = "" ) : + patterns( std::move( _patterns ) ), types( toSyntaxStyleTypeV( _types ) ), - typesNames( _types ), + typesNames( std::move( _types ) ), syntax( _syntax ) {} }; @@ -53,10 +53,10 @@ class EE_API SyntaxDefinition { public: SyntaxDefinition(); - SyntaxDefinition( const std::string& languageName, const std::vector& files, - const std::vector& patterns, - const std::unordered_map& symbols = {}, - const std::string& comment = "", const std::vector headers = {}, + SyntaxDefinition( const std::string& languageName, std::vector&& files, + std::vector&& patterns, + UnorderedMap&& symbols = {}, + const std::string& comment = "", std::vector&& headers = {}, const std::string& lspName = "" ); const std::string& getLanguageName() const; @@ -73,7 +73,7 @@ class EE_API SyntaxDefinition { const std::string& getComment() const; - const std::unordered_map& getSymbols() const; + const UnorderedMap& getSymbols() const; SyntaxStyleType getSymbol( const std::string& symbol ) const; @@ -93,7 +93,7 @@ class EE_API SyntaxDefinition { SyntaxDefinition& addSymbols( const std::vector& symbolNames, const SyntaxStyleType& typeName ); - SyntaxDefinition& setSymbols( const std::unordered_map& symbols ); + SyntaxDefinition& setSymbols( const UnorderedMap& symbols ); /** Sets the comment string used for auto-comment functionality. */ SyntaxDefinition& setComment( const std::string& comment ); @@ -128,15 +128,15 @@ class EE_API SyntaxDefinition { void setExtensionPriority( bool hasExtensionPriority ); - std::unordered_map getSymbolNames() const; + UnorderedMap getSymbolNames() const; protected: std::string mLanguageName; String::HashType mLanguageId; std::vector mFiles; std::vector mPatterns; - std::unordered_map mSymbols; - std::unordered_map mSymbolNames; + UnorderedMap mSymbols; + UnorderedMap mSymbolNames; std::string mComment; std::vector mHeaders; std::string mLSPName; diff --git a/src/eepp/system/process.cpp b/src/eepp/system/process.cpp index 9bb97d942..825824ddc 100644 --- a/src/eepp/system/process.cpp +++ b/src/eepp/system/process.cpp @@ -38,10 +38,8 @@ Process::Process( const std::string& command, const Uint32& options, Process::~Process() { mShuttingDown = true; - if ( mProcess && isAlive() ) { - subprocess_init_shutdown( PROCESS_PTR ); + if ( mProcess && isAlive() ) kill(); - } if ( mStdOutThread.joinable() ) mStdOutThread.join(); if ( mStdErrThread.joinable() ) @@ -143,18 +141,7 @@ bool Process::create( const std::string& command, const std::string& args, const } size_t Process::readAllStdOut( std::string& buffer ) { - if ( buffer.empty() ) - buffer.resize( CHUNK_SIZE ); - size_t bytesRead = 0; - size_t totalBytesRead = 0; - totalBytesRead = bytesRead = readStdOut( (char* const)buffer.c_str(), buffer.size() ); - while ( bytesRead != 0 && isAlive() && !mShuttingDown ) { - if ( totalBytesRead + CHUNK_SIZE > buffer.size() ) - buffer.resize( totalBytesRead + CHUNK_SIZE ); - bytesRead = readStdOut( (char* const)buffer.c_str() + totalBytesRead, CHUNK_SIZE ); - totalBytesRead += bytesRead; - } - return totalBytesRead; + return readAll( buffer, false ); } size_t Process::readStdOut( std::string& buffer ) { @@ -167,18 +154,7 @@ size_t Process::readStdOut( char* const buffer, const size_t& size ) { } size_t Process::readAllStdErr( std::string& buffer ) { - if ( buffer.empty() ) - buffer.resize( CHUNK_SIZE ); - size_t bytesRead = 0; - size_t totalBytesRead = 0; - totalBytesRead = bytesRead = readStdErr( (char* const)buffer.c_str(), buffer.size() ); - while ( bytesRead != 0 && isAlive() && !mShuttingDown ) { - if ( totalBytesRead + CHUNK_SIZE > buffer.size() ) - buffer.resize( totalBytesRead + CHUNK_SIZE ); - bytesRead = readStdErr( (char* const)buffer.c_str() + totalBytesRead, CHUNK_SIZE ); - totalBytesRead += bytesRead; - } - return totalBytesRead; + return readAll( buffer, true ); } size_t Process::readStdErr( std::string& buffer ) { @@ -208,6 +184,8 @@ bool Process::join( int* const returnCodeOut ) { } bool Process::kill() { + mShuttingDown = true; + subprocess_init_shutdown( PROCESS_PTR ); eeASSERT( mProcess != nullptr ); if ( PROCESS_PTR->alive ) { destroy(); @@ -249,6 +227,60 @@ const bool& Process::isShuttingDown() { return mShuttingDown; } +size_t Process::readAll( std::string& buffer, bool readErr ) { + eeASSERT( mProcess != nullptr ); + if ( buffer.empty() || buffer.size() < CHUNK_SIZE ) + buffer.resize( CHUNK_SIZE ); + size_t totalBytesRead = 0; +#if EE_PLATFORM == EE_PLATFORM_WIN + while ( !mShuttingDown && isAlive() ) { + unsigned n = + readErr + ? subprocess_read_stderr( PROCESS_PTR, buffer.data() + totalBytesRead, CHUNK_SIZE ) + : subprocess_read_stdout( PROCESS_PTR, buffer.data() + totalBytesRead, CHUNK_SIZE ); + if ( n == 0 ) + break; + totalBytesRead += n; + if ( totalBytesRead + CHUNK_SIZE > buffer.size() ) + buffer.resize( totalBytesRead + CHUNK_SIZE ); + } +#elif defined( EE_PLATFORM_POSIX ) + auto stdOutFd = fileno( readErr ? PROCESS_PTR->stderr_file : PROCESS_PTR->stdout_file ); + pollfd pollfd = {}; + pollfd.fd = + fcntl( stdOutFd, F_SETFL, fcntl( stdOutFd, F_GETFL ) | O_NONBLOCK ) == 0 ? stdOutFd : -1; + pollfd.events = POLLIN; + buffer.resize( mBufferSize ); + bool anyOpen = pollfd.fd != -1; + ssize_t n = 0; + while ( anyOpen && !mShuttingDown && isAlive() && errno != EINTR ) { + int res = poll( &pollfd, static_cast( 1 ), 100 ); + if ( res <= 0 ) + continue; + anyOpen = false; + if ( pollfd.revents & POLLIN ) { + n = read( pollfd.fd, buffer.data() + totalBytesRead, CHUNK_SIZE ); + if ( n > 0 ) { + totalBytesRead += n; + if ( totalBytesRead + CHUNK_SIZE > buffer.size() ) + buffer.resize( totalBytesRead + CHUNK_SIZE ); + } else if ( n == 0 || + ( n < 0 && errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK ) ) { + pollfd.fd = -1; + continue; + } + } + if ( pollfd.revents & ( POLLERR | POLLHUP | POLLNVAL ) ) { + pollfd.fd = -1; + continue; + } + anyOpen = true; + } +#endif + buffer.resize( totalBytesRead ); + return totalBytesRead; +} + void Process::startAsyncRead( ReadFn readStdOut, ReadFn readStdErr ) { eeASSERT( mProcess != nullptr ); mReadStdOutFn = readStdOut; diff --git a/src/eepp/ui/doc/syntaxdefinition.cpp b/src/eepp/ui/doc/syntaxdefinition.cpp index 54bea6ac1..8f2868eed 100644 --- a/src/eepp/ui/doc/syntaxdefinition.cpp +++ b/src/eepp/ui/doc/syntaxdefinition.cpp @@ -7,22 +7,21 @@ namespace EE { namespace UI { namespace Doc { SyntaxDefinition::SyntaxDefinition() {} SyntaxDefinition::SyntaxDefinition( const std::string& languageName, - const std::vector& files, - const std::vector& patterns, - const std::unordered_map& symbols, - const std::string& comment, - const std::vector headers, + std::vector&& files, + std::vector&& patterns, + UnorderedMap&& symbols, + const std::string& comment, std::vector&& headers, const std::string& lspName ) : mLanguageName( languageName ), mLanguageId( String::hash( String::toLower( languageName ) ) ), - mFiles( files ), - mPatterns( patterns ), - mSymbolNames( symbols ), + mFiles( std::move( files ) ), + mPatterns( std::move( patterns ) ), + mSymbolNames( std::move( symbols ) ), mComment( comment ), - mHeaders( headers ), + mHeaders( std::move( headers ) ), mLSPName( lspName.empty() ? String::toLower( mLanguageName ) : lspName ) { - mSymbols.reserve( symbols.size() ); - for ( const auto& symbol : symbols ) + mSymbols.reserve( mSymbolNames.size() ); + for ( const auto& symbol : mSymbolNames ) mSymbols.insert( { symbol.first, toSyntaxStyleType( symbol.second ) } ); } @@ -64,7 +63,7 @@ void SyntaxDefinition::setExtensionPriority( bool hasExtensionPriority ) { mHasExtensionPriority = hasExtensionPriority; } -std::unordered_map SyntaxDefinition::getSymbolNames() const { +UnorderedMap SyntaxDefinition::getSymbolNames() const { return mSymbolNames; } @@ -76,7 +75,7 @@ const std::string& SyntaxDefinition::getComment() const { return mComment; } -const std::unordered_map& SyntaxDefinition::getSymbols() const { +const UnorderedMap& SyntaxDefinition::getSymbols() const { return mSymbols; } @@ -127,7 +126,7 @@ SyntaxDefinition& SyntaxDefinition::addSymbols( const std::vector& } SyntaxDefinition& -SyntaxDefinition::setSymbols( const std::unordered_map& symbols ) { +SyntaxDefinition::setSymbols( const UnorderedMap& symbols ) { mSymbols = symbols; return *this; } diff --git a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp index 1101228d8..0f8a54fa8 100644 --- a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp +++ b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp @@ -1009,7 +1009,7 @@ static void addDart() { static void addNim() { std::vector nim_patterns; - std::unordered_map nim_symbols; + UnorderedMap nim_symbols; const std::vector nim_number_patterns = { "0[bB][01][01_]*", "0o[0-7][0-7_]*", @@ -1083,14 +1083,14 @@ static void addNim() { SyntaxDefinitionManager::instance()->add( { "Nim", { "%.nim$", "%.nims$", "%.nimble$" }, - nim_patterns, - nim_symbols, + std::move( nim_patterns ), + std::move( nim_symbols ), "#", } ); } static void addCMake() { - std::unordered_map cmake_symbols; + UnorderedMap cmake_symbols; const std::vector cmake_keywords{ "ANDROID", "APPLE", "BORLAND", "CACHE", "CYGWIN", "ENV", "GHSMULTI", "IOS", "MINGW", "MSVC", "MSVC10", "MSVC11", @@ -1134,7 +1134,7 @@ static void addCMake() { { { "%${[%a_][%w_]*%}" }, "keyword2" }, { { "[%a_][%w_]*" }, "symbol" }, }, - cmake_symbols, + std::move( cmake_symbols ), "//" } ); } @@ -2041,7 +2041,7 @@ static SyntaxDefinition loadLanguage( const nlohmann::json& json ) { ptrns.emplace_back( pattern["pattern"] ); } } - def.addPattern( SyntaxPattern( ptrns, type, syntax ) ); + def.addPattern( SyntaxPattern( std::move( ptrns ), std::move( type ), syntax ) ); } } if ( json.contains( "symbols" ) ) { diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 34cb66891..f474b1296 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -3321,7 +3321,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe [this]( EE::Window::Window* win ) -> bool { return onCloseRequestCallback( win ); } ); mWindow->setQuitCallback( [this]( EE::Window::Window* win ) { - if ( mWindow->isOpen() ) + if ( win->isOpen() ) closeApp(); } ); diff --git a/src/tools/ecode/plugins/formatter/formatterplugin.cpp b/src/tools/ecode/plugins/formatter/formatterplugin.cpp index ac1e699e5..90902a905 100644 --- a/src/tools/ecode/plugins/formatter/formatterplugin.cpp +++ b/src/tools/ecode/plugins/formatter/formatterplugin.cpp @@ -310,8 +310,7 @@ const std::vector& FormatterPlugin::getFormatters() return mFormatters; } -FormatterPlugin::Formatter -FormatterPlugin::getFormatterForLang( const std::string& lang ) { +FormatterPlugin::Formatter FormatterPlugin::getFormatterForLang( const std::string& lang ) { for ( const auto& formatter : mFormatters ) { for ( const auto& clang : formatter.languages ) { if ( clang == lang ) { @@ -428,14 +427,9 @@ void FormatterPlugin::runFormatter( UICodeEditor* editor, const Formatter& forma String::replaceAll( cmd, "$FILENAME", "\"" + path + "\"" ); Process process; if ( process.create( cmd ) ) { - std::string buffer( 1024, '\0' ); - std::string data; - unsigned bytesRead = 0; int returnCode; - do { - bytesRead = process.readStdOut( buffer ); - data += buffer.substr( 0, bytesRead ); - } while ( bytesRead != 0 && process.isAlive() && !mShuttingDown ); + std::string data; + process.readAllStdOut( data ); if ( mShuttingDown ) { process.kill(); diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index f336dfe60..0c3badf14 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -727,13 +726,15 @@ void LinterPlugin::lintDoc( std::shared_ptr doc ) { return; ScopedOp op( - [this]() { - mWorkMutex.lock(); + [this, doc]() { + std::lock_guard l( mWorkMutex ); mWorkersCount++; }, [this]() { - mWorkersCount--; - mWorkMutex.unlock(); + { + std::lock_guard l( mWorkMutex ); + mWorkersCount--; + } mWorkerCondition.notify_all(); } ); if ( !mReady ) @@ -776,16 +777,26 @@ void LinterPlugin::runLinter( std::shared_ptr doc, const Linter& l std::string cmd( linter.command ); String::replaceAll( cmd, "$FILENAME", "\"" + path + "\"" ); Process process; + TextDocument* docPtr = doc.get(); + ScopedOp op( + [this, &process, &docPtr] { + std::lock_guard l( mRunningProcessesMutex ); + auto found = mRunningProcesses.find( docPtr ); + if ( found != mRunningProcesses.end() ) + found->second->kill(); + mRunningProcesses[docPtr] = &process; + }, + [this, &docPtr] { + std::lock_guard l( mRunningProcessesMutex ); + mRunningProcesses.erase( docPtr ); + } ); + ; + if ( process.create( cmd, Process::getDefaultOptions() | Process::CombinedStdoutStderr, {}, mManager->getWorkspaceFolder() ) ) { - std::string buffer( 1024, '\0' ); - std::string data; - unsigned bytesRead = 0; int returnCode; - do { - bytesRead = process.readStdOut( buffer ); - data += buffer.substr( 0, bytesRead ); - } while ( bytesRead != 0 && process.isAlive() && !mShuttingDown ); + std::string data; + process.readAllStdOut( data ); if ( mShuttingDown ) { process.kill(); diff --git a/src/tools/ecode/plugins/linter/linterplugin.hpp b/src/tools/ecode/plugins/linter/linterplugin.hpp index e407ef071..fecd04110 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.hpp +++ b/src/tools/ecode/plugins/linter/linterplugin.hpp @@ -4,6 +4,7 @@ #include "../pluginmanager.hpp" #include #include +#include #include #include #include @@ -123,6 +124,8 @@ class LinterPlugin : public Plugin { std::condition_variable mWorkerCondition; Int32 mWorkersCount{ 0 }; std::map mKeyBindings; /* cmd, shortcut */ + std::mutex mRunningProcessesMutex; + std::unordered_map mRunningProcesses; bool mHoveringMatch{ false }; bool mEnableLSPDiagnostics{ true }; diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp index 67dea6535..c7f5fdaf2 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp @@ -830,6 +830,12 @@ void LSPClientPlugin::loadLSPConfig( std::vector& lsps, const std if ( j.contains( "config" ) ) { auto& config = j["config"]; + + if ( config.contains( "silent" ) ) + mSilence = config.value( "silent", false ); + else if ( updateConfigFile ) + config["silent"] = mSilence; + if ( config.contains( "hover_delay" ) ) setHoverDelay( Time::fromString( config["hover_delay"].get() ) ); else if ( updateConfigFile ) diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.hpp b/src/tools/ecode/plugins/lsp/lspclientplugin.hpp index 9efebb112..981121082 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.hpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.hpp @@ -84,6 +84,10 @@ class LSPClientPlugin : public Plugin { bool langSupportsSemanticHighlighting( const std::string& lspLang ); + bool isSilent() const { return mSilence; } + + void setSilent( bool silence = true ) { mSilence = silence; } + protected: friend class LSPDocumentClient; friend class LSPClientServer; @@ -102,6 +106,7 @@ class LSPClientPlugin : public Plugin { bool mOldUsingCustomStyling{ false }; bool mSymbolInfoShowing{ false }; bool mSemanticHighlighting{ false }; + bool mSilence{ false }; std::map mKeyBindings; /* cmd, shortcut */ std::map> mDelayedDocs; Uint32 mHoverWaitCb{ 0 }; diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.cpp b/src/tools/ecode/plugins/lsp/lspclientserver.cpp index 1838a281d..501f6922e 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.cpp @@ -416,7 +416,7 @@ struct LSPSymbolInformationTmp { } }; -static LSPSymbolInformationList parseDocumentSymbols( const json& result ) { +static LSPSymbolInformationList parseDocumentSymbols( const json& result, bool isSilent ) { // TODO: Optimize this Clock clock; std::list ret; @@ -468,8 +468,9 @@ static LSPSymbolInformationList parseDocumentSymbols( const json& result ) { for ( const auto& r : ret ) rret.push_back( LSPSymbolInformationTmp::fromTmp( r ) ); - Log::debug( "LSPClientServer - parseDocumentSymbols took: %.2fms", - clock.getElapsedTimeAndReset().asMilliseconds() ); + if ( isSilent ) + Log::debug( "LSPClientServer - parseDocumentSymbols took: %.2fms", + clock.getElapsedTimeAndReset().asMilliseconds() ); return rret; } @@ -1317,10 +1318,12 @@ LSPClientServer::LSPRequestHandle LSPClientServer::write( const json& msg, method = msg[MEMBER_METHOD].get(); else if ( msg.contains( MEMBER_MESSAGE ) ) method = msg[MEMBER_MESSAGE]; - Log::info( "LSPClientServer server %s calling %s", mLSP.name.c_str(), method.c_str() ); - Log::debug( "LSPClientServer server %s sending message:\n%s", mLSP.name.c_str(), - sjson.c_str() ); - + if ( !isSilent() ) { + Log::info( "LSPClientServer server %s calling %s", mLSP.name.c_str(), + method.c_str() ); + Log::debug( "LSPClientServer server %s sending message:\n%s", mLSP.name.c_str(), + sjson.c_str() ); + } if ( mSocket ) { size_t sent = 0; mSocket->send( sjson.c_str(), sjson.size(), sent ); @@ -1331,8 +1334,8 @@ LSPClientServer::LSPRequestHandle LSPClientServer::write( const json& msg, mQueuedMessages.push_back( { std::move( ob ), h, eh } ); } } catch ( const json::exception& e ) { - Log::debug( "LSPClientServer::write server %s failed. Coudln't dump json err: %s", - mLSP.name.c_str(), e.what() ); + Log::warning( "LSPClientServer::write server %s failed. Coudln't dump json err: %s", + mLSP.name.c_str(), e.what() ); } return ret; @@ -1350,8 +1353,8 @@ LSPClientServer::LSPRequestHandle LSPClientServer::send( const json& msg, const if ( isRunning() ) { return write( msg, h, eh ); } else { - Log::debug( "LSPClientServer server %s Send for non-running server: %s", mLSP.name.c_str(), - mLSP.name.c_str() ); + Log::warning( "LSPClientServer server %s Send for non-running server: %s", + mLSP.name.c_str(), mLSP.name.c_str() ); } return LSPRequestHandle(); } @@ -1362,8 +1365,8 @@ LSPClientServer::LSPRequestHandle LSPClientServer::sendSync( const json& msg, if ( isRunning() ) { return write( msg, h, eh ); } else { - Log::debug( "LSPClientServer server %s Send for non-running server: %s", mLSP.name.c_str(), - mLSP.name.c_str() ); + Log::warning( "LSPClientServer server %s Send for non-running server: %s", + mLSP.name.c_str(), mLSP.name.c_str() ); } return LSPRequestHandle(); } @@ -1383,6 +1386,10 @@ void LSPClientServer::refreshCodeLens() { client.second->requestCodeLens(); } +bool LSPClientServer::isSilent() const { + return mManager->getPlugin()->isSilent(); +} + LSPClientServer::LSPRequestHandle LSPClientServer::didOpen( const URI& document, const std::string& text, int version ) { auto params = textDocumentParams( textDocumentItem( document, mLSP.language, text, version ) ); @@ -1490,9 +1497,9 @@ LSPClientServer::documentSymbols( const URI& document, const ReplyHandler& eh ) { return documentSymbols( document, - [h]( const IdType& id, const json& json ) { + [this, h]( const IdType& id, const json& json ) { if ( h ) - h( id, parseDocumentSymbols( json ) ); + h( id, parseDocumentSymbols( json, isSilent() ) ); }, [eh]( const IdType& id, const json& json ) { if ( eh ) @@ -1598,23 +1605,27 @@ void LSPClientServer::publishDiagnostics( const json& msg ) { PluginMessageType::Diagnostics, PluginMessageFormat::Diagnostics, &res ); } - Log::info( "LSPClientServer::publishDiagnostics: %s - returned %zu items", - res.uri.toString().c_str(), res.diagnostics.size() ); - Log::debug( "LSPClientServer::publishDiagnostics: %s", msg.dump().c_str() ); + if ( !isSilent() ) { + Log::info( "LSPClientServer::publishDiagnostics: %s - returned %zu items", + res.uri.toString().c_str(), res.diagnostics.size() ); + Log::debug( "LSPClientServer::publishDiagnostics: %s", msg.dump().c_str() ); + } } void LSPClientServer::workDoneProgress( const LSPWorkDoneProgressParams& workDoneParams ) { // should emit event somewhere - Log::debug( "LSPClientServer::workDoneProgress: %s", - workDoneParams.token.is_string() - ? workDoneParams.token.get().c_str() - : String::toString( workDoneParams.token.get() ).c_str() ); + if ( !isSilent() ) + Log::debug( "LSPClientServer::workDoneProgress: %s", + workDoneParams.token.is_string() + ? workDoneParams.token.get().c_str() + : String::toString( workDoneParams.token.get() ).c_str() ); } void LSPClientServer::processNotification( const json& msg ) { if ( !msg.contains( MEMBER_METHOD ) ) { - Log::debug( "LSPClientServer::processNotification - Unexpected notification, msg: %s", - msg.dump().c_str() ); + if ( !isSilent() ) + Log::debug( "LSPClientServer::processNotification - Unexpected notification, msg: %s", + msg.dump().c_str() ); return; } auto method = msg[MEMBER_METHOD].get(); @@ -1649,13 +1660,15 @@ void LSPClientServer::processNotification( const json& msg ) { workDoneProgress( parseWorkDone( msg[MEMBER_PARAMS] ) ); return; } - Log::debug( "LSPClientServer::processNotification server %s: %s", mLSP.name.c_str(), - msg.dump().c_str() ); + if ( !isSilent() ) + Log::debug( "LSPClientServer::processNotification server %s: %s", mLSP.name.c_str(), + msg.dump().c_str() ); } void LSPClientServer::processRequest( const json& msg ) { - Log::debug( "LSPClientServer::processRequest server %s:\n%s", mLSP.name.c_str(), - msg.dump().c_str() ); + if ( !isSilent() ) + Log::debug( "LSPClientServer::processRequest server %s:\n%s", mLSP.name.c_str(), + msg.dump().c_str() ); auto method = msg[MEMBER_METHOD].get(); auto msgid = getID( msg ); if ( method == "workspace/applyEdit" ) { @@ -1731,15 +1744,18 @@ void LSPClientServer::readStdOut( const char* bytes, size_t n ) { // FIXME perhaps detect if no reply for some time // then again possibly better left to user to restart in such case if ( !ok ) { - Log::debug( "LSPClientServer::readStdOut server %s invalid " CONTENT_LENGTH, - mLSP.name.c_str() ); + if ( !isSilent() ) + Log::debug( "LSPClientServer::readStdOut server %s invalid " CONTENT_LENGTH, + mLSP.name.c_str() ); // flush and try to carry on to some next header buffer.erase( 0, msgstart ); continue; } // sanity check to avoid extensive buffering if ( length > ( 1 << 29 ) ) { - Log::debug( "LSPClientServer::readStdOut server %s excessive size", mLSP.name.c_str() ); + if ( !isSilent() ) + Log::debug( "LSPClientServer::readStdOut server %s excessive size", + mLSP.name.c_str() ); buffer.clear(); continue; } @@ -1752,7 +1768,9 @@ void LSPClientServer::readStdOut( const char* bytes, size_t n ) { buffer.erase( 0, msgstart + length ); if ( payload.empty() ) { - Log::debug( "LSPClientServer::readStdOut server %s empty payload", mLSP.name.c_str() ); + if ( !isSilent() ) + Log::debug( "LSPClientServer::readStdOut server %s empty payload", + mLSP.name.c_str() ); continue; } @@ -1774,8 +1792,9 @@ void LSPClientServer::readStdOut( const char* bytes, size_t n ) { continue; } - Log::debug( "LSPClientServer::readStdOut server %s said:\n%s", mLSP.name.c_str(), - res.dump().c_str() ); + if ( !isSilent() ) + Log::debug( "LSPClientServer::readStdOut server %s said:\n%s", mLSP.name.c_str(), + res.dump().c_str() ); HandlersMap::iterator it; HandlersMap::iterator itEnd; @@ -1801,8 +1820,9 @@ void LSPClientServer::readStdOut( const char* bytes, size_t n ) { handlerOK( msgid, res[MEMBER_RESULT] ); } } else { - Log::debug( "LSPClientServer::readStdOut server %s unexpected reply id: %s", - mLSP.name.c_str(), msgid.toString().c_str() ); + if ( !isSilent() ) + Log::debug( "LSPClientServer::readStdOut server %s unexpected reply id: %s", + mLSP.name.c_str(), msgid.toString().c_str() ); } #ifndef EE_DEBUG } catch ( const json::exception& e ) { diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.hpp b/src/tools/ecode/plugins/lsp/lspclientserver.hpp index 6c7fb9128..0f521c7dc 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.hpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.hpp @@ -314,6 +314,8 @@ class LSPClientServer { void refreshSmenaticHighlighting(); void refreshCodeLens(); + + bool isSilent() const; }; } // namespace ecode diff --git a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp index 86543f1d0..9804c7287 100644 --- a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp +++ b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp @@ -148,6 +148,21 @@ static bool isClosedTag( TextDocument* doc, TextPosition start ) { return false; } +static bool isAlreadyClosedTag( TextDocument* doc, TextPosition start ) { + SyntaxHighlighter* highlighter = doc->getHighlighter(); + TextPosition endOfDoc = doc->endOfDoc(); + do { + String::StringBaseType ch = doc->getChar( start ); + if ( ch == '>' ) { + auto tokenType = highlighter->getTokenTypeAt( start ); + if ( tokenType != "comment"_sst && tokenType != "string"_sst ) + return true; + } + start = doc->positionOffset( start, 1 ); + } while ( start.isValid() && start != endOfDoc ); + return false; +} + void XMLToolsPlugin::XMLToolsClient::updateCurrentMatch( XMLToolsPlugin::ClientMatch& match, int translation ) { TextRange& open = match.open(); @@ -206,7 +221,10 @@ void XMLToolsPlugin::XMLToolsClient::onDocumentTextChanged( if ( match.isSameLine() && !match.currentIsClose ) translatedPos = mDoc->positionOffset( translatedPos, translation + docChange.text.size() ); - mDoc->insert( 0, translatedPos, docChange.text ); + if ( !( ">" == docChange.text && isAlreadyClosedTag( mDoc, match.matchBracket.start() ) ) && + !( " " == docChange.text && docChange.range.end() == match.currentBracket.end() ) ) { + mDoc->insert( 0, translatedPos, docChange.text ); + } mWaitingText = false; if ( match.isSameLine() && match.currentIsClose ) { for ( auto& s : sel ) { diff --git a/src/tools/ecode/statusbuildoutputcontroller.cpp b/src/tools/ecode/statusbuildoutputcontroller.cpp index 71fe7a193..a98ecfe71 100644 --- a/src/tools/ecode/statusbuildoutputcontroller.cpp +++ b/src/tools/ecode/statusbuildoutputcontroller.cpp @@ -187,7 +187,7 @@ void StatusBuildOutputController::runBuild( const std::string& buildName, patterns.emplace_back( SyntaxPattern( { "%d%d%d%d%-%d%d%-%d%d%s%d%d%:%d%d%:%d%d%:[^\n]+" }, "notice" ) ); - SyntaxDefinition synDef( "custom_build", {}, patterns ); + SyntaxDefinition synDef( "custom_build", {}, std::move( patterns ) ); mBuildOutput->getDocument().setSyntaxDefinition( synDef ); mBuildOutput->getVScrollBar()->setValue( 1.f ); @@ -304,7 +304,7 @@ void StatusBuildOutputController::runClean( const std::string& buildName, patterns.emplace_back( SyntaxPattern( { "%d%d%d%d%-%d%d%-%d%d%s%d%d%:%d%d%:%d%d%:[^\n]+" }, "notice" ) ); - SyntaxDefinition synDef( "custom_build", {}, patterns ); + SyntaxDefinition synDef( "custom_build", {}, std::move( patterns ) ); mBuildOutput->getDocument().setSyntaxDefinition( synDef ); mBuildOutput->getVScrollBar()->setValue( 1.f );