Automattic / Automattic/simplenote-android
Crash: IndexOutOfBoundsException When Inserting Checklist Item Above Empty Checklist Item
- Dominant language
- Java
- Stars
- 1.9k
- Forks
- 318
- Avg merge
- 15h 23m
- Merged PRs (30d)
- 5
Description
### Expected
When tapping the **_Enter_**/**_Return_** key at the end of a line of a checklist item with the next line containing an empty checklist item and the line after that being a checklist item, the app inserts a new checklist item and does not crash.
### Observed
When tapping the **_Enter_**/**_Return_** key at the end of a line of a checklist item with the next line containing an empty checklist item and the line after that being a checklist item, the app does not insert a new checklist item and does crash. See the stack trace below for details.
Stack Trace
java.lang.IndexOutOfBoundsException: 5, -1
at android.text.PackedIntVector.deleteAt(PackedIntVector.java:222)
at android.text.DynamicLayout.reflow(DynamicLayout.java:317)
at android.text.DynamicLayout.-wrap0
at android.text.DynamicLayout$ChangeWatcher.reflow(DynamicLayout.java:750)
at android.text.DynamicLayout$ChangeWatcher.onSpanChanged(DynamicLayout.java:779)
at android.text.SpannableStringBuilder.sendSpanChanged(SpannableStringBuilder.java:1292)
at android.text.SpannableStringBuilder.sendToSpanWatchers(SpannableStringBuilder.java:647)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:577)
at android.text.SpannableStringBuilder.insert(SpannableStringBuilder.java:224)
at android.text.SpannableStringBuilder.insert(SpannableStringBuilder.java:222)
at com.automattic.simplenote.utils.AutoBullet.apply
at com.automattic.simplenote.NoteEditorFragment.attemptAutoList
at com.automattic.simplenote.NoteEditorFragment.afterTextChanged
at android.widget.TextView.sendAfterTextChanged(TextView.java:9375)
at android.widget.TextView$ChangeWatcher.afterTextChanged(TextView.java:11917)
at android.text.SpannableStringBuilder.sendAfterTextChanged(SpannableStringBuilder.java:1262)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:574)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:504)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:502)
at android.text.method.QwertyKeyListener.onKeyDown(QwertyKeyListener.java:228)
at android.text.method.TextKeyListener.onKeyDown(TextKeyListener.java:141)
at android.widget.TextView.doKeyDown(TextView.java:7316)
at android.widget.TextView.onKeyDown(TextView.java:7093)
at android.view.KeyEvent.dispatch(KeyEvent.java:2688)
at android.view.View.dispatchKeyEvent(View.java:11662)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at androidx.core.widget.NestedScrollView.dispatchKeyEvent
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at androidx.core.widget.NestedScrollView.dispatchKeyEvent
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at androidx.viewpager.widget.ViewPager.dispatchKeyEvent
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at com.android.internal.policy.DecorView.superDispatchKeyEvent(DecorView.java:437)
at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1818)
at androidx.core.view.KeyEventDispatcher.activitySuperDispatchKeyEventPre28
at androidx.core.view.KeyEventDispatcher.dispatchKeyEvent
at androidx.core.app.ComponentActivity.dispatchKeyEvent
at androidx.appcompat.app.AppCompatActivity.dispatchKeyEvent
at androidx.appcompat.view.WindowCallbackWrapper.dispatchKeyEvent
at androidx.appcompat.app.AppCompatDelegateImpl$AppCompatWindowCallback.dispatchKeyEvent
at androidx.appcompat.view.WindowCallbackWrapper.dispatchKeyEvent
at com.android.internal.policy.DecorView.dispatchKeyEvent(DecorView.java:351)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4714)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4586)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4128)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4181)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4147)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4274)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4155)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4331)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4128)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4181)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4147)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4155)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4128)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4181)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4147)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4307)
at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4468)
at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2435)
at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1998)
at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1989)
at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2412)
at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
at android.os.MessageQueue.next(MessageQueue.java:325)
at android.os.Looper.loop(Looper.java:142)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
### Reproduced
1. Tap **_New Note_** floating action button.
2. Tap ***Toggle Checklist*** item in app bar.
3. Tap **_Enter_**/**_Return_** key twice.
4. Tap end of first line.
5. Tap **_Enter_**/**_Return_** key.
6. Notice crash.
Make|Model|Android Version|App Version
-|-|-|-
Google|Pixel 2|8.0.0|2.5.1
Contributor guide
Research direction
Start with AutoBullet.apply and follow its callers in NoteEditorFragment.attemptAutoList and afterTextChanged. Reproduce the sequence with an empty checklist item between two checklist items, then verify that pressing Enter inserts the new checklist item without an IndexOutOfBoundsException.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, java
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100