IDEA-365690 Logical Structure: clean and document API

GitOrigin-RevId: 8aa5059b709f539873792b126a867a3e0c030ee1
This commit is contained in:
Anton Kozub
2025-02-19 23:43:15 +00:00
committed by intellij-monorepo-bot
parent f673d46b5f
commit a3b3c3a9a1
12 changed files with 59 additions and 97 deletions
@@ -1,9 +1,7 @@
// 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.lang.java.logical
import com.intellij.ide.structureView.logical.ConvertElementsProvider
import com.intellij.ide.structureView.logical.LogicalStructureElementsProvider
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiClassOwner
import org.jetbrains.annotations.ApiStatus
@@ -15,7 +13,7 @@ class ClassOwnerLogicalStructureElementsProvider: LogicalStructureElementsProvid
for (psiClass in parent.classes) {
if (!psiClass.isValid) continue
val convertedModels = LogicalStructureElementsProvider.getProviders(psiClass)
.filterIsInstance<ConvertElementsProvider<PsiClass, Any>>()
.filterIsInstance<PsiClassLogicalElementProvider<Any>>()
.map { it.convert(psiClass) }
.filterNotNull()
if (convertedModels.count() > 0) {
@@ -1,7 +1,16 @@
// 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.lang.java.logical
import com.intellij.ide.structureView.logical.ConvertElementsProvider
import com.intellij.ide.structureView.logical.LogicalStructureElementsProvider
import com.intellij.psi.PsiClass
abstract class PsiClassLogicalElementProvider<T> : ConvertElementsProvider<PsiClass, T>()
abstract class PsiClassLogicalElementProvider<T> : LogicalStructureElementsProvider<PsiClass, T> {
abstract fun convert(p: PsiClass): T?
override fun getElements(parent: PsiClass): List<T> {
val t = convert(parent)
return if (t != null) listOf(t) else emptyList()
}
}
@@ -4,3 +4,32 @@
- isApplicable(java.lang.Object):Z
*f:com.intellij.ide.structureView.logical.LogicalStructureElementsProvider$Companion
- f:getProviders(java.lang.Object):kotlin.sequences.Sequence
*:com.intellij.ide.structureView.logical.LogicalStructureTreeElementProvider
- *sf:Companion:com.intellij.ide.structureView.logical.LogicalStructureTreeElementProvider$Companion
- a:getModelClass():java.lang.Class
- a:getTreeElement(java.lang.Object):com.intellij.ide.structureView.StructureViewTreeElement
*f:com.intellij.ide.structureView.logical.LogicalStructureTreeElementProvider$Companion
- f:getTreeElement(java.lang.Object):com.intellij.ide.structureView.StructureViewTreeElement
*:com.intellij.ide.structureView.logical.model.ExtendedLogicalObject
- a:isTheSameParent(java.lang.Object):Z
*:com.intellij.ide.structureView.logical.model.LogicalContainer
- a:getElements():java.util.List
*a:com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider
- com.intellij.ide.presentation.PresentationProvider
- *sf:Companion:com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider$Companion
- <init>():V
- getColoredText(java.lang.Object):java.util.List
- handleClick(java.lang.Object,I):Z
- isAutoExpand(java.lang.Object):Z
*f:com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider$Companion
- f:getForObject(java.lang.Object):com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider
*f:com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel
- *sf:Companion:com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel$Companion
- equals(java.lang.Object):Z
- f:getChildren():java.util.List
- f:getModel():java.lang.Object
- f:getParent():com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel
- f:getProject():com.intellij.openapi.project.Project
- 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
-35
View File
@@ -47,26 +47,11 @@ a:com.intellij.ide.structureView.impl.common.PsiTreeElementBase
- navigate(Z):V
com.intellij.ide.structureView.logical.ContainerElementsProvider
- com.intellij.ide.structureView.logical.LogicalStructureElementsProvider
- a:getContainerName():java.lang.String
a:com.intellij.ide.structureView.logical.ConvertElementsProvider
- com.intellij.ide.structureView.logical.LogicalStructureElementsProvider
- sf:Companion:com.intellij.ide.structureView.logical.ConvertElementsProvider$Companion
- <init>():V
- a:convert(java.lang.Object):java.lang.Object
- getElements(java.lang.Object):java.util.List
f:com.intellij.ide.structureView.logical.ConvertElementsProvider$Companion
- f:convert(java.lang.Object):kotlin.sequences.Sequence
com.intellij.ide.structureView.logical.ExternalElementsProvider
- com.intellij.ide.structureView.logical.ContainerElementsProvider
f:com.intellij.ide.structureView.logical.LogicalStructureDataKeys
- sf:STRUCTURE_TREE_ELEMENT:com.intellij.openapi.actionSystem.DataKey
- <init>():V
com.intellij.ide.structureView.logical.LogicalStructureTreeElementProvider
- sf:Companion:com.intellij.ide.structureView.logical.LogicalStructureTreeElementProvider$Companion
- a:getModelClass():java.lang.Class
- a:getTreeElement(java.lang.Object):com.intellij.ide.structureView.StructureViewTreeElement
f:com.intellij.ide.structureView.logical.LogicalStructureTreeElementProvider$Companion
- f:getTreeElement(java.lang.Object):com.intellij.ide.structureView.StructureViewTreeElement
f:com.intellij.ide.structureView.logical.PhysicalAndLogicalStructureViewBuilder
- com.intellij.ide.structureView.TreeBasedStructureViewBuilder
- <init>(com.intellij.ide.structureView.TreeBasedStructureViewBuilder,com.intellij.psi.PsiFile):V
@@ -86,26 +71,6 @@ f:com.intellij.ide.structureView.logical.impl.LogicalStructureViewService$Compan
com.intellij.ide.structureView.logical.impl.LogicalStructureViewTreeElement
- com.intellij.ide.structureView.StructureViewTreeElement
- a:getLogicalAssembledModel():com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel
a:com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider
- com.intellij.ide.presentation.PresentationProvider
- sf:Companion:com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider$Companion
- <init>():V
- getColoredText(java.lang.Object):java.util.List
- handleClick(java.lang.Object,I):Z
- isAutoExpand(java.lang.Object):Z
f:com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider$Companion
- f:getForObject(java.lang.Object):com.intellij.ide.structureView.logical.model.LogicalModelPresentationProvider
f:com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel
- sf:Companion:com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel$Companion
- equals(java.lang.Object):Z
- f:getChildren():java.util.List
- f:getChildrenGrouped():java.util.List
- f:getModel():java.lang.Object
- f:getParent():com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel
- f:getProject():com.intellij.openapi.project.Project
- 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
a:com.intellij.ide.util.InheritedMembersNodeProvider
- com.intellij.ide.util.ActionShortcutProvider
- com.intellij.ide.util.FileStructureNodeProvider
@@ -1,24 +0,0 @@
// 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
/**
* Provides logical model [C] for some physical object [P]
*/
abstract class ConvertElementsProvider<P, C> : LogicalStructureElementsProvider<P, C> {
abstract fun convert(p: P): C?
override fun getElements(parent: P): List<C> {
val t = convert(parent)
return if (t != null) listOf(t) else emptyList()
}
companion object {
fun <P> convert(p: P): Sequence<*> {
val convertProviders = LogicalStructureElementsProvider.getProviders(p).filterIsInstance<ConvertElementsProvider<P, Any>>()
if (convertProviders.count() == 0) return sequenceOf(p)
val converted = convertProviders.map { it.convert(p) }.filterNotNull()
return if(converted.count() == 0) sequenceOf(p) else converted
}
}
}
@@ -10,7 +10,6 @@ import org.jetbrains.annotations.ApiStatus.Experimental
* Do not implement it itself, there are three extensions, use them depending on logical meaning:
* [ContainerElementsProvider] - to provide children for parent (e.g. entity attributes for an entity)
* [PropertyElementProvider] - to provide property for element (e.g. scope for a spring bean)
* [ConvertElementsProvider] - to provide logical view for element (e.g. entity/bean for a class)
* To build full model for some element, see [com.intellij.ide.structureView.logical.model.LogicalStructureAssembledModel]
*/
@Experimental
@@ -35,7 +34,6 @@ interface LogicalStructureElementsProvider<P, C> {
* Provides logical children with type [C] for logical object [P]
*/
interface ContainerElementsProvider<P, C> : LogicalStructureElementsProvider<P, C> {
val containerName: String?
}
/**
@@ -3,12 +3,14 @@ package com.intellij.ide.structureView.logical
import com.intellij.ide.structureView.StructureViewTreeElement
import com.intellij.openapi.extensions.ExtensionPointName
import org.jetbrains.annotations.ApiStatus
/**
* Provides logical structure view for logical elements
* It is supposed to apply when we want to reuse existing tree for some logical elements branch
* By default it's better to provide [com.intellij.ide.presentation.PresentationProvider] for [T]
*/
@ApiStatus.Experimental
interface LogicalStructureTreeElementProvider<T> {
companion object {
@@ -192,8 +192,8 @@ private class ElementsBuilder {
while (parentTmp != null) {
val first = parentTmp.model
val second = assembledModel.model
if (first is ExtendedLogicalObject && first.logicalEquals(second)
|| second is ExtendedLogicalObject && second.logicalEquals(first)
if (first is ExtendedLogicalObject && first.isTheSameParent(second)
|| second is ExtendedLogicalObject && second.isTheSameParent(first)
|| first == second) return true
parentTmp = parentTmp.parent
}
@@ -6,12 +6,14 @@ import org.jetbrains.annotations.ApiStatus
/**
* Logical elements have not implement this class, but they can if they want to add some specific logic
*/
@ApiStatus.Internal
@ApiStatus.Experimental
interface ExtendedLogicalObject {
/**
* The method helps prevent recursion in the logical tree.
* @return true - if elements are not equally themselves but are the same if threat them as parents.
* This equality can break common rules for usual "equal", for example, symmetry rule
*/
fun logicalEquals(other: Any?): Boolean
fun isTheSameParent(other: Any?): Boolean
}
@@ -4,7 +4,7 @@ package com.intellij.ide.structureView.logical.model
import com.intellij.ide.structureView.logical.LogicalStructureElementsProvider
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
@ApiStatus.Experimental
interface LogicalContainer<C> {
fun getElements(): List<C>
@@ -5,7 +5,15 @@ import com.intellij.ide.presentation.PresentationProvider
import com.intellij.ide.util.treeView.PresentableNodeDescriptor
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.util.ClassExtension
import org.jetbrains.annotations.ApiStatus
/**
* Adds additional features for common PresentationProvider
*
* Important: do not define the providers which implement this class via @Presentation annotation,
* only <presentationProvider> extension point is allowed
*/
@ApiStatus.Experimental
abstract class LogicalModelPresentationProvider<T>: PresentationProvider<T>() {
companion object {
@@ -8,6 +8,7 @@ import org.jetbrains.annotations.ApiStatus
/**
* Utility class which helps to build full logical model for some element
*/
@ApiStatus.Experimental
class LogicalStructureAssembledModel<T> private constructor(
val project: Project,
val model: T,
@@ -25,7 +26,6 @@ class LogicalStructureAssembledModel<T> private constructor(
return model.getElements().map { LogicalStructureAssembledModel(project, it, parent) }
}
return LogicalStructureElementsProvider.getProviders(model!!)
.filter { it !is ConvertElementsProvider }
.flatMap { provider ->
if (provider is ContainerElementsProvider || provider is PropertyElementProvider) {
listOf(ProvidedLogicalContainer(provider) { provider.getElements(model) })
@@ -38,31 +38,6 @@ class LogicalStructureAssembledModel<T> private constructor(
.toList()
}
/**
* The grouping element in each pair - Any - can be any object, for which a PresentationProvider is registered
*/
@Deprecated("")
@ApiStatus.ScheduledForRemoval
fun getChildrenGrouped(): List<Pair<Any, () -> List<LogicalStructureAssembledModel<*>>>> {
val result = mutableListOf<Pair<Any, () -> List<LogicalStructureAssembledModel<*>>>>()
for (provider in LogicalStructureElementsProvider.getProviders(model!!)) {
if (provider !is ContainerElementsProvider && provider !is PropertyElementProvider) continue
//if (provider is ContainerGroupedElementsProvider<*, *, *>) {
// for (groupedElement in (provider as ContainerGroupedElementsProvider<T, *, *>).getGroupedElements(model)) {
// result.add(Pair(groupedElement.key!!) { groupedElement.value.map { LogicalStructureAssembledModel(project, it, this) } })
// }
// continue
//}
val children = {
provider.getElements(model)
.map { LogicalStructureAssembledModel(project, it, this) }
}
result.add(Pair(provider, children))
}
result.sortBy { if (it.first is PropertyElementProvider<*, *>) 0 else 1 }
return result
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false