summaryrefslogtreecommitdiff
path: root/logcat
diff options
context:
space:
mode:
authorAlon Albert <aalbert@google.com>2022-07-22 14:27:18 -0700
committerTreeHugger Robot <treehugger-gerrit@google.com>2022-07-26 21:41:42 +0000
commit120c64c98518391dd09c6b3d2cde09af6151a425 (patch)
tree9559fee4f57ffd1431b6eeda08d8a7d686962c5c /logcat
parent1b64decc768a02c915116720625fa4665c0caf0b (diff)
downloadidea-120c64c98518391dd09c6b3d2cde09af6151a425.tar.gz
Keep Track of Caret Position
Since `CaretModel.getOffset()` can be unreliable under extreme load, we keep track of the caret position ourselves as a backup. We log as ERROR so we get crash reports and see how frequently this happens. See b/239095674 Fixes: 239095674 Test: Existing Change-Id: Ie9bb63bd3df7bb9545932991c03c9a9d50c2c663
Diffstat (limited to 'logcat')
-rw-r--r--logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt27
1 files changed, 25 insertions, 2 deletions
diff --git a/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt b/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt
index 66013f84185..5d41dfbb87f 100644
--- a/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt
+++ b/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt
@@ -70,6 +70,7 @@ import com.android.tools.idea.logcat.service.LogcatServiceImpl
import com.android.tools.idea.logcat.settings.AndroidLogcatSettings
import com.android.tools.idea.logcat.util.AndroidProjectDetector
import com.android.tools.idea.logcat.util.AndroidProjectDetectorImpl
+import com.android.tools.idea.logcat.util.LOGGER
import com.android.tools.idea.logcat.util.LogcatUsageTracker
import com.android.tools.idea.logcat.util.MostRecentlyAddedSet
import com.android.tools.idea.logcat.util.createLogcatEditor
@@ -101,6 +102,8 @@ import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.RangeMarker
import com.intellij.openapi.editor.actions.ScrollToTheEndToolbarAction
+import com.intellij.openapi.editor.event.CaretEvent
+import com.intellij.openapi.editor.event.CaretListener
import com.intellij.openapi.editor.event.EditorMouseEvent
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.editor.ex.util.EditorUtil
@@ -180,6 +183,7 @@ internal class LogcatMainPanel(
) : BorderLayoutPanel(), LogcatPresenter, SplittingTabsStateProvider, DataProvider, Disposable {
private var isLogcatPaused: Boolean = false
+ private var caretLine = 0
@VisibleForTesting
internal val editor: EditorEx = createLogcatEditor(project)
@@ -227,6 +231,7 @@ internal class LogcatMainPanel(
private val connectedDevice = AtomicReference<Device?>()
private val logcatServiceChannel = Channel<LogcatServiceEvent>(1)
private val clientListener = ProjectAppMonitor(this, packageNamesProvider)
+
@VisibleForTesting
internal var logcatServiceJob: Job? = null
@@ -239,6 +244,13 @@ internal class LogcatMainPanel(
if (StudioFlags.LOGCAT_CLICK_TO_ADD_FILTER.get()) {
addFilterHintHandlers()
}
+
+ // Keep track of the caret because calling caretModel.getOffset() is not reliable (b/239095674).
+ caretModel.addCaretListener(object : CaretListener {
+ override fun caretPositionChanged(event: CaretEvent) {
+ caretLine = event.newPosition.line
+ }
+ }, this@LogcatMainPanel)
}
toolbar.targetComponent = this
@@ -378,7 +390,7 @@ internal class LogcatMainPanel(
return@withContext
}
// Derived from similar code in ConsoleViewImpl. See initScrollToEndStateHandling()
- val shouldStickToEnd = !ignoreCaretAtBottom && editor.isCaretAtBottom()
+ val shouldStickToEnd = !ignoreCaretAtBottom && isCaretAtBottom()
ignoreCaretAtBottom = false // The 'ignore' only needs to last for one update. Next time, isCaretAtBottom() will be false.
// Mark the end for post-processing. Adding text changes the lines due to the cyclic buffer.
val endMarker: RangeMarker = document.createRangeMarker(document.textLength, document.textLength)
@@ -537,7 +549,7 @@ internal class LogcatMainPanel(
@UiThread
private fun updateScrollToEndState(useImmediatePosition: Boolean) {
val scrollAtBottom = editor.isScrollAtBottom(useImmediatePosition)
- val caretAtBottom = editor.isCaretAtBottom()
+ val caretAtBottom = isCaretAtBottom()
if (!scrollAtBottom && caretAtBottom) {
ignoreCaretAtBottom = true
}
@@ -561,6 +573,7 @@ internal class LogcatMainPanel(
private fun scrollToEnd() {
EditorUtil.scrollToTheEnd(editor, true)
+ caretLine = document.lineCount
ignoreCaretAtBottom = false
}
@@ -626,6 +639,16 @@ internal class LogcatMainPanel(
object StopLogcat : LogcatServiceEvent()
object PauseLogcat : LogcatServiceEvent()
}
+
+ private fun isCaretAtBottom(): Boolean {
+ return try {
+ editor.isCaretAtBottom()
+ } catch (t: Throwable) {
+ // Logging as error in order to see how prevalent this is in the wild. See b/239095674
+ LOGGER.error("Failed to check caret position directly. Using backup method.", t)
+ caretLine >= document.lineCount - 1
+ }
+ }
}
private fun LogcatPanelConfig?.getFormattingOptions(): FormattingOptions =