Skip to content

Commit

Permalink
Fix some edge cases with argtextobj
Browse files Browse the repository at this point in the history
  • Loading branch information
jphalip committed Nov 22, 2024
1 parent 6608e1d commit 4a56fa4
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public void init() {

/**
* The pairs of brackets that delimit different types of argument lists.
* Brackets are ordered by rank (highest to lowest priority) and used to handle
* nested structures correctly, e.g. handling function arguments inside code blocks.
*/
private static class BracketPairs {
// NOTE: brackets must match by the position, and ordered by rank (highest to lowest).
Expand Down Expand Up @@ -298,7 +300,7 @@ private static class ArgBoundsFinder {
* @param position starting position.
*/
boolean findBoundsAt(int position) throws IllegalStateException {
if (text.length() == 0) {
if (text.isEmpty()) {
error = "empty document";
return false;
}
Expand All @@ -317,8 +319,6 @@ boolean findBoundsAt(int position) throws IllegalStateException {
}
if (brackets.isCloseBracket(ch)) {
--leftBound;
} else if (brackets.isOpenBracket(ch)) {
++rightBound;
} else {
++rightBound;
}
Expand Down Expand Up @@ -368,18 +368,35 @@ boolean findBoundsAt(int position) throws IllegalStateException {
return true;
}

/**
* Checks if there is a function-like construct (bracket pair) ahead.
* Uses simple bracket matching rather than language-specific identifier rules
* to work across different programming languages.
*
* @param position starting position to search from
* @return true if potential function call found
*/
private boolean isBeforeFunction(int position) {
int pos = position;
int rightLimit = rightLimit(position);

// Skip whitespace before potential function name
while (pos < rightLimit && Character.isWhitespace(getCharAt(pos))) {
while (pos < rightLimit) {
char ch = getCharAt(pos);

if (brackets.isOpenBracket(ch)) {
// Found opening bracket, check if it's matched
int matchingClose = skipSexp(pos, rightLimit, SexpDirection.forward(brackets));
if (matchingClose > pos + 1) { // Must have at least one character between brackets
leftBound = pos + 1; // Inside the brackets
rightBound = pos + 1;
return true;
}
}

pos++;
}

// Must start with identifier character
char ch = getCharAt(pos);
return ch != 0 && Character.isJavaIdentifierStart(ch);
return false;
}

private int findOpeningBracket(int position) {
Expand Down Expand Up @@ -486,7 +503,6 @@ private boolean isIdentPreceding() {
/**
* Detects if current position is inside a quoted string and adjusts
* left and right bounds to the boundaries of the string.
*
* NOTE: Does not support line continuations for quoted string ('\' at the end of line).
*/
private void getOutOfQuotedText() {
Expand Down Expand Up @@ -728,34 +744,44 @@ private int skipSexp(final int start, final int end, SexpDirection dir) {

/**
* Find a pair of brackets surrounding (leftBracket..rightBracket) block.
* If brackets have different priorities, will attempt to skip higher priority
* brackets to find matching pairs of lower priority brackets.
*
* @param start minimum position to look for
* @param end maximum position
* @return true if found
* @return true if found matching bracket pair
*/

boolean findOuterBrackets(final int start, final int end) {
boolean hasNewBracket = findPrevOpenBracket(start) && findNextCloseBracket(end);
while (hasNewBracket) {
final int leftPrio = brackets.getBracketPrio(getCharAt(leftBracket));
final int rightPrio = brackets.getBracketPrio(getCharAt(rightBracket));
if (leftPrio == rightPrio) {
// matching brackets
char leftChar = getCharAt(leftBracket);
char rightChar = getCharAt(rightBracket);

// If brackets match, we're done
if (brackets.matchingBracket(leftChar) == rightChar) {
return true;
}

// Handle unmatched brackets based on priority
int leftPrio = brackets.getBracketPrio(leftChar);
int rightPrio = brackets.getBracketPrio(rightChar);

if (leftPrio > rightPrio) {
// If left bracket has higher priority (e.g. {), ignore it and try next
if (leftBracket > start) {
leftBracket--;
hasNewBracket = findPrevOpenBracket(start);
} else {
hasNewBracket = false;
}
} else {
if (leftPrio < rightPrio) {
if (rightBracket + 1 < end) {
++rightBracket;
hasNewBracket = findNextCloseBracket(end);
} else {
hasNewBracket = false;
}
// If right bracket has higher priority, ignore it and try next
if (rightBracket < end) {
rightBracket++;
hasNewBracket = findNextCloseBracket(end);
} else {
if (leftBracket > 1) {
--leftBracket;
hasNewBracket = findPrevOpenBracket(start);
} else {
hasNewBracket = false;
}
hasNewBracket = false;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ class VimArgTextObjExtensionTest : VimTestCase() {
fun testChangeInnerArgumentLookAhead() {
doTest(
Lists.newArrayList("cia"),
"def <caret>my_func(arg1, arg2):",
"def my_func(<caret>, arg2):",
"<caret>12 + 100 + my_func(arg1, arg2):",
"12 + 100 + my_func(<caret>, arg2):",
Mode.INSERT,
)
}
Expand Down

0 comments on commit 4a56fa4

Please sign in to comment.