From d9ccaf2597cb1d2a67ea2e11787b6873c9990d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 5 Aug 2023 14:42:27 -0300 Subject: [PATCH] XML Tools fixes. V lang LSP server updated to the new official LSP. --- bin/assets/plugins/lspclient.json | 6 +- include/eepp/ui/doc/textdocument.hpp | 7 +- src/eepp/ui/doc/textdocument.cpp | 86 +++++++++++++++++-- .../ecode/plugins/xmltools/xmltoolsplugin.cpp | 30 +++++-- 4 files changed, 111 insertions(+), 18 deletions(-) diff --git a/bin/assets/plugins/lspclient.json b/bin/assets/plugins/lspclient.json index d05876a53..408ea7f62 100644 --- a/bin/assets/plugins/lspclient.json +++ b/bin/assets/plugins/lspclient.json @@ -254,9 +254,9 @@ }, { "language": "v", - "name": "vls", - "url": "https://github.com/vlang/vls", - "command": "v ls", + "name": "v-analyzer", + "url": "https://github.com/v-analyzer/v-analyzer", + "command": "v-analyzer --stdio", "file_patterns": ["%.v$"] }, { diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index ed19bf7f4..8c50eb5c7 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -548,11 +548,12 @@ class EE_API TextDocument { TextPosition getMatchingBracket( TextPosition startPosition, const String::StringBaseType& openBracket, - const String::StringBaseType& closeBracket, - MatchDirection dir ); + const String::StringBaseType& closeBracket, MatchDirection dir, + bool allowDepth = true ); TextRange getMatchingBracket( TextPosition startPosition, const String& openBracket, - const String& closeBracket, MatchDirection dir ); + const String& closeBracket, MatchDirection dir, + bool matchingXMLTags = false ); SyntaxHighlighter* getHighlighter() const; diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index 7dfe5262a..f92e6bb2d 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -2529,7 +2529,7 @@ static inline void changeDepth( SyntaxHighlighter* highlighter, int& depth, cons TextPosition TextDocument::getMatchingBracket( TextPosition sp, const String::StringBaseType& openBracket, const String::StringBaseType& closeBracket, - MatchDirection dir ) { + MatchDirection dir, bool allowDepth ) { SyntaxHighlighter* highlighter = getHighlighter(); int depth = 0; while ( sp.isValid() ) { @@ -2538,10 +2538,14 @@ TextPosition TextDocument::getMatchingBracket( TextPosition sp, changeDepth( highlighter, depth, sp, 1 ); if ( depth == 0 ) return sp; + if ( !allowDepth && depth > 1 ) + return {}; } else if ( byte == closeBracket ) { changeDepth( highlighter, depth, sp, -1 ); if ( depth == 0 ) return sp; + if ( !allowDepth && depth > 1 ) + return {}; } auto prevPos = sp; @@ -2553,7 +2557,8 @@ TextPosition TextDocument::getMatchingBracket( TextPosition sp, } TextRange TextDocument::getMatchingBracket( TextPosition start, const String& openBracket, - const String& closeBracket, MatchDirection dir ) { + const String& closeBracket, MatchDirection dir, + bool matchingXMLTags ) { if ( !start.isValid() ) return {}; SyntaxHighlighter* highlighter = getHighlighter(); @@ -2579,9 +2584,34 @@ TextRange TextDocument::getMatchingBracket( TextPosition start, const String& op do { // Find all the open brackets between the first open bracket and the first close bracket do { - foundOpen = - find( openBracket, start, true, false, TextDocument::FindReplaceType::Normal, - { start, foundClose.start() } ); + if ( matchingXMLTags ) { + // Ignore closed XML tags + do { + foundOpen = find( openBracket, start, true, false, + TextDocument::FindReplaceType::Normal, + { start, foundClose.start() } ); + + if ( foundOpen.isValid() ) { + TextPosition closePosition = + getMatchingBracket( foundOpen.start(), openBracket[0], '>', + MatchDirection::Forward, false ); + if ( closePosition.isValid() ) { + if ( getChar( positionOffset( closePosition, -1 ) ) != '/' ) { + break; + } else { + start = closePosition; + } + } else { + break; + } + } + } while ( foundOpen.isValid() ); + } else { + foundOpen = find( openBracket, start, true, false, + TextDocument::FindReplaceType::Normal, + { start, foundClose.start() } ); + } + if ( foundOpen.isValid() ) { start = foundOpen.end(); changeDepth( highlighter, depth, start, 1 ); @@ -2612,7 +2642,28 @@ TextRange TextDocument::getMatchingBracket( TextPosition start, const String& op } // Ensure there's an open bracket - auto foundOpen = findLast( openBracket, start ); + TextRange foundOpen; + if ( matchingXMLTags ) { + do { + foundOpen = findLast( openBracket, start ); + if ( foundOpen.isValid() ) { + TextPosition closePosition = + getMatchingBracket( foundOpen.normalized().start(), openBracket[0], '>', + MatchDirection::Forward, false ); + if ( closePosition.isValid() ) { + if ( getChar( positionOffset( closePosition, -1 ) ) != '/' ) { + break; + } else { + start = foundOpen.normalized().start(); + } + } else { + break; + } + } + } while ( foundOpen.isValid() ); + } else { + foundOpen = findLast( openBracket, start ); + } if ( !foundOpen.isValid() ) return {}; // Not found, exit @@ -2637,7 +2688,28 @@ TextRange TextDocument::getMatchingBracket( TextPosition start, const String& op if ( depth > 0 ) { // Find the next open bracket from the last open bracket - foundOpen = findLast( openBracket, start ); + if ( matchingXMLTags ) { + do { + foundOpen = findLast( openBracket, start ); + if ( foundOpen.isValid() ) { + TextPosition closePosition = + getMatchingBracket( foundOpen.normalized().start(), openBracket[0], + '>', MatchDirection::Forward, false ); + if ( closePosition.isValid() ) { + if ( getChar( positionOffset( closePosition, -1 ) ) != '/' ) { + break; + } else { + start = foundOpen.normalized().start(); + } + } else { + break; + } + } + } while ( foundOpen.isValid() ); + } else { + foundOpen = findLast( openBracket, start ); + } + if ( !foundOpen.isValid() ) break; } diff --git a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp index e0fdc722b..981542ff4 100644 --- a/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp +++ b/src/tools/ecode/plugins/xmltools/xmltoolsplugin.cpp @@ -231,7 +231,7 @@ void XMLToolsPlugin::XMLToolsClient::updateMatch( const TextRange& sel ) { if ( !def.getAutoCloseXMLTags() ) // getAutoCloseXMLTags means that it supports XML element tags return clearMatch(); TextRange range = mDoc->getWordRangeInPosition( sel.start(), false ); - if ( !range.isValid() ) + if ( !range.isValid() || !range.hasSelection() ) return clearMatch(); range.normalize(); if ( range.start().column() == 0 || line.size() <= 1 ) @@ -250,21 +250,41 @@ void XMLToolsPlugin::XMLToolsClient::updateMatch( const TextRange& sel ) { return; // Moving inside match } String tag( mDoc->getText( range ) ); - TextRange found; + + const auto ensureMatchesWord = [&]( int offset ) { + if ( found.isValid() && found.hasSelection() ) { + found.normalize(); + auto start( mDoc->positionOffset( found.start(), offset ) ); + TextRange wordRange = mDoc->getWordRangeInPosition( start, false ); + if ( !wordRange.isValid() || + wordRange.normalized() != TextRange( start, found.end() ).normalized() ) { + found = TextRange(); + } + } + }; + if ( isCloseBracket ) { String openBracket( tag ); openBracket.erase( 1 ); found = mDoc->getMatchingBracket( range.start(), openBracket, tag, - TextDocument::MatchDirection::Backward ); + TextDocument::MatchDirection::Backward, true ); + ensureMatchesWord( 1 ); } else { + // Ensure the current bracket is closed, otherwise don't try to match + TextPosition matchClose( mDoc->getMatchingBracket( + range.start(), '<', '>', TextDocument::MatchDirection::Forward, false ) ); + if ( !matchClose.isValid() ) + return; + String closeBracket( tag ); closeBracket.insert( 1, '/' ); found = mDoc->getMatchingBracket( range.start(), tag, closeBracket, - TextDocument::MatchDirection::Forward ); + TextDocument::MatchDirection::Forward, true ); + ensureMatchesWord( 2 ); } - if ( found.isValid() ) { + if ( found.isValid() && found.hasSelection() ) { ClientMatch match{ range.normalized(), found.normalized(), isCloseBracket }; mParent->mMatches[mDoc] = std::move( match ); } else {