mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-354490 Customise Structure tool window for Spring elements
GitOrigin-RevId: b0ba9385fc2f8421b3f334aec25431d1a8e985c7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
90f2e26354
commit
f8acffcc57
@@ -782,6 +782,10 @@
|
||||
<codeInsight.linkHandler prefix="#javaClass/" handlerClass="com.intellij.codeInsight.daemon.impl.JavaClassTooltipLinkHandler"/>
|
||||
|
||||
<lang.psiStructureViewFactory language="JAVA" implementationClass="com.intellij.lang.java.JavaStructureViewBuilderFactory"/>
|
||||
<lang.logicalStructureElementsProvider implementation="com.intellij.ide.structureView.logical.ClassOwnerLogicalStructureElementsProvider"/>
|
||||
<lang.logicalStructureTreeElementProvider
|
||||
id="javaPsiClassLogicalStructureTreeElementProvider"
|
||||
implementation="com.intellij.ide.structureView.logical.JavaPsiClassLogicalStructureTreeElementProvider"/>
|
||||
|
||||
<lang.smartEnterProcessor language="JSPX" implementationClass="com.intellij.codeInsight.completion.XmlSmartEnterProcessor"/>
|
||||
|
||||
|
||||
+13
@@ -0,0 +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
|
||||
|
||||
import com.intellij.ide.logical.LogicalStructureElementsProvider
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiClassOwner
|
||||
|
||||
class ClassOwnerLogicalStructureElementsProvider: LogicalStructureElementsProvider<PsiClassOwner, PsiClass> {
|
||||
override fun getElements(parent: PsiClassOwner): List<PsiClass> {
|
||||
return parent.classes.toList()
|
||||
}
|
||||
override fun forLogicalModelClass(): Class<PsiClassOwner> = PsiClassOwner::class.java
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// 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
|
||||
|
||||
import com.intellij.ide.logical.LogicalStructureTreeElementProvider
|
||||
import com.intellij.ide.structureView.StructureViewTreeElement
|
||||
import com.intellij.ide.structureView.impl.java.JavaClassTreeElement
|
||||
import com.intellij.psi.PsiClass
|
||||
|
||||
class JavaPsiClassLogicalStructureTreeElementProvider: LogicalStructureTreeElementProvider<PsiClass> {
|
||||
|
||||
override fun getModelClass(): Class<PsiClass> = PsiClass::class.java
|
||||
|
||||
override fun getTreeElement(model: PsiClass): StructureViewTreeElement {
|
||||
return JavaClassTreeElement(model, false)
|
||||
}
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// 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
|
||||
|
||||
import com.intellij.ide.logical.ConvertElementsProvider
|
||||
import com.intellij.psi.PsiClass
|
||||
|
||||
abstract class PsiClassLogicalElementProvider<T> : ConvertElementsProvider<PsiClass, T>() {
|
||||
override fun forLogicalModelClass(): Class<PsiClass> {
|
||||
return PsiClass::class.java
|
||||
}
|
||||
}
|
||||
@@ -120,6 +120,9 @@
|
||||
|
||||
<extensionPoint name="lang.structureViewExtension" interface="com.intellij.ide.structureView.StructureViewExtension" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="lang.logicalStructureElementsProvider" interface="com.intellij.ide.logical.LogicalStructureElementsProvider" dynamic="true"/>
|
||||
<extensionPoint name="lang.logicalStructureTreeElementProvider" interface="com.intellij.ide.logical.LogicalStructureTreeElementProvider" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="lang.surroundDescriptor" beanClass="com.intellij.lang.LanguageExtensionPoint" dynamic="true">
|
||||
<with attribute="implementationClass" implements="com.intellij.lang.surroundWith.SurroundDescriptor"/>
|
||||
</extensionPoint>
|
||||
|
||||
+7
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.intellij.ide.highlighter;
|
||||
|
||||
import com.intellij.ide.logical.impl.LogicalStructureViewService;
|
||||
import com.intellij.ide.structureView.StructureViewBuilder;
|
||||
import com.intellij.ide.structureView.StructureViewBuilderProvider;
|
||||
import com.intellij.lang.LanguageStructureViewBuilder;
|
||||
@@ -43,6 +44,12 @@ public class LanguageFileTypeStructureViewBuilderProvider implements StructureVi
|
||||
final PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
if (psiFile == null) return null;
|
||||
|
||||
//boolean isLogicalViewAvailable = true; // TODO StructureTW: add logic
|
||||
//if (isLogicalViewAvailable) {
|
||||
StructureViewBuilder logicalViewBuilder = LogicalStructureViewService.Companion.getInstance(project).getLogicalStructureBuilder(psiFile);
|
||||
if (logicalViewBuilder != null) return logicalViewBuilder;
|
||||
//}
|
||||
|
||||
final PsiStructureViewFactory factory = LanguageStructureViewBuilder.getInstance().forLanguage(psiFile.getLanguage());
|
||||
return factory == null ? null : factory.getStructureViewBuilder(psiFile);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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.logical
|
||||
|
||||
abstract class ConvertElementsProvider<P, C> : LogicalStructureElementsProvider<P, C> {
|
||||
abstract fun convert(p: P): C?
|
||||
|
||||
override fun getElements(p: P): List<C> {
|
||||
val t = convert(p)
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// 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.logical
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
|
||||
interface LogicalStructureElementsProvider<P, C> {
|
||||
|
||||
fun getElements(parent: P): List<C>
|
||||
|
||||
companion object {
|
||||
private const val EP_FQN = "com.intellij.lang.logicalStructureElementsProvider"
|
||||
|
||||
val EP_NAME = ExtensionPointName.create<LogicalStructureElementsProvider<*, *>>(EP_FQN)
|
||||
|
||||
fun <P> getProviders(p: P): Sequence<LogicalStructureElementsProvider<P, Any>> {
|
||||
return EP_NAME.extensionList.asSequence()
|
||||
.filter { it.forLogicalModelClass().isInstance(p) } as Sequence<LogicalStructureElementsProvider<P, Any>>
|
||||
}
|
||||
}
|
||||
fun forLogicalModelClass(): Class<P>
|
||||
}
|
||||
|
||||
interface ContainerElementsProvider<P, C> : LogicalStructureElementsProvider<P, C> {
|
||||
val containerName: String?
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// 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.logical
|
||||
|
||||
import com.intellij.ide.structureView.StructureViewTreeElement
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
|
||||
interface LogicalStructureTreeElementProvider<T> {
|
||||
|
||||
companion object {
|
||||
private const val EP_FQN = "com.intellij.lang.logicalStructureTreeElementProvider"
|
||||
|
||||
val EP_NAME = ExtensionPointName.create<LogicalStructureTreeElementProvider<*>>(EP_FQN)
|
||||
|
||||
fun <T> getTreeElement(model: T): StructureViewTreeElement? {
|
||||
val provider = EP_NAME.extensionList
|
||||
.firstOrNull { it.getModelClass().isInstance(model) } as? LogicalStructureTreeElementProvider<T>
|
||||
return provider?.getTreeElement(model)
|
||||
}
|
||||
}
|
||||
|
||||
fun getModelClass(): Class<T>
|
||||
|
||||
fun getTreeElement(model: T): StructureViewTreeElement
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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.logical.impl
|
||||
|
||||
import com.intellij.ide.TypePresentationService
|
||||
import com.intellij.ide.projectView.PresentationData
|
||||
import com.intellij.ide.util.treeView.AbstractTreeNode
|
||||
import com.intellij.ide.util.treeView.smartTree.ActionPresentation
|
||||
import com.intellij.ide.util.treeView.smartTree.Group
|
||||
import com.intellij.ide.util.treeView.smartTree.Grouper
|
||||
import com.intellij.ide.util.treeView.smartTree.TreeElement
|
||||
import com.intellij.navigation.ItemPresentation
|
||||
import javax.swing.Icon
|
||||
|
||||
class LogicalGrouper: Grouper {
|
||||
|
||||
private val typePresentationService = TypePresentationService.getService()
|
||||
|
||||
override fun getPresentation(): ActionPresentation {
|
||||
return object : ActionPresentation {
|
||||
override fun getText(): String = "Logical"
|
||||
|
||||
override fun getDescription(): String = ""
|
||||
|
||||
override fun getIcon(): Icon? = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getName(): String = "Logical"
|
||||
|
||||
override fun group(parent: AbstractTreeNode<*>, children: MutableCollection<TreeElement>): Collection<Group> {
|
||||
val structureElement = parent.value as? LogicalStructureViewTreeElement<*> ?: return emptyList()
|
||||
val result = mutableListOf<Group>()
|
||||
for (pair in structureElement.getLogicalAssembledModel().getChildrenGrouped()) {
|
||||
result.add(object: Group {
|
||||
override fun getPresentation(): ItemPresentation {
|
||||
val groupingObject = pair.first
|
||||
return PresentationData(
|
||||
typePresentationService.getObjectName(groupingObject),
|
||||
typePresentationService.getTypeName(groupingObject),
|
||||
typePresentationService.getIcon(groupingObject),
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
override fun getChildren(): Collection<TreeElement> {
|
||||
return pair.second.mapNotNull { childLogical ->
|
||||
children.firstOrNull { it is LogicalStructureViewTreeElement<*> && it.getLogicalAssembledModel().model == childLogical.model }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// 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.logical.impl
|
||||
|
||||
import com.intellij.ide.logical.model.LogicalStructureAssembledModel
|
||||
import com.intellij.ide.structureView.*
|
||||
import com.intellij.ide.util.treeView.smartTree.Grouper
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFile
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
class LogicalStructureViewService(
|
||||
private val project: Project
|
||||
) {
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): LogicalStructureViewService = project.getService(LogicalStructureViewService::class.java)
|
||||
}
|
||||
|
||||
fun getLogicalStructureBuilder(psiFile: PsiFile): StructureViewBuilder? {
|
||||
val assembledModel = LogicalStructureAssembledModel(project, psiFile)
|
||||
if (assembledModel.getChildren().isEmpty()) return null
|
||||
return object: TreeBasedStructureViewBuilder() {
|
||||
override fun createStructureViewModel(editor: Editor?): StructureViewModel {
|
||||
return LogicalStructureViewModel(psiFile, editor, assembledModel)
|
||||
}
|
||||
|
||||
override fun isRootNodeShown(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class LogicalStructureViewModel(psiFile: PsiFile, editor: Editor?, assembledModel: LogicalStructureAssembledModel<*>)
|
||||
: StructureViewModelBase(psiFile, editor, createViewTreeElement(assembledModel)), StructureViewModel.ElementInfoProvider {
|
||||
|
||||
override fun isAlwaysShowsPlus(element: StructureViewTreeElement?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isAlwaysLeaf(element: StructureViewTreeElement?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getGroupers(): Array<Grouper> {
|
||||
return arrayOf(LogicalGrouper())
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
// 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.logical.impl
|
||||
|
||||
import com.intellij.ide.TypePresentationService
|
||||
import com.intellij.ide.logical.LogicalStructureTreeElementProvider
|
||||
import com.intellij.ide.logical.model.LogicalStructureAssembledModel
|
||||
import com.intellij.ide.logical.model.LogicalStructureModel
|
||||
import com.intellij.ide.logical.model.PsiRepresentingLogicalStructureModel
|
||||
import com.intellij.ide.projectView.PresentationData
|
||||
import com.intellij.ide.structureView.StructureViewTreeElement
|
||||
import com.intellij.ide.structureView.impl.common.PsiTreeElementBase
|
||||
import com.intellij.ide.util.treeView.smartTree.TreeElement
|
||||
import com.intellij.navigation.ItemPresentation
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiTarget
|
||||
import javax.swing.Icon
|
||||
|
||||
fun <T> createViewTreeElement(assembledModel: LogicalStructureAssembledModel<T>): StructureViewTreeElement {
|
||||
val model = assembledModel.model
|
||||
val explicitElement = LogicalStructureTreeElementProvider.getTreeElement(model)
|
||||
if (explicitElement != null) return explicitElement
|
||||
val psiElement: PsiElement? = when {
|
||||
model is PsiElement -> model
|
||||
model is PsiTarget && model.isValid() -> model.navigationElement
|
||||
else -> null
|
||||
}
|
||||
if (psiElement != null) {
|
||||
return PsiElementStructureElement(assembledModel, psiElement)
|
||||
}
|
||||
return OtherStructureElement(assembledModel)
|
||||
}
|
||||
|
||||
|
||||
interface LogicalStructureViewTreeElement<T>: StructureViewTreeElement {
|
||||
|
||||
fun getLogicalAssembledModel(): LogicalStructureAssembledModel<T>
|
||||
|
||||
}
|
||||
|
||||
private class PsiElementStructureElement<T>(
|
||||
private val assembledModel: LogicalStructureAssembledModel<T>,
|
||||
psiElement: PsiElement
|
||||
): PsiTreeElementBase<PsiElement>(psiElement), LogicalStructureViewTreeElement<T> {
|
||||
|
||||
private val typePresentationService = TypePresentationService.getService()
|
||||
|
||||
override fun getPresentableText(): String? = typePresentationService.getObjectName(assembledModel.model!!)
|
||||
|
||||
override fun getLocationString(): String? = typePresentationService.getTypeName(assembledModel.model!!)
|
||||
|
||||
override fun getIcon(open: Boolean): Icon? = typePresentationService.getIcon(assembledModel.model!!)
|
||||
|
||||
override fun getChildrenBase(): Collection<StructureViewTreeElement> {
|
||||
return assembledModel.getChildren().map { createViewTreeElement(it) }
|
||||
}
|
||||
|
||||
override fun getLogicalAssembledModel() = assembledModel
|
||||
|
||||
}
|
||||
|
||||
private class OtherStructureElement<T>(
|
||||
private val assembledModel: LogicalStructureAssembledModel<T>,
|
||||
): StructureViewTreeElement, LogicalStructureViewTreeElement<T> {
|
||||
|
||||
private val typePresentationService = TypePresentationService.getService()
|
||||
|
||||
override fun getValue(): Any = assembledModel.model ?: ""
|
||||
|
||||
override fun getLogicalAssembledModel() = assembledModel
|
||||
|
||||
override fun getPresentation(): ItemPresentation {
|
||||
return object: ItemPresentation {
|
||||
override fun getPresentableText(): String? = typePresentationService.getObjectName(assembledModel.model!!)
|
||||
|
||||
override fun getLocationString(): String? = typePresentationService.getTypeName(assembledModel.model!!)
|
||||
|
||||
override fun getIcon(unused: Boolean): Icon? = typePresentationService.getIcon(assembledModel.model!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getChildren(): Array<TreeElement> {
|
||||
return assembledModel.getChildren().map { createViewTreeElement(it) }.toTypedArray()
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// 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.logical.model
|
||||
|
||||
import com.intellij.ide.logical.ContainerElementsProvider
|
||||
import com.intellij.ide.logical.ConvertElementsProvider
|
||||
import com.intellij.ide.logical.LogicalStructureElementsProvider
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
class LogicalStructureAssembledModel<T>(
|
||||
val project: Project,
|
||||
val model: T
|
||||
) {
|
||||
|
||||
fun getChildren(): List<LogicalStructureAssembledModel<*>> {
|
||||
return LogicalStructureElementsProvider.getProviders(model!!)
|
||||
.flatMap { it.getElements(model) }
|
||||
.flatMap { ConvertElementsProvider.convert(it) }
|
||||
.map { LogicalStructureAssembledModel(project, it) }
|
||||
.toList()
|
||||
}
|
||||
|
||||
/**
|
||||
* The grouping element in each pair - Any - can be any object, for which a PresentationProvider is registered
|
||||
*/
|
||||
fun getChildrenGrouped(): List<Pair<Any, List<LogicalStructureAssembledModel<*>>>> {
|
||||
return LogicalStructureElementsProvider.getProviders(model!!)
|
||||
.mapNotNull { provider ->
|
||||
if (provider !is ContainerElementsProvider) return@mapNotNull null
|
||||
val children = provider.getElements(model)
|
||||
.map { LogicalStructureAssembledModel(project, it) }
|
||||
Pair(provider, children)
|
||||
}
|
||||
.toList()
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// 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.logical.model
|
||||
|
||||
interface LogicalStructureModel {
|
||||
|
||||
fun getName(): String
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// 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.logical.model
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
|
||||
interface PsiRepresentingLogicalStructureModel<T: PsiElement>: LogicalStructureModel {
|
||||
|
||||
fun getPsiElement(): T?
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +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 org.jetbrains.kotlin.idea.structureView
|
||||
|
||||
import com.intellij.ide.logical.LogicalStructureTreeElementProvider
|
||||
import com.intellij.ide.structureView.StructureViewTreeElement
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
|
||||
class KotlinClassLogicalStructureTreeElementProvider: LogicalStructureTreeElementProvider<KtLightClass> {
|
||||
|
||||
override fun getModelClass(): Class<KtLightClass> = KtLightClass::class.java
|
||||
|
||||
override fun getTreeElement(model: KtLightClass): StructureViewTreeElement {
|
||||
return KotlinStructureViewElement(model.kotlinOrigin ?: model, false)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -155,6 +155,9 @@
|
||||
order="first"
|
||||
key="KNM"
|
||||
factoryClass="org.jetbrains.kotlin.idea.structureView.KtDecompiledFileStructureViewBuilderProvider"/>
|
||||
<lang.logicalStructureTreeElementProvider
|
||||
implementation="org.jetbrains.kotlin.idea.structureView.KotlinClassLogicalStructureTreeElementProvider"
|
||||
order="before javaPsiClassLogicalStructureTreeElementProvider"/>
|
||||
</extensions>
|
||||
|
||||
<!-- Line markers -->
|
||||
|
||||
Reference in New Issue
Block a user