make presentation consistent in different target interfaces

Affected target interfaces: `NavigationTarget`, `DocumentationTarget`, `SearchTarget`, `RenameTarget`.

- Now it's a function to avoid storing presentation unnecessarily in a property.
If needed, an implementation can still define a field and cache the presentation there.
- Proper RW annotations were specified.

GitOrigin-RevId: 5499bd2f71343a4ed4dd70c5fd4cf1bcc6e0ad30
This commit is contained in:
Daniil Ovchinnikov
2022-10-12 13:05:32 +00:00
committed by intellij-monorepo-bot
parent a2ec06a0d0
commit 900f0bea95
32 changed files with 78 additions and 67 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.navigation;
import com.intellij.model.Pointer;
@@ -32,7 +32,9 @@ public interface NavigationTarget {
*
* @return presentation to render this target in navigation popup
*/
@NotNull TargetPresentation getTargetPresentation();
@RequiresReadLock
@RequiresBackgroundThread
@NotNull TargetPresentation presentation();
/**
* This method is called once before the actual navigation.
@@ -15,7 +15,7 @@ internal class PsiElementNavigationTarget(private val myElement: PsiElement) : N
myElement.createSmartPointer(), ::PsiElementNavigationTarget
)
override fun getTargetPresentation(): TargetPresentation = targetPresentation(myElement)
override fun presentation(): TargetPresentation = targetPresentation(myElement)
override fun navigationRequest(): NavigationRequest? = myElement.psiNavigatable()?.navigationRequest()
@@ -19,7 +19,7 @@ internal class PsiFileNavigationTarget(
psiFile.createSmartPointer(), ::PsiFileNavigationTarget
)
override fun getTargetPresentation(): TargetPresentation {
override fun presentation(): TargetPresentation {
val project = psiFile.project
var builder = TargetPresentation
@@ -86,7 +86,7 @@ private class TargetGTDActionData(private val project: Project, private val targ
}
else -> {
val targets = result.map { (navigationTarget, navigationProvider) ->
LazyTargetWithPresentation(navigationTarget::navigationRequest, navigationTarget.targetPresentation, navigationProvider)
LazyTargetWithPresentation(navigationTarget::navigationRequest, navigationTarget.presentation(), navigationProvider)
}
MultipleTargets(targets)
}
@@ -156,7 +156,7 @@ internal fun result(navigationTargets: Collection<NavigationTarget>): Navigation
SingleTarget(request, null)
}
else -> MultipleTargets(navigationTargets.map { navigationTarget ->
LazyTargetWithPresentation(navigationTarget::navigationRequest, navigationTarget.targetPresentation, null)
LazyTargetWithPresentation(navigationTarget::navigationRequest, navigationTarget.presentation(), null)
})
}
}
@@ -41,7 +41,7 @@ class SearchTarget2UsageTarget(
}
private fun getItemPresentation(target: SearchTarget): ItemPresentation {
val presentation = target.presentation
val presentation = target.presentation()
return object : ItemPresentation {
override fun getIcon(unused: Boolean): Icon? = presentation.icon
override fun getPresentableText(): String = presentation.presentableText
@@ -75,7 +75,7 @@ private fun canReuseTab(project: Project): Boolean {
}
}
internal val SearchTarget.displayString: String get() = presentation.presentableText
internal val SearchTarget.displayString: String get() = presentation().presentableText
@Nls(capitalization = Nls.Capitalization.Title)
internal fun UsageHandler.getSearchString(allOptions: AllSearchOptions): String {
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:ApiStatus.Internal
package com.intellij.find.actions
@@ -63,7 +63,7 @@ internal sealed class TargetVariant {
}
internal class SearchTargetVariant(private val target: SearchTarget) : TargetVariant() {
override val presentation: TargetPresentation get() = target.presentation
override val presentation: TargetPresentation get() = target.presentation()
override fun handle(handler: UsageVariantHandler): Unit = handler.handleTarget(target)
}
@@ -6,6 +6,8 @@ import com.intellij.model.search.SearchRequest
import com.intellij.navigation.TargetPresentation
import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.SearchScope
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
import com.intellij.util.concurrency.annotations.RequiresReadLock
/**
* Represents the search implementation (the usage handler and the text search strings)
@@ -34,7 +36,9 @@ interface SearchTarget {
* or in the Usage View (only [icon][TargetPresentation.icon]
* and [presentable text][TargetPresentation.presentableText] are used)
*/
val presentation: TargetPresentation
@RequiresReadLock
@RequiresBackgroundThread
fun presentation(): TargetPresentation
/**
* @see UsageHandler.createEmptyUsageHandler
@@ -35,10 +35,9 @@ interface DocumentationTarget {
* Returned presentation is used to render the tab name and icon in the tool window,
* and to render location info under the documentation in the popup.
*/
val presentation: TargetPresentation
@RequiresReadLock
@RequiresBackgroundThread
get
@RequiresReadLock
@RequiresBackgroundThread
fun presentation(): TargetPresentation
@Suppress("DEPRECATION") // deprecated JvmDefault
@JvmDefault
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.lang.documentation.impl
import com.intellij.lang.documentation.DocumentationResult
@@ -12,9 +12,9 @@ internal object EmptyDocumentationTarget : DocumentationTarget, Pointer<EmptyDoc
override fun dereference(): EmptyDocumentationTarget = this
override val presentation: TargetPresentation = TargetPresentation.builder("").presentation()
override fun presentation(): TargetPresentation = TargetPresentation.builder("").presentation()
override fun computeDocumentation(): DocumentationResult? = null
val request: DocumentationRequest = DocumentationRequest(this, presentation)
val request: DocumentationRequest = DocumentationRequest(this, presentation())
}
@@ -42,7 +42,7 @@ fun documentationTargets(file: PsiFile, offset: Int): List<DocumentationTarget>
internal fun DocumentationTarget.documentationRequest(): DocumentationRequest {
ApplicationManager.getApplication().assertReadAccessAllowed()
return DocumentationRequest(createPointer(), presentation)
return DocumentationRequest(createPointer(), presentation())
}
@Internal
@@ -62,7 +62,7 @@ class PsiElementDocumentationTarget private constructor(
override fun createPointer(): Pointer<out DocumentationTarget> = pointer
override val presentation: TargetPresentation get() = targetPresentation(targetElement)
override fun presentation(): TargetPresentation = targetPresentation(targetElement)
override val navigatable: Navigatable? get() = targetElement as? Navigatable
@@ -50,7 +50,7 @@ final class PsiExternalDocumentationHandlerTarget implements DocumentationTarget
@NotNull
@Override
public TargetPresentation getPresentation() {
public TargetPresentation presentation() {
return UtilKt.targetPresentation(myTargetElement);
}
@@ -50,7 +50,7 @@ private class UrlSymbol(
override fun getNavigationTargets(project: Project): Collection<NavigationTarget> = listOf(this)
override fun getTargetPresentation(): TargetPresentation = TODO(
override fun presentation(): TargetPresentation = TODO(
"In all known cases the symbol doesn't appear in the disambiguation popup, " +
"because this symbol is usually alone, so no popup required. Implement this method when needed."
)
@@ -1,9 +1,11 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.refactoring.rename.api
import com.intellij.model.Pointer
import com.intellij.navigation.TargetPresentation
import com.intellij.psi.search.SearchScope
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
import com.intellij.util.concurrency.annotations.RequiresReadLock
/**
* The thing being renamed.
@@ -41,7 +43,9 @@ interface RenameTarget {
* and [presentable text][TargetPresentation.presentableText] are used)
* @see com.intellij.find.usages.api.SearchTarget.presentation
*/
val presentation: TargetPresentation
@RequiresReadLock
@RequiresBackgroundThread
fun presentation(): TargetPresentation
/**
* The single [RenameTarget] might be referenced differently in different contexts,
@@ -3,6 +3,7 @@ package com.intellij.refactoring.rename.impl
import com.intellij.model.Pointer
import com.intellij.navigation.ItemPresentation
import com.intellij.navigation.TargetPresentation
import com.intellij.openapi.application.ApplicationManager
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.rename.api.RenameTarget
@@ -34,13 +35,15 @@ internal class RenameTarget2UsageTarget(
private fun computeItemPresentation(target: RenameTarget): ItemPresentation = object : ItemPresentation {
override fun getIcon(unused: Boolean): Icon? = target.presentation.icon
private val presentation: TargetPresentation = target.presentation()
override fun getIcon(unused: Boolean): Icon? = presentation.icon
override fun getPresentableText(): String = RefactoringBundle.message(
"rename.target.text.0.1", target.presentation.presentableText, newName
"rename.target.text.0.1", presentation.presentableText, newName
)
override fun getLocationString(): String? = target.presentation.locationText
override fun getLocationString(): String? = presentation.locationText
}
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.refactoring.rename.impl
import com.intellij.openapi.editor.Editor
@@ -13,7 +13,7 @@ class RenameTargetRenamer(
private val target: RenameTarget
) : Renamer {
override fun getPresentableText(): String = target.presentation.presentableText
override fun getPresentableText(): String = target.presentation().presentableText
override fun performRename(): Unit = startRename(project, editor, target)
}
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.refactoring.rename.impl
import com.intellij.codeInsight.actions.VcsFacade
@@ -52,7 +52,7 @@ internal fun showDialogAndRename(project: Project, target: RenameTarget, targetN
targetName = targetName,
renameOptions = renameOptions(project, target)
)
val dialog = RenameDialog(project, target.presentation.presentableText, initOptions)
val dialog = RenameDialog(project, target.presentation().presentableText, initOptions)
if (!dialog.showAndGet()) {
// cancelled
return
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.refactoring.rename.inplace
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
@@ -94,7 +94,7 @@ internal fun inplaceRename(project: Project, editor: Editor, target: RenameTarge
var textOptions: TextOptions = getTextOptions(target)
val data = prepareTemplate(hostDocument, hostFile, originUsage, psiUsages, textOptionsRef = { textOptions })
?: return false
val commandName: String = RefactoringBundle.message("rename.command.name.0.in.place.template", target.presentation.presentableText)
val commandName: String = RefactoringBundle.message("rename.command.name.0.in.place.template", target.presentation().presentableText)
val startMarkAction: StartMarkAction = try {
InplaceRefactoring.startMarkAction(project, hostEditor, commandName)
}
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.refactoring.rename.ui
import com.intellij.model.Pointer
@@ -62,7 +62,7 @@ private class CoroutineBackgroundTask(
private suspend fun Pointer<out RenameTarget>.presentableText(): String? {
return readAction {
dereference()?.presentation?.presentableText
dereference()?.presentation()?.presentableText
}
}
@@ -16,10 +16,11 @@ interface WebSymbolDocumentationTarget : DocumentationTarget {
val symbol: WebSymbol
@JvmDefault
override val presentation: TargetPresentation
get() = TargetPresentation.builder(symbol.name)
override fun presentation(): TargetPresentation {
return TargetPresentation.builder(symbol.name)
.icon(symbol.icon)
.presentation()
}
@JvmDefault
override fun computeDocumentation(): DocumentationResult? =
@@ -1,3 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.webSymbols.refactoring
import com.intellij.model.Pointer
@@ -17,7 +18,7 @@ open class WebSymbolRenameTarget(val symbol: WebSymbol) : RenameTarget {
override val targetName: String
get() = symbol.matchedName
override val presentation: TargetPresentation
get() = symbol.presentation
override fun presentation(): TargetPresentation {
return symbol.presentation
}
}
@@ -17,11 +17,12 @@ class WebSymbolSearchTargetImpl(override val symbol: WebSymbol) : WebSymbolSearc
}
}
override val presentation: TargetPresentation
get() = symbol.presentation
override fun presentation(): TargetPresentation {
return symbol.presentation
}
override val usageHandler: UsageHandler
get() = UsageHandler.createEmptyUsageHandler(presentation.presentableText)
get() = UsageHandler.createEmptyUsageHandler(presentation().presentableText)
override fun equals(other: Any?): Boolean =
other === this ||
@@ -17,8 +17,8 @@ import com.intellij.psi.util.PsiModificationTracker
import com.intellij.util.containers.Stack
import com.intellij.webSymbols.*
import com.intellij.webSymbols.html.WebSymbolHtmlAttributeValue
import com.intellij.webSymbols.references.WebSymbolReferenceProblem.ProblemKind
import com.intellij.webSymbols.impl.sortSymbolsByPriority
import com.intellij.webSymbols.references.WebSymbolReferenceProblem.ProblemKind
import com.intellij.webSymbols.registry.WebSymbolMatch
import com.intellij.webSymbols.registry.WebSymbolNamesProvider
import com.intellij.webSymbols.registry.WebSymbolsNameMatchQueryParams
@@ -194,7 +194,7 @@ fun Sequence<WebSymbolHtmlAttributeValue?>.merge(): WebSymbolHtmlAttributeValue?
fun NavigationTarget.createPsiRangeNavigationItem(element: PsiElement, offsetWithinElement: Int): Navigatable {
val vf = element.containingFile.virtualFile
?: return EmptyNavigatable.INSTANCE
val targetPresentation = this.targetPresentation
val targetPresentation = this.presentation()
val descriptor = OpenFileDescriptor(
element.project, vf, element.textRange.startOffset + offsetWithinElement)
@@ -1,4 +1,4 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.editorconfig.language.documentation
import com.intellij.codeInsight.documentation.DocumentationManager
@@ -22,7 +22,7 @@ class EditorConfigDocumentationTest : BasePlatformTestCase() {
val targets = IdeDocumentationTargetProvider.getInstance(project).documentationTargets(myFixture.editor, myFixture.file, offset)
UsefulTestCase.assertSize(1, targets)
val target = targets[0]
val text = target.presentation.presentableText
val text = target.presentation().presentableText
assertEquals("indent_size", text)
val doc = EditorConfigDocumentationProvider().generateDoc(element, originalElement)
val expected = "number of whitespace symbols used for indents"
@@ -50,14 +50,13 @@ abstract class GradleProjectSymbol(
override val usageHandler: UsageHandler get() = UsageHandler.createEmptyUsageHandler(projectName)
override val presentation: TargetPresentation
get() {
val presentation = symbolPresentation
return TargetPresentation
.builder(presentation.longDescription)
.icon(presentation.icon)
.presentation()
}
override fun presentation(): TargetPresentation {
val presentation = symbolPresentation
return TargetPresentation
.builder(presentation.longDescription)
.icon(presentation.icon)
.presentation()
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -47,7 +47,9 @@ internal class KotlinDocumentationTarget(val element: PsiElement, private val or
}
}
override val presentation: TargetPresentation get() = targetPresentation(element)
override fun presentation(): TargetPresentation {
return targetPresentation(element)
}
override fun computeDocumentationHint(): String? {
return computeLocalDocumentation(element, originalElement, true)
@@ -24,8 +24,9 @@ internal class KotlinNamedDeclarationRenameUsage private constructor(
override val targetName: String
get() = element.name ?: reportMissingName()
override val presentation: TargetPresentation
get() = TargetPresentation.builder(targetName).presentation()
override fun presentation(): TargetPresentation {
return TargetPresentation.builder(targetName).presentation()
}
override val file: PsiFile
get() = element.containingFile
@@ -52,7 +52,7 @@ class MarkdownLinkDestination(node: ASTNode): MarkdownLinkDestinationImpl(node),
return Pointer.hardPointer(this)
}
override fun getTargetPresentation(): TargetPresentation {
override fun presentation(): TargetPresentation {
return TargetPresentation.builder(text)
.icon(MarkdownIcons.EditorActions.Link)
.presentation()
@@ -55,13 +55,10 @@ data class HeaderSymbol(
override val maximalSearchScope: SearchScope
get() = GlobalSearchScope.allScope(file.project)
override val presentation: TargetPresentation
get() = targetPresentation
override val usageHandler: UsageHandler
get() = UsageHandler.createEmptyUsageHandler(anchorText)
override fun getTargetPresentation(): TargetPresentation {
override fun presentation(): TargetPresentation {
val virtualFile = file.containingFile.virtualFile
val builder = TargetPresentation.builder(text).icon(MarkdownIcons.EditorActions.Header_level_up)
val presentation = when (virtualFile) {
@@ -47,16 +47,13 @@ data class LinkLabelSymbol(
override val maximalSearchScope: SearchScope?
get() = GlobalSearchScope.fileScope(file)
override val presentation: TargetPresentation
get() = targetPresentation
override val usageHandler: UsageHandler
get() = UsageHandler.createEmptyUsageHandler(text)
override val searchText: String
get() = text
override fun getTargetPresentation(): TargetPresentation {
override fun presentation(): TargetPresentation {
return TargetPresentation.builder(text).icon(MarkdownIcons.EditorActions.Link).presentation()
}