mlopatkin / andlogview

Tool for viewing application logs from Android devices.
https://andlogview.mlopatkin.name/
Apache License 2.0
43 stars 6 forks source link

Exception when editing a filter after deleting the one before it #374

Closed mlopatkin closed 5 months ago

mlopatkin commented 5 months ago

Affects 0.23-SNAPSHOT.

  1. Add two filters
  2. Remove first filter
  3. Edit the remaining

Expected result: edit succeeds. Actual result: an exception is thrown:

java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
    at java.util.ArrayList.rangeCheck(ArrayList.java:659)
    at java.util.ArrayList.set(ArrayList.java:450)
    at name.mlopatkin.andlogview.filters.FilterModelImpl.replaceFilter(FilterModelImpl.java:72)
    at name.mlopatkin.andlogview.ui.filters.BaseFilterPresenter.setEnabled(BaseFilterPresenter.java:46)
    at name.mlopatkin.andlogview.ui.filters.FilterPanelModelAdapter.setFilterEnabled(FilterPanelModelAdapter.java:73)
    at name.mlopatkin.andlogview.ui.filters.FilterPanelModelAdapter.setFilterEnabled(FilterPanelModelAdapter.java:31)
    at name.mlopatkin.andlogview.ui.filterpanel.FilterPanel$FilterButton.actionPerformed(FilterPanel.java:178)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.JToggleButton$ToggleButtonModel.setPressed(JToggleButton.java:308)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
    at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
    at java.awt.Component.processMouseEvent(Component.java:6539)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6304)
    at java.awt.Container.processEvent(Container.java:2239)
    at java.awt.Component.dispatchEventImpl(Component.java:4889)
    at java.awt.Container.dispatchEventImpl(Container.java:2297)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476)
    at java.awt.Container.dispatchEventImpl(Container.java:2283)
    at java.awt.Window.dispatchEventImpl(Window.java:2746)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84)
    at java.awt.EventQueue$4.run(EventQueue.java:733)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:730)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
mlopatkin commented 5 months ago

The filter-to-index map of FilterModelImpl is the culprit: it doesn't update remaining stored indices when any of the filters are removed. Why do we need the map in the first place? It makes replacing O(1), but is having O(n) replace that bad actually?