From 31b7c22a140add4e3dea4480626d3e00bfee38f0 Mon Sep 17 00:00:00 2001 From: Anton Kozub Date: Sun, 29 Jun 2025 15:54:24 +0400 Subject: [PATCH] IDEA-372093 Structure view: endless loading after start of IDEA (cherry picked from commit 5a00096980eefcad6391d3b821e4075b09d7a1ac) IJ-CR-169146 GitOrigin-RevId: d60f72d26b09a18d0e0dc9828a8a20aa981d75db --- .../com/intellij/ide/impl/StructureViewWrapperImpl.kt | 10 +++++++--- platform/structure-view-impl/api-dump-experimental.txt | 1 + .../logical/PhysicalAndLogicalStructureViewBuilder.kt | 4 ++-- .../logical/impl/LogicalStructureViewService.kt | 10 +++++++--- .../logical/model/LogicalStructureAssembledModel.kt | 10 ++++++++++ 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.kt b/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.kt index 0ca11097988f..51be19e2061e 100644 --- a/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.kt +++ b/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.kt @@ -165,9 +165,13 @@ class StructureViewWrapperImpl( } } } - if (ExperimentalUI.isNewUI() && myStructureView is StructureViewComponent) { - val additional = (myStructureView as StructureViewComponent).dotsActions - myToolWindow.setAdditionalGearActions(additional) + if (ExperimentalUI.isNewUI()) { + (myStructureView as? StructureViewComponent)?.let { + myToolWindow.setAdditionalGearActions(it.dotsActions) + } + (myStructureView as? StructureViewComposite)?.structureViews?.forEach { + (it.structureView as? StructureViewComponent)?.let { sv -> myToolWindow.setAdditionalGearActions(sv.dotsActions) } + } } } }) diff --git a/platform/structure-view-impl/api-dump-experimental.txt b/platform/structure-view-impl/api-dump-experimental.txt index 682adf6e7e59..52417e314363 100644 --- a/platform/structure-view-impl/api-dump-experimental.txt +++ b/platform/structure-view-impl/api-dump-experimental.txt @@ -30,6 +30,7 @@ - f:getModel():java.lang.Object - f:getParent():com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel - f:getProject():com.intellij.openapi.project.Project +- f:hasChildren():Z - hashCode():I *f:com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel$Companion - f:getInstance(com.intellij.openapi.project.Project,java.lang.Object):com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel diff --git a/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/PhysicalAndLogicalStructureViewBuilder.kt b/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/PhysicalAndLogicalStructureViewBuilder.kt index 85ccb55cb8b5..4b8f5e31e1b9 100644 --- a/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/PhysicalAndLogicalStructureViewBuilder.kt +++ b/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/PhysicalAndLogicalStructureViewBuilder.kt @@ -7,7 +7,7 @@ import com.intellij.ide.structureView.logical.impl.LogicalStructureViewService.C import com.intellij.idea.AppMode import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.EDT -import com.intellij.openapi.application.readAction +import com.intellij.openapi.application.smartReadAction import com.intellij.openapi.application.writeIntentReadAction import com.intellij.openapi.client.currentSession import com.intellij.openapi.editor.Editor @@ -45,7 +45,7 @@ class PhysicalAndLogicalStructureViewBuilder( } override suspend fun createStructureViewSuspend(fileEditor: FileEditor?, project: Project): StructureView { - val logicalBuilder = readAction { + val logicalBuilder = smartReadAction(project) { getInstance(psiFile.project).getLogicalStructureBuilder(psiFile) } return withContext(Dispatchers.EDT) { diff --git a/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/impl/LogicalStructureViewService.kt b/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/impl/LogicalStructureViewService.kt index cdb90243f801..251fb398a365 100644 --- a/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/impl/LogicalStructureViewService.kt +++ b/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/impl/LogicalStructureViewService.kt @@ -1,10 +1,13 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.structureView.logical.impl +import com.intellij.ide.structureView.StructureViewBuilder +import com.intellij.ide.structureView.StructureViewModel +import com.intellij.ide.structureView.TreeBasedStructureViewBuilder import com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel -import com.intellij.ide.structureView.* import com.intellij.openapi.components.Service import com.intellij.openapi.editor.Editor +import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.project.Project import com.intellij.psi.PsiFile @@ -21,8 +24,9 @@ class LogicalStructureViewService( if (!psiFile.isValid) return null val assembledModel = LogicalStructureAssembledModel.getInstance(project, psiFile) try { - if (assembledModel.getChildren().isEmpty()) return null - } catch (_: Throwable) { + if (!assembledModel.hasChildren()) return null + } catch (e: Throwable) { + if (e is ProcessCanceledException) throw e return null } return object: TreeBasedStructureViewBuilder() { diff --git a/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/model/LogicalStructureAssembledModel.kt b/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/model/LogicalStructureAssembledModel.kt index ba5f3c5dbd97..eb013b0d66ab 100644 --- a/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/model/LogicalStructureAssembledModel.kt +++ b/platform/structure-view-impl/src/com/intellij/ide/structureView/logical/model/LogicalStructureAssembledModel.kt @@ -43,6 +43,16 @@ class LogicalStructureAssembledModel private constructor( return result } + fun hasChildren(): Boolean { + if (model is LogicalContainer<*> && model.getElements().isNotEmpty()) { + return true + } + for (provider in LogicalStructureElementsProvider.getProviders(model!!)) { + if (provider is ExternalElementsProvider<*, *> || provider.getElements(model).isNotEmpty()) return true + } + return false + } + internal fun hasSameModelParent(): Boolean { var parentTmp = parent while (parentTmp != null) {