JetBrains / JetBrains/MPS-extensions
StringIndexOutOfBoundsException in certain scenario when deleting lines in a rich text
Nobody has claimed this yet.
- Dominant language
- JetBrains MPS
- Stars
- 88
- Forks
- 60
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 15
Description
Related to issue 647.
Steps to reproduce: Set the content of a Text to a number of newlines.
Empty lines are marked with "." here.
Set the cursor (here: "|") on the last line.
Example:
.
.
.
.
|
Press Shift-Upwards to select (shown by []) the empty lines except the first.
MPS will show "boxes" like this for the selection, it will not show a box for the last line (which should be also marked).
.
[]
[]
[]
.
Press Backspace/Delete once, it will delete the empty lines except one which is still selected:
.
[]
Press Backspace/Delete again, or change the selection with e.g. Rightarrow, an exception will occur:
Action dispatch failed. Thread AWT-EventQueue-0, state ACTIVE, 1 active clients.
java.lang.StringIndexOutOfBoundsException: begin 4, end 1, length 1
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:4602)
at java.base/java.lang.String.substring(String.java:2705)
at de.slisson.mps.richtext.runtime.selection.RichtextSelection.deleteSelected(RichtextSelection.java:510)
at de.slisson.mps.richtext.runtime.selection.RichtextSelection.lambda$executeDeleteSelected$4(RichtextSelection.java:449)
at jetbrains.mps.smodel.WorkbenchModelAccess$UndoContextSetup.run(WorkbenchModelAccess.java:367)
at jetbrains.mps.smodel.ActionDispatcher.dispatch(ActionDispatcher.java:98)
at jetbrains.mps.smodel.ActionDispatcher.lambda$wrap$0(ActionDispatcher.java:135)
at jetbrains.mps.smodel.ActionDispatcher.dispatch(ActionDispatcher.java:98)
at jetbrains.mps.smodel.ActionDispatcher.lambda$wrap$0(ActionDispatcher.java:135)
at jetbrains.mps.smodel.LockRunnable.run(LockRunnable.java:60)
at jetbrains.mps.smodel.TryRunPlatformWriteHelper.lambda$tryWrite$2(TryRunPlatformWriteHelper.java:122)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:1023)
at jetbrains.mps.smodel.TryRunPlatformWriteHelper.runWrite(TryRunPlatformWriteHelper.java:103)
at jetbrains.mps.smodel.TryRunPlatformWriteHelper.tryWrite(TryRunPlatformWriteHelper.java:120)
at jetbrains.mps.smodel.WorkbenchModelAccess.lambda$tryWriteInCommand$3(WorkbenchModelAccess.java:218)
at jetbrains.mps.util.ComputeRunnable.compute(ComputeRunnable.java:32)
at jetbrains.mps.util.AbstractComputeRunnable.run(AbstractComputeRunnable.java:27)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:219)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:174)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:164)
at jetbrains.mps.smodel.WorkbenchModelAccess.tryWriteInCommand(WorkbenchModelAccess.java:235)
at jetbrains.mps.smodel.WorkbenchModelAccess.lambda$runCommandInEDT_$2(WorkbenchModelAccess.java:151)
at jetbrains.mps.smodel.EDTExecutor$1.tryRun(EDTExecutor.java:61)
at jetbrains.mps.smodel.EDTExecutorInternal.tryToRunTopTask(EDTExecutorInternal.java:296)
at jetbrains.mps.smodel.EDTExecutorInternal.flushNTasks(EDTExecutorInternal.java:251)
at jetbrains.mps.smodel.EDTExecutorInternal.doFlush(EDTExecutorInternal.java:233)
at jetbrains.mps.smodel.EDTExecutorInternal.flushTasksQueue(EDTExecutorInternal.java:213)
at jetbrains.mps.smodel.EDTExecutorInternal.lambda$guaranteeWriteSafetyViaHack$2(EDTExecutorInternal.java:200)
at com.intellij.openapi.application.TransactionGuardImpl.runWithWritingAllowed(TransactionGuardImpl.java:209)
at com.intellij.openapi.application.TransactionGuardImpl.access$100(TransactionGuardImpl.java:21)
at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:191)
at jetbrains.mps.smodel.EDTExecutorInternal.lambda$guaranteeWriteSafetyViaHack$3(EDTExecutorInternal.java:205)
at jetbrains.mps.smodel.EDTExecutorInternal.lambda$forceScheduleFlushEDT$1(EDTExecutorInternal.java:168)
at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:194)
at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:881)
at com.intellij.openapi.application.impl.ApplicationImpl$3.run(ApplicationImpl.java:513)
at com.intellij.openapi.application.impl.FlushQueue.doRun(FlushQueue.java:75)
at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:118)
at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:42)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:779)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:730)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:724)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:749)
at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:918)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:766)
at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$6(IdeEventQueue.java:450)
at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:791)
at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$7(IdeEventQueue.java:449)
at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:105)
at com.intellij.ide.IdeEventQueue.performActivity(IdeEventQueue.java:624)
at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$8(IdeEventQueue.java:447)
at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:881)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:493)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
The above stacktrace is in MPS Extensions 2022.2, but probably looks similar with newer versions.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at de.slisson.mps.richtext.runtime.selection.RichtextSelection, especially deleteSelected at line 510 and executeDeleteSelected near line 449. Reproduce the newline-selection sequence in the issue, then trace the selection bounds during the second deletion or selection change. Done means the sequence no longer throws StringIndexOutOfBoundsException and preserves the expected selection behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- desktop-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100