Fix potential ConcurrentModificationException in statistics collection by using thread-safe collections.
Issues found:
- VimscriptState.Util and PluginState.Util used non-thread-safe HashSets
- Collections were modified from EDT/user actions but read from getMetrics()
- IntelliJ's ApplicationUsagesCollector.getMetrics() may be called on background threads
- Race conditions could cause ConcurrentModificationException or data corruption
Changes:
- Replace HashSet with ConcurrentHashMap.newKeySet() for thread-safe add/read operations
- Add @Volatile annotations to boolean flags to ensure visibility across threads
- This ensures safe concurrent access between statistics writers and collectors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This breaks a specific construct: `echo(42)(999)`. The `echo` command can parse multiple expressions without separating whitespace. IdeaVim now treats this example as a function call of the resul of the `(42)` expression, which is, of course, invalid. Vim evaluates expressions as it is parsing and declines to apply the `(999)` subscript because it knows the first expression is not a funcref/partial.
IdeaVim does not have this context, so cannot know that this is two expressions and not a function call.
I think it is better to support the `expr10(expr1, ...)` syntax and break this (what feels like niche) functionality than not have function calls through expression results at all.
The only change to the rules themselves is to add unary plus/minus to IntExpression and FloatExpression. This matches Vim's precedence, where the unary operator applies to numeric constants at a higher precedence than to other expressions. E.g. `-4->abs()` invokes `abs` on `-4`, while `-a->abs()` is the negative value of `abs(a)`.
The 3-argument mapping functions (e.g., nmap(keys, actionName, action)) had
incorrect implementation that used recursive mappings for both sub-mappings.
Also, this approach makes it impossible to implement other mapping features
such as skipping mapping registration if the mapping is already defined in
.ideavimrc.
A different solution for convenient mapping patterns will be implemented later.
Changes:
- Remove 16 three-argument function declarations from MappingScope interface
- Remove 16 three-argument function implementations from MappingScopeImpl
- Update ReplaceWithRegister plugins to use correct 2-step pattern:
1. nnoremap("<Plug>...") for non-recursive <Plug> → action
2. nmap("key", "<Plug>...") for recursive key → <Plug>
Total: 374 lines deleted, 18 lines added
The project switching and version control menus in the top-left corner remain unavailable due to accessibility issues (failure to implement the Accessible interface, specifically) with the ToolbarComboButton component in the IntelliJ platform.
Fixes wrong recorded inputs when code completion introduces an import.
Fixes wrong recorded inputs when completing a static member with a partial type name. Example: `WiE.A` -> `WindowEvent.ACTION_EVENT_MASK`
Co-authored-by: Alex Plãte <aleksei.plate@jetbrains.com>
- Remove duplicate empty dictionary test (already covered at line 28)
- Rename 'test len with zero' to 'test len with zero number' for clarity
- Rename 'test len with negative number' to 'test len with negative numbers' (plural)
Co-authored-by: Alex Plãte <AlexPl292@users.noreply.github.com>
What was inspected:
- LenFunctionTest.kt and its corresponding implementation LenFunctionHandler.kt
Issues found:
- Test coverage was limited to basic happy path scenarios
- Missing tests for important edge cases: empty strings, zero, negative numbers,
large numbers, empty collections, and special character handling
- No tests distinguishing between single-quoted and double-quoted string behavior
in Vimscript
Changes made:
- Added 9 new test methods covering:
* Empty strings (both single and double quoted)
* Empty lists and dictionaries
* Zero and negative numbers
* Large numbers
* Multi-element collections
* Strings with escape sequences (documenting Vim's single vs double quote behavior)
Why this improves the code:
- Ensures len() function handles all data type edge cases correctly
- Documents expected behavior for Vimscript string quoting conventions
- Provides regression protection against future changes
- Aligns with testing best practices by covering boundary conditions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The 'idearefactormode' default of Select would leave an inline rename in Insert mode, and hitting Escape to return to Normal frequently cancelled the rename.
Also fixes various edge cases when moving between template variables. Often, this works due to a change in selection, but if there's an empty template variable and no current selection, there's no change in selection, and the mode isn't updated.
In clearStatusBarMessage(), the mutable 'message' property was being
accessed multiple times without capturing it in a local variable. This
could theoretically cause issues if the property changed between the
null check and the usage. Additionally, calling toString() on a String
is redundant and creates an unnecessary allocation.
Fixed by capturing the message in a local variable at the start of the
method, which allows Kotlin's smart cast to work properly and removes
the need for the redundant toString() call.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This test validates the off-by-one error fix in IndexedExpression.kt:56.
When accessing a string at index equal to its length, the code should
return an empty string rather than throwing IndexOutOfBoundsException.
The old condition (idx > text.length) would allow idx == text.length to
pass through, causing an exception. The new condition (idx >= text.length)
correctly treats this as out of bounds.
Test case: 'hello'[5] should return '' since 'hello'.length == 5
Co-authored-by: Alex Plãte <AlexPl292@users.noreply.github.com>
Fixed a variable shadowing bug in the hint generation logic where the lambda
parameter name 'it' was being shadowed in nested lambda, causing incorrect
logic when checking for hint conflicts. The code now uses explicit parameter
names 'candidateHint' and 'existingHint' to make the logic clear and correct.
Also replaced wildcard import (java.util.*) with explicit import of
WeakHashMap, following project conventions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed a missing assertion in the test case "test range negative with start
past end throws error" that was not verifying the error condition actually
occurred. Also cleaned up imports by adding a proper import for assertTrue
instead of using the fully qualified kotlin.test.assertTrue.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add bounds checking to clamp line numbers to the last line of the document,
preventing potential exceptions when accessing line text with out-of-bounds
ranges like `:$+100=`. This matches the behavior of other commands like
GoToLineCommand.
Also add tests to verify the edge case behavior with and without flags.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update copyright year from 2023 to 2025
- Remove redundant 'internal constructor()' modifier (already implied by internal class)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update copyright year to 2025 and add test coverage for edge case when
caret is at the beginning of the command line.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements five new vimscript list functions:
- count(): counts occurrences of a value in a list/dict
- index(): finds first index of a value in a list
- min()/max(): finds minimum/maximum value in a list/dict
- range(): generates a list of numbers with optional stride
Includes error handling for edge cases like zero stride and invalid ranges.
Implement five commonly used vimscript functions:
- repeat(expr, count): Repeats strings or lists multiple times
- char2nr(char): Converts character to Unicode code point
- nr2char(number): Converts code point to character
- trim(text, [mask], [dir]): Trims whitespace or custom characters
- reverse(object): Reverses lists in-place or returns reversed string
All functions include comprehensive test coverage and follow vim's
official behavior including edge cases.
Now, the inputProcessor will be called after all closing is finished. This includes the mode that won't be CMD_LINE anymore, but the one that was used before entering CMD_LINE