| 250 | } |
| 251 | |
| 252 | void XMLToolsPlugin::XMLToolsClient::updateMatch( const TextRange& sel ) { |
| 253 | const auto& line = mDoc->line( mDoc->getSelection().start().line() ).getText(); |
| 254 | if ( mDoc->getSelection().start().column() >= (Int64)line.size() ) |
| 255 | return clearMatch(); |
| 256 | auto def = mDoc->getHighlighter()->getSyntaxDefinitionFromTextPosition( sel.start() ); |
| 257 | if ( !def.getAutoCloseXMLTags() ) // getAutoCloseXMLTags means that it supports XML element tags |
| 258 | return clearMatch(); |
| 259 | TextRange range = mDoc->getWordRangeInPosition( sel.start(), false ); |
| 260 | if ( !range.isValid() || !range.hasSelection() ) |
| 261 | return clearMatch(); |
| 262 | range.normalize(); |
| 263 | if ( range.start().column() == 0 || line.size() <= 1 ) |
| 264 | return clearMatch(); |
| 265 | if ( line[range.start().column() - 1] != '<' && line[range.start().column() - 1] != '/' && |
| 266 | ( range.start().column() - 2 < 0 || range.start().column() - 2 >= (Int64)line.size() || |
| 267 | line[range.start().column() - 2] != '<' ) ) |
| 268 | return clearMatch(); |
| 269 | bool isCloseBracket = line[range.start().column() - 1] == '/'; |
| 270 | if ( isCloseBracket && |
| 271 | ( ( line.size() >= 2 && line[range.start().column() - 2] != '<' ) || line.size() < 2 ) ) |
| 272 | return clearMatch(); |
| 273 | if ( !isCloseBracket && isClosedTag( mDoc, range.end() ) ) |
| 274 | return clearMatch(); |
| 275 | range.start().setColumn( range.start().column() - ( isCloseBracket ? 2 : 1 ) ); |
| 276 | if ( mParent->mMatches.count( mDoc ) > 0 ) { |
| 277 | const ClientMatch& curMatch( mParent->mMatches[mDoc] ); |
| 278 | if ( curMatch.currentBracket == range ) |
| 279 | return; // Moving inside match |
| 280 | } |
| 281 | String tag( mDoc->getText( range ) ); |
| 282 | TextRange found; |
| 283 | |
| 284 | const auto ensureMatchesWord = [&]( int offset ) { |
| 285 | if ( found.isValid() && found.hasSelection() ) { |
| 286 | found.normalize(); |
| 287 | auto start( mDoc->positionOffset( found.start(), offset ) ); |
| 288 | TextRange wordRange = mDoc->getWordRangeInPosition( start, false ); |
| 289 | if ( !wordRange.isValid() || |
| 290 | wordRange.normalized() != TextRange( start, found.end() ).normalized() ) { |
| 291 | found = TextRange(); |
| 292 | } |
| 293 | } |
| 294 | }; |
| 295 | |
| 296 | if ( isCloseBracket ) { |
| 297 | String openBracket( tag ); |
| 298 | openBracket.erase( 1 ); |
| 299 | found = mDoc->getMatchingBracket( range.start(), openBracket, tag, |
| 300 | TextDocument::MatchDirection::Backward, true ); |
| 301 | ensureMatchesWord( 1 ); |
| 302 | } else { |
| 303 | // Ensure the current bracket is closed, otherwise don't try to match |
| 304 | TextPosition matchClose( mDoc->getMatchingBracket( |
| 305 | range.start(), '<', '>', TextDocument::MatchDirection::Forward, false ) ); |
| 306 | if ( !matchClose.isValid() ) |
| 307 | return; |
| 308 | |
| 309 | String closeBracket( tag ); |
nothing calls this directly
no test coverage detected