Skip to content

Commit

Permalink
remove old code, performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
mkurnikov committed Aug 9, 2024
1 parent fd1e458 commit 627cbc9
Show file tree
Hide file tree
Showing 16 changed files with 141 additions and 199 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class MvSyntaxErrorAnnotator: MvAnnotatorBase() {
}

private fun checkIndexExpr(holder: MvAnnotationHolder, indexExpr: MvIndexExpr) {
// always supported in specs
if (indexExpr.isMsl()) return
if (!indexExpr.project.moveSettings.enableIndexExpr) {
Diagnostic
.IndexExprIsNotSupportedInCompilerV1(indexExpr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import org.move.ide.inspections.imports.ImportAnalyzer2
class MvUnusedImportInspection: MvLocalInspectionTool() {

override fun buildMvVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = ImportAnalyzer2(holder)
// override fun buildMvVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = ImportAnalyzer(holder)

@Suppress("CompanionObjectInExtension")
companion object {
Expand Down
61 changes: 29 additions & 32 deletions src/main/kotlin/org/move/ide/inspections/imports/BasePathType.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package org.move.ide.inspections.imports

import com.intellij.openapi.util.Key
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValueProvider.Result
import com.intellij.psi.util.PsiModificationTracker
import org.move.lang.core.psi.*
import org.move.lang.core.psi.NamedItemScope.*
import org.move.lang.core.psi.ext.*
import org.move.utils.cache
import org.move.utils.cacheManager
import org.move.utils.cacheResult

// classifies foo of `foo::bar::baz`
sealed class BasePathType {
Expand Down Expand Up @@ -34,42 +43,30 @@ fun MvPath.basePathType(): BasePathType? {
return qualifier.referenceName?.let { BasePathType.Module(it) }
}

// only Main/Test for now
val MvElement.usageScope: NamedItemScope
get() {
var parentElement = this.parent
while (parentElement != null) {
// if (parentElement is MslOnlyElement) return ItemScope.MAIN
if (parentElement is MvDocAndAttributeOwner && parentElement.hasTestOnlyAttr) {
return NamedItemScope.TEST
}
if (parentElement is MvDocAndAttributeOwner && parentElement.hasVerifyOnlyAttr) {
return NamedItemScope.VERIFY
private val USAGE_SCOPE_KEY: Key<CachedValue<NamedItemScope>> = Key.create("USAGE_SCOPE_KEY")

class UsageScopeProvider(val scopeElement: MvElement): CachedValueProvider<NamedItemScope> {
override fun compute(): Result<NamedItemScope> {
var scope = MAIN
for (ancestor in scopeElement.ancestorsOfType<MvDocAndAttributeOwner>()) {
// msl items
if (scopeElement is MvSpecCodeBlock || scopeElement is MvItemSpecRef) {
scope = VERIFY
break
}
if (parentElement is MvFunction && parentElement.hasTestAttr) {
return NamedItemScope.TEST
// explicit attrs, #[test], #[test_only], #[verify_only]
val attributeScope = ancestor.itemScopeFromAttributes()
if (attributeScope != null) {
scope = attributeScope
break
}
parentElement = parentElement.parent
}
return NamedItemScope.MAIN
return scopeElement.cacheResult(scope, listOf(PsiModificationTracker.MODIFICATION_COUNT))
}
}

// only Main/Test for now
val MvUseStmt.declaredItemScope: NamedItemScope
val MvElement.usageScope: NamedItemScope
get() {
if (this.hasTestOnlyAttr) {
return NamedItemScope.TEST
}
var parentElement = this.parent
while (parentElement != null) {
// if (parentElement is MslOnlyElement) return ItemScope.MAIN
if (parentElement is MvDocAndAttributeOwner && parentElement.hasTestOnlyAttr) {
return NamedItemScope.TEST
}
if (parentElement is MvFunction && parentElement.hasTestAttr) {
return NamedItemScope.TEST
}
parentElement = parentElement.parent
}
return NamedItemScope.MAIN
return project.cacheManager
.cache(this, USAGE_SCOPE_KEY, UsageScopeProvider(this))
}
36 changes: 21 additions & 15 deletions src/main/kotlin/org/move/ide/inspections/imports/ImportAnalyzer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import org.move.stdext.chain
class ImportAnalyzer2(val holder: ProblemsHolder): MvVisitor() {

override fun visitModule(o: MvModule) = analyzeImportsOwner(o)
// override fun visitModuleBlock(o: MvModuleBlock) = analyzeImportsOwner(o)
override fun visitScript(o: MvScript) = analyzeImportsOwner(o)
// override fun visitScriptBlock(o: MvScriptBlock) = analyzeImportsOwner(o)
override fun visitModuleSpecBlock(o: MvModuleSpecBlock) = analyzeImportsOwner(o)

fun analyzeImportsOwner(importsOwner: MvItemsOwner) {
Expand All @@ -24,28 +22,36 @@ class ImportAnalyzer2(val holder: ProblemsHolder): MvVisitor() {
val allUseItemsHit = mutableSetOf<UseItem>()
val rootItemOwnerWithSiblings = rootItemsOwner.itemsOwnerWithSiblings

val paths = rootItemOwnerWithSiblings
.flatMap { it.descendantsOfType<MvPath>() }
.filter { it.basePath() == it }
.filter { it.usageScope == itemScope }
.filter { !it.hasAncestor<MvUseSpeck>() }
val allFiles = rootItemOwnerWithSiblings.mapNotNull { it.containingMoveFile }.distinct()
val fileItemOwners = allFiles
// collect every possible MvItemOwner
.flatMap { it.descendantsOfType<MvItemsOwner>().flatMap { i -> i.itemsOwnerWithSiblings } }
.distinct()
.associateWith { itemOwner ->
itemOwner.useItems.filter { it.scope == itemScope }
}

val reachablePaths =
rootItemOwnerWithSiblings
.flatMap { it.descendantsOfType<MvPath>() }
.filter { it.basePath() == it }
.filter { it.usageScope == itemScope }
.filter { !it.hasAncestor<MvUseSpeck>() }

for (path in paths) {
for (path in reachablePaths) {
val basePathType = path.basePathType()
for (itemsOwner in path.ancestorsOfType<MvItemsOwner>()) {
val useItems =
itemsOwner.itemsOwnerWithSiblings
.flatMap { it.useItems }.filter { it.scope == itemScope }

val reachableUseItems =
itemsOwner.itemsOwnerWithSiblings.flatMap { fileItemOwners[it]!! }
val useItemHit =
when (basePathType) {
is BasePathType.Item -> {
useItems.filter { it.type == ITEM }
reachableUseItems.filter { it.type == ITEM }
// only hit first encountered to remove duplicates
.firstOrNull { it.nameOrAlias == basePathType.itemName }
}
is BasePathType.Module -> {
useItems.filter { it.type == MODULE || it.type == SELF_MODULE }
reachableUseItems.filter { it.type == MODULE || it.type == SELF_MODULE }
// only hit first encountered to remove duplicates
.firstOrNull { it.nameOrAlias == basePathType.moduleName }
}
Expand All @@ -63,7 +69,7 @@ class ImportAnalyzer2(val holder: ProblemsHolder): MvVisitor() {
// includes self
val reachableItemsOwners = rootItemsOwner.descendantsOfTypeOrSelf<MvItemsOwner>()
for (itemsOwner in reachableItemsOwners) {
val scopeUseStmts = itemsOwner.useStmtList.filter { it.declaredItemScope == itemScope }
val scopeUseStmts = itemsOwner.useStmtList.filter { it.usageScope == itemScope }
for (useStmt in scopeUseStmts) {
val unusedUseItems = useStmt.useItems.toSet() - allUseItemsHit
holder.registerStmtSpeckError2(useStmt, unusedUseItems)
Expand Down
13 changes: 6 additions & 7 deletions src/main/kotlin/org/move/ide/inspections/imports/UseItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,16 @@ data class UseItem(
val scope: NamedItemScope
)

val MvItemsOwner.useItems: List<UseItem>
get() = this.useStmtList.flatMap { it.useItems }
val MvItemsOwner.useItems: List<UseItem> get() = this.useStmtList.flatMap { it.useItems }

val MvUseStmt.useItems: List<UseItem>
get() {
val items = mutableListOf<UseItem>()
val stmtItemScope = this.declaredItemScope
this.forEachLeafSpeck { path, useAlias ->
val useSpeck = path.parent as MvUseSpeck
val nameOrAlias = useAlias?.name ?: path.referenceName ?: return@forEachLeafSpeck false
val pathKind = path.pathKind()
val stmtItemScope = this.usageScope
this.forEachLeafSpeck { speckPath, useAlias ->
val useSpeck = speckPath.parent as MvUseSpeck
val nameOrAlias = useAlias?.name ?: speckPath.referenceName ?: return@forEachLeafSpeck false
val pathKind = speckPath.pathKind()
when (pathKind) {
is PathKind.QualifiedPath.Module ->
items.add(UseItem(useSpeck, nameOrAlias, MODULE, stmtItemScope))
Expand Down
5 changes: 3 additions & 2 deletions src/main/kotlin/org/move/ide/utils/imports/ImportUtils.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.move.ide.utils.imports

import org.move.ide.inspections.imports.usageScope
import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.*
import org.move.lang.core.types.ItemQualName
Expand All @@ -13,8 +14,8 @@ fun ImportCandidate.import(context: MvElement) {
checkWriteAccessAllowed()
val insertionScope = context.containingModule ?: context.containingScript ?: return
val insertTestOnly =
insertionScope.itemScope == NamedItemScope.MAIN
&& context.itemScope == NamedItemScope.TEST
insertionScope.usageScope == NamedItemScope.MAIN
&& context.usageScope == NamedItemScope.TEST
insertionScope.insertUseItem(qualName, insertTestOnly)
}

Expand Down
117 changes: 3 additions & 114 deletions src/main/kotlin/org/move/lang/core/psi/NamedItemScope.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package org.move.lang.core.psi

import com.intellij.openapi.util.Key
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValuesManager
import org.move.lang.core.psi.ext.*
import org.move.lang.core.resolve.ref.MvReferenceElement

enum class NamedItemScope {
MAIN,
Expand All @@ -19,129 +15,22 @@ enum class NamedItemScope {
}
return this
}

companion object {
fun all(): Set<NamedItemScope> = setOf(MAIN, TEST, VERIFY)
}
}

//fun MvElement.isVisibleInContext(contextScope: NamedItemScope): Boolean {
// val itemScope = this.itemScope
// // MAIN scope items are visible from any context
// return itemScope == NamedItemScope.MAIN || itemScope == contextScope
//}

fun MvNamedElement.isVisibleInContext(refItemScopes: Set<NamedItemScope>): Boolean {
// for (requiredScope in this.itemScopes) {
// if (!contextScopes.contains(requiredScope)) return false
// }
val requiredScopes = this.namedItemScopes
return (requiredScopes - refItemScopes).isEmpty()
// MAIN scope items are visible from any context
// return itemScope == ItemScope.MAIN || itemScope == contextScope
}


private val ITEM_SCOPES_KEY =
Key.create<CachedValue<Set<NamedItemScope>>>("org.move.ITEM_SCOPES_KEY")

val MvReferenceElement.refItemScopes: Set<NamedItemScope>
get() {
return (this as MvElement).itemScopes
}

val MvNamedElement.namedItemScopes: Set<NamedItemScope>
get() {
return (this as MvElement).itemScopes
}

val MvElement.itemScopes: Set<NamedItemScope>
get() {
// TODO: special case module items to use stub-only in some cases
// project.cacheManager.cache(this, ITEM_SCOPES_KEY) {
val scopes = mutableSetOf(NamedItemScope.MAIN)
var element: MvElement? = this
if (element is MvStruct || element is MvFunction) {
val attributeScopes = (element as MvDocAndAttributeOwner).explicitItemScopes()
return attributeScopes
}
while (element != null) {
when (element) {
is MvDocAndAttributeOwner -> {
val attributeScopes = element.explicitItemScopes()
scopes.addAll(attributeScopes)
// val ownerItemScope = element.explicitAttributeItemScope()
// if (ownerItemScope != null) {
// scopes.add(ownerItemScope)
// }
}
is MvSpecCodeBlock, is MvItemSpecRef -> scopes.add(NamedItemScope.VERIFY)
}
element = element.parent as? MvElement
}
return scopes
// cacheResult(scopes, listOf(PsiModificationTracker.MODIFICATION_COUNT))
}

val MvElement.itemScope: NamedItemScope
get() {
return CachedValuesManager.getProjectPsiDependentCache(this) {
var element = it
while (element != null) {
when (element) {
is MvDocAndAttributeOwner -> {
val ownerItemScope = element.explicitAttributeItemScope()
if (ownerItemScope != null) {
return@getProjectPsiDependentCache ownerItemScope
}
}
is MvSpecCodeBlock, is MvItemSpecRef -> return@getProjectPsiDependentCache NamedItemScope.VERIFY
}
element = element.parent as? MvElement
}
NamedItemScope.MAIN
}
}

private fun MvDocAndAttributeOwner.explicitItemScopes(): Set<NamedItemScope> {
val scopes = mutableSetOf<NamedItemScope>()
when {
this.hasTestOnlyAttr -> scopes.add(NamedItemScope.TEST)
this.hasVerifyOnlyAttr -> scopes.add(NamedItemScope.VERIFY)
this is MvStruct -> {
scopes.addAll(this.module.explicitItemScopes())
}
this is MvFunction -> {
if (this.hasTestAttr) {
scopes.add(NamedItemScope.TEST)
}
scopes.addAll(this.module?.explicitItemScopes().orEmpty())
}
}
// if (this.hasTestOnlyAttr || (this is MvFunction && this.hasTestAttr)) {
// scopes.add(NamedItemScope.TEST)
// }
// if (this.hasVerifyOnlyAttr) {
// scopes.add(NamedItemScope.VERIFY)
// }
return scopes
}

private fun MvDocAndAttributeOwner.explicitAttributeItemScope(): NamedItemScope? =
fun MvDocAndAttributeOwner.itemScopeFromAttributes(): NamedItemScope? =
when (this) {
// is MvSpecInlineFunction -> ItemScope.MAIN
is MvFunction ->
when {
this.hasTestOnlyAttr || this.hasTestAttr -> NamedItemScope.TEST
this.hasVerifyOnlyAttr -> NamedItemScope.VERIFY
else ->
this.module?.explicitAttributeItemScope() ?: NamedItemScope.MAIN
this.module?.itemScopeFromAttributes() ?: NamedItemScope.MAIN
}
is MvStruct ->
when {
this.hasTestOnlyAttr -> NamedItemScope.TEST
this.hasVerifyOnlyAttr -> NamedItemScope.VERIFY
else -> this.module.explicitAttributeItemScope() ?: NamedItemScope.MAIN
else -> this.module.itemScopeFromAttributes() ?: NamedItemScope.MAIN
}
else ->
when {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ val MvVisibilityOwner.visibility2: Visibility2
PACKAGE -> containingMovePackage?.let { Visibility2.Restricted.Package(it) } ?: Visibility2.Public
FRIEND -> {
val module = this.containingModule ?: return Visibility2.Private
// todo: make lazy
Visibility2.Restricted.Friend(lazy { module.friendModules })
}
SCRIPT -> Visibility2.Restricted.Script
Expand Down
5 changes: 5 additions & 0 deletions src/main/kotlin/org/move/lang/core/psi/ext/PsiElement.kt
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ inline fun <reified T: PsiElement> PsiElement.ancestorsOfType(): Sequence<T> {
return this.ancestors.filterIsInstance<T>()
}

inline fun <reified T: PsiElement> PsiElement.ancestorsOfTypeWithSelf(): Sequence<T> {
return (sequenceOf(this) + this.ancestors).filterIsInstance<T>()
// return this.ancestors.filterIsInstance<T>()
}

fun PsiElement.findFirstParent(strict: Boolean = true, cond: Condition<in PsiElement>) =
PsiTreeUtil.findFirstParent(this, strict, cond)

Expand Down
8 changes: 4 additions & 4 deletions src/main/kotlin/org/move/lang/core/resolve/Processors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -558,10 +558,10 @@ fun RsResolveProcessor.processAllItems(
namespaces: Set<Namespace>,
vararg collections: Iterable<MvItemElement>,
): Boolean {
return sequenceOf(*collections).flatten().any { e ->
val name = e.name ?: return false
val visibilityFilter = e.visInfo().createFilter()
process(ScopeEntryWithVisibility(name, e, namespaces, visibilityFilter))
return sequenceOf(*collections).flatten().any { itemElement ->
val name = itemElement.name ?: return false
val visibilityFilter = itemElement.visInfo().createFilter()
process(ScopeEntryWithVisibility(name, itemElement, namespaces, visibilityFilter))
}
}

Expand Down
Loading

0 comments on commit 627cbc9

Please sign in to comment.