Skip to content

Commit

Permalink
#258 | Improved PSI cache usage
Browse files Browse the repository at this point in the history
  • Loading branch information
mlytvyn authored Mar 3, 2023
1 parent d10dda0 commit 5271ad0
Show file tree
Hide file tree
Showing 25 changed files with 466 additions and 429 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@
/.idea/misc.xml
/.idea/vcs.xml
/.idea/.gitignore
/.idea/hybrisProjectSettings.xml

/rt-ant/out/
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
idea
kotlin("jvm")
id("org.jetbrains.intellij") version "1.13.1-SNAPSHOT"
id("org.jetbrains.intellij") version "1.13.1"
}

sourceSets.main {
Expand Down
1 change: 1 addition & 0 deletions resources/META-INF/plugin-release-info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
<![CDATA[
<h3>2023.1.2</h3>
<ul>
<li><i>Feature:</i> Improved PSI cache usage (<a href="https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/258" target="_blank" rel="nofollow">#258</a>)</li>
<li><i>Feature:</i> Improved performance of the Global Meta Model and TS LineMarker (<a href="https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/257" target="_blank" rel="nofollow">#257</a>)</li>
</ul>
<h3>2023.1.1</h3>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiIdentifier
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker
import com.intellij.psi.xml.XmlElement
import javax.swing.Icon

Expand All @@ -53,7 +54,7 @@ abstract class AbstractTSItemLineMarkerProvider<T : PsiElement> : RelatedItemLin
CachedValuesManager.getCachedValue(element) {
CachedValueProvider.Result.create(
collectDeclarations(element as T),
TSMetaModelAccess.getInstance(element.project).getMetaModel()
TSMetaModelAccess.getInstance(element.project).getMetaModel(), PsiModificationTracker.MODIFICATION_COUNT
)
}
?.let { result.add(it) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ private class ImpexHeaderLineVisitor(private val problemsHolder: ProblemsHolder)

if (result.isEmpty()) {
val typeName = findHeaderItemTypeName(parameter)
.map { it.text }
.orElse("")
?.text
?: ""
problemsHolder.registerProblem(
parameter,
message("hybris.inspections.impex.ImpexUnknownTypeAttributeInspection.key", parameter.text, typeName),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,107 +13,116 @@ import com.intellij.idea.plugin.hybris.system.type.meta.TSMetaModelAccess
import com.intellij.idea.plugin.hybris.system.type.psi.reference.result.AttributeResolveResult
import com.intellij.idea.plugin.hybris.system.type.psi.reference.result.EnumResolveResult
import com.intellij.idea.plugin.hybris.system.type.psi.reference.result.RelationEndResolveResult
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.psi.PsiElement
import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.*

internal class FxsTSAttributeReference(owner: FlexibleSearchColumnReference) : TSReferenceBase<FlexibleSearchColumnReference>(owner),
HighlightedReference {

override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> {
val featureName = element.text.replace("!", "")
val result = if (hasPrefix(element)) {
findReference(deepSearchOfTypeReference(element, element.firstChild.text), element.lastChild.text)
} else {
findReference(findItemTypeReference(), featureName)
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> = CachedValuesManager.getManager(project)
.getParameterizedCachedValue(element, CACHE_KEY, provider, false, this)
.let { PsiUtils.getValidResults(it) }

companion object {
val CACHE_KEY = Key.create<ParameterizedCachedValue<Array<ResolveResult>, FxsTSAttributeReference>>("HYBRIS_TS_CACHED_REFERENCE")

private val provider = ParameterizedCachedValueProvider<Array<ResolveResult>, FxsTSAttributeReference> { ref ->
val featureName = ref.element.text.replace("!", "")
val result: Array<ResolveResult> = if (hasPrefix(ref.element)) {
findReference(ref.project, deepSearchOfTypeReference(ref.element, ref.element.firstChild.text), ref.element.lastChild.text)
} else {
findReference(ref.project, findItemTypeReference(ref.element), featureName)
}

CachedValueProvider.Result.create(
result,
TSMetaModelAccess.getInstance(ref.project).getMetaModel(), PsiModificationTracker.MODIFICATION_COUNT
)
}
return PsiUtils.getValidResults(result)
}

private fun hasPrefix(element: FlexibleSearchColumnReference) =
((element.firstChild as LeafPsiElement).elementType == FlexibleSearchTypes.TABLE_NAME_IDENTIFIER)
private fun hasPrefix(element: FlexibleSearchColumnReference) =
((element.firstChild as LeafPsiElement).elementType == FlexibleSearchTypes.TABLE_NAME_IDENTIFIER)

private fun findReference(project: Project, itemType: FlexibleSearchTableName?, refName: String): Array<ResolveResult> {
val metaService = TSMetaModelAccess.getInstance(project)
val type = itemType
?.text
?.replace("!", "")
?: return ResolveResult.EMPTY_ARRAY
return tryResolveByItemType(type, refName, metaService)
?: tryResolveByRelationType(type, refName, metaService)
?: tryResolveByEnumType(type, refName, metaService)
?: ResolveResult.EMPTY_ARRAY
}

private fun findReference(itemType: FlexibleSearchTableName?, refName: String): Array<ResolveResult> {
val metaService = TSMetaModelAccess.getInstance(project)
val type = itemType
?.text
?.replace("!", "")
?: return ResolveResult.EMPTY_ARRAY
return tryResolveByItemType(type, refName, metaService)
?: tryResolveByRelationType(type, refName, metaService)
?: tryResolveByEnumType(type, refName, metaService)
?: ResolveResult.EMPTY_ARRAY
}
private fun tryResolveByItemType(type: String, refName: String, metaService: TSMetaModelAccess): Array<ResolveResult>? =
metaService.findMetaItemByName(type)
?.let { meta ->
val attributes = meta.allAttributes
.filter { refName.equals(it.name, true) }
.map { AttributeResolveResult(it) }

private fun tryResolveByItemType(type: String, refName: String, metaService: TSMetaModelAccess): Array<ResolveResult>? =
metaService.findMetaItemByName(type)
?.let { meta ->
val attributes = meta.allAttributes
.filter { refName.equals(it.name, true) }
.map { AttributeResolveResult(it) }
val relations = meta.allRelationEnds
.filter { refName.equals(it.name, true) }
.map { RelationEndResolveResult(it) }

val relations = meta.allRelationEnds
.filter { refName.equals(it.name, true) }
.map { RelationEndResolveResult(it) }
(attributes + relations).toTypedArray()
}

(attributes + relations).toTypedArray()
}
private fun tryResolveByRelationType(type: String, refName: String, metaService: TSMetaModelAccess): Array<ResolveResult>? {
val meta = metaService.findMetaRelationByName(type) ?: return null

private fun tryResolveByRelationType(type: String, refName: String, metaService: TSMetaModelAccess): Array<ResolveResult>? {
val meta = metaService.findMetaRelationByName(type) ?: return null
if (SOURCE_ATTRIBUTE_NAME.equals(refName, true)) {
return arrayOf(RelationEndResolveResult(meta.source))
} else if (TARGET_ATTRIBUTE_NAME.equals(refName, true)) {
return arrayOf(RelationEndResolveResult(meta.target))
}

if (SOURCE_ATTRIBUTE_NAME.equals(refName, true)) {
return arrayOf(RelationEndResolveResult(meta.source))
} else if (TARGET_ATTRIBUTE_NAME.equals(refName, true)) {
return arrayOf(RelationEndResolveResult(meta.target))
return metaService.findMetaItemByName(HybrisConstants.TS_TYPE_LINK)
?.attributes
?.get(refName)
?.let { arrayOf(AttributeResolveResult(it)) }
}

return metaService.findMetaItemByName(HybrisConstants.TS_TYPE_LINK)
?.attributes
?.get(refName)
?.let { arrayOf(AttributeResolveResult(it)) }
}

private fun tryResolveByEnumType(type: String, refName: String, metaService: TSMetaModelAccess): Array<ResolveResult>? {
val meta = metaService.findMetaEnumByName(type) ?: return null
private fun tryResolveByEnumType(type: String, refName: String, metaService: TSMetaModelAccess): Array<ResolveResult>? {
val meta = metaService.findMetaEnumByName(type) ?: return null

return if (CODE_ATTRIBUTE_NAME == refName || NAME_ATTRIBUTE_NAME == refName) {
arrayOf(EnumResolveResult(meta))
} else return null
}
return if (CODE_ATTRIBUTE_NAME == refName || NAME_ATTRIBUTE_NAME == refName) {
arrayOf(EnumResolveResult(meta))
} else return null
}

private fun findItemTypeReference(): FlexibleSearchTableName? {
return PsiTreeUtil.getParentOfType(element, FlexibleSearchQuerySpecification::class.java)
private fun findItemTypeReference(element: PsiElement) = PsiTreeUtil.getParentOfType(element, FlexibleSearchQuerySpecification::class.java)
?.let {
PsiTreeUtil.findChildOfType(it, FlexibleSearchFromClause::class.java)
?.tableReferenceList
?.let { PsiTreeUtil.findChildOfType(it, FlexibleSearchTableName::class.java) }
}
}

private fun deepSearchOfTypeReference(elem: PsiElement, prefix: String): FlexibleSearchTableName? {
val parent = PsiTreeUtil.getParentOfType(elem, FlexibleSearchQuerySpecification::class.java)
val tables = PsiTreeUtil.findChildrenOfType(parent, FlexibleSearchTableReference::class.java).toList()
private fun deepSearchOfTypeReference(elem: PsiElement, prefix: String): FlexibleSearchTableName? {
val parent = PsiTreeUtil.getParentOfType(elem, FlexibleSearchQuerySpecification::class.java)
val tables = PsiTreeUtil.findChildrenOfType(parent, FlexibleSearchTableReference::class.java).toList()

val tableReference = tables.find {
val tableName = PsiTreeUtil.findChildOfAnyType(it, FlexibleSearchTableName::class.java)
val corName = findCorName(tableName)
prefix == corName
}
return if (tableReference == null && parent != null) {
deepSearchOfTypeReference(parent, prefix)
} else {
PsiTreeUtil.findChildOfType(tableReference, FlexibleSearchTableName::class.java)
val tableReference = tables.find {
val tableName = PsiTreeUtil.findChildOfAnyType(it, FlexibleSearchTableName::class.java)
val corName = findCorName(tableName)
prefix == corName
}
return if (tableReference == null && parent != null) {
deepSearchOfTypeReference(parent, prefix)
} else {
PsiTreeUtil.findChildOfType(tableReference, FlexibleSearchTableName::class.java)
}
}
}

private fun findCorName(tableName: FlexibleSearchTableName?): String {
val corNameEl = PsiTreeUtil.findSiblingForward(tableName!!.originalElement, FlexibleSearchTypes.CORRELATION_NAME, null)
if (corNameEl == null) {
return tableName.text
}
return corNameEl.text
private fun findCorName(tableName: FlexibleSearchTableName?) = PsiTreeUtil.findSiblingForward(tableName!!.originalElement, FlexibleSearchTypes.CORRELATION_NAME, null)
?.text
?: tableName.text

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,37 @@ import com.intellij.idea.plugin.hybris.psi.utils.PsiUtils
import com.intellij.idea.plugin.hybris.system.type.meta.TSMetaModelAccess
import com.intellij.idea.plugin.hybris.system.type.psi.reference.result.ItemResolveResult
import com.intellij.idea.plugin.hybris.system.type.psi.reference.result.RelationResolveResult
import com.intellij.openapi.util.Key
import com.intellij.psi.ResolveResult
import com.intellij.psi.util.*

class FxsTSItemReference(owner: FlexibleSearchTableName) : TSReferenceBase<FlexibleSearchTableName>(owner), HighlightedReference {

override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> {
val lookingForName = element.text.replace("!", "")
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> = CachedValuesManager.getManager(project)
.getParameterizedCachedValue(element, CACHE_KEY, provider, false, this)
.let { PsiUtils.getValidResults(it) }

val items = (TSMetaModelAccess.getInstance(project).findMetaItemByName(lookingForName)
?.declarations
?.map { ItemResolveResult(it) }
?: emptyList())
companion object {
val CACHE_KEY = Key.create<ParameterizedCachedValue<Array<ResolveResult>, FxsTSItemReference>>("HYBRIS_TS_CACHED_REFERENCE")

val relations = TSMetaModelAccess.getInstance(project).findRelationByName(lookingForName)
private val provider = ParameterizedCachedValueProvider<Array<ResolveResult>, FxsTSItemReference> { ref ->
val lookingForName = ref.element.text.replace("!", "")
val modelAccess = TSMetaModelAccess.getInstance(ref.project)

val items = (modelAccess.findMetaItemByName(lookingForName)
?.declarations
?.map { ItemResolveResult(it) }
?: emptyList())

val relations = modelAccess.findRelationByName(lookingForName)
.distinctBy { it.name }
.map { RelationResolveResult(it) }

return PsiUtils.getValidResults((items + relations).toTypedArray())
CachedValueProvider.Result.create(
(items + relations).toTypedArray(),
modelAccess.getMetaModel(), PsiModificationTracker.MODIFICATION_COUNT
)
}
}

}
Loading

0 comments on commit 5271ad0

Please sign in to comment.