diff --git a/tests/java-tests/src/test/kotlin/org/jetbrains/plugins/ideavim/action/motion/updown/MotionPercentOrMatchActionJavaTest.kt b/tests/java-tests/src/test/kotlin/org/jetbrains/plugins/ideavim/action/motion/updown/MotionPercentOrMatchActionJavaTest.kt
index 8646aecd2..341ca0d3e 100644
--- a/tests/java-tests/src/test/kotlin/org/jetbrains/plugins/ideavim/action/motion/updown/MotionPercentOrMatchActionJavaTest.kt
+++ b/tests/java-tests/src/test/kotlin/org/jetbrains/plugins/ideavim/action/motion/updown/MotionPercentOrMatchActionJavaTest.kt
@@ -117,4 +117,48 @@ class MotionPercentOrMatchActionJavaTest : VimJavaTestCase() {
     $c}
     """.trimIndent())
   }
+
+  @Test
+  @TestWithoutNeovim(SkipNeovimReason.PSI)
+  fun `test matching works with a sequence of single-line comments`() {
+    configureByJavaText("""
+      protected TokenStream normalize(String fieldName, TokenStream in) {
+      // $c{
+      // result = new LowerCaseFilter(result);
+      // }
+      return result;
+    }
+    """.trimIndent())
+    typeText("%")
+    assertState("""
+      protected TokenStream normalize(String fieldName, TokenStream in) {
+      // {
+      // result = new LowerCaseFilter(result);
+      // $c}
+      return result;
+    }
+    """.trimIndent())
+  }
+
+  @Test
+  @TestWithoutNeovim(SkipNeovimReason.PSI)
+  fun `test matching doesn't work if a sequence of single-line comments is broken`() {
+    configureByJavaText("""
+      protected TokenStream normalize(String fieldName, TokenStream in) {
+      // $c{
+        result = new LowerCaseFilter(result);
+      // }
+      return result;
+    }
+    """.trimIndent())
+    typeText("%")
+    assertState("""
+      protected TokenStream normalize(String fieldName, TokenStream in) {
+      // $c{
+        result = new LowerCaseFilter(result);
+      // }
+      return result;
+    }
+    """.trimIndent())
+  }
 }
\ No newline at end of file
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/group/SearchGroup.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/group/SearchGroup.kt
index 884f813de..b461b871f 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/group/SearchGroup.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/group/SearchGroup.kt
@@ -150,13 +150,70 @@ private fun parsMatchPairsOption(editor: VimEditor): Map<Char, Char> {
  * If the first brace is inside string or comment, then the second one should be also in the same string or comment; otherwise there is no match.
  */
 public fun findMatchingChar(editor: VimEditor, start: Int, charToMatch: Char, pairChar: Char, direction: Direction): Int? {
-  // TODO enhance implementation with IDE's built in code to go to the matching brace to speed up search
-  val rangeForSearch = getStringAtPos(editor, start, true) ?: injector.psiService.getCommentAtPos(editor, start)?.first
-  return if (rangeForSearch != null && start in rangeForSearch) {
-    findBlockLocation(editor, rangeForSearch, start, charToMatch, pairChar, direction)
-  } else {
-    findBlockLocation(editor, start, charToMatch, pairChar, direction, 0)
+  // If we are inside string, we search for the pair inside the string only
+  val stringRange = getStringAtPos(editor, start, true)
+  if (stringRange != null && start in stringRange) {
+    return findBlockLocation(editor, stringRange, start, charToMatch, pairChar, direction)
   }
+
+  val comment = injector.psiService.getCommentAtPos(editor, start)
+  if (comment != null && start in comment.first) {
+    val prefixToSuffix = comment.second
+    return if (prefixToSuffix != null) {
+      // If it is a block comment (has prefix & suffix), we search for the pair inside the block only
+      findBlockLocation(editor, comment.first, start, charToMatch, pairChar, direction)
+    } else {
+      // If it is not a block comment, that there may be a sequence of single line comments, and we want to iterate over
+      // all of them in an attempt to find a matching char
+      val commentRange = getRangeOfNonBlockComments(editor, comment.first, direction)
+      findBlockLocation(editor, commentRange, start, charToMatch, pairChar, direction)
+    }
+  }
+
+  return findBlockLocation(editor, start, charToMatch, pairChar, direction, 0)
+}
+
+private fun getRangeOfNonBlockComments(editor: VimEditor, startComment: TextRange, direction: Direction): TextRange {
+  var lastComment: TextRange = startComment
+
+  while (true) {
+    val nextNonWhitespaceChar = if (direction == Direction.FORWARDS) {
+      findNextNonWhitespaceChar(editor.text(), lastComment.endOffset)
+    } else {
+      findPreviousNonWhitespaceChar(editor.text(), lastComment.startOffset - 1)
+    } ?: break
+
+    val nextComment = injector.psiService.getCommentAtPos(editor, nextNonWhitespaceChar)
+    if (nextComment != null && nextComment.second == null) {
+      lastComment = nextComment.first
+    } else {
+      break
+    }
+  }
+
+  return if (direction == Direction.FORWARDS) {
+    TextRange(startComment.startOffset, lastComment.endOffset)
+  } else {
+    TextRange(lastComment.startOffset, startComment.endOffset)
+  }
+}
+
+private fun findNextNonWhitespaceChar(chars: CharSequence, startIndex: Int): Int? {
+  for (i in startIndex .. chars.lastIndex) {
+    if (!chars[i].isWhitespace()) {
+      return i
+    }
+  }
+  return null
+}
+
+private fun findPreviousNonWhitespaceChar(chars: CharSequence, startIndex: Int): Int? {
+  for (i in startIndex downTo 0) {
+    if (!chars[i].isWhitespace()) {
+      return i
+    }
+  }
+  return null
 }
 
 /**