diff --git a/src/main/kotlin/org/move/cli/BuildDirectoryWatcher.kt b/src/main/kotlin/org/move/cli/BuildDirectoryWatcher.kt index ad6c89b62..73f3ffdcd 100644 --- a/src/main/kotlin/org/move/cli/BuildDirectoryWatcher.kt +++ b/src/main/kotlin/org/move/cli/BuildDirectoryWatcher.kt @@ -14,9 +14,9 @@ class BuildDirectoryWatcher( } override fun after(events: MutableList) { - val builds = moveProjects.map { FileUtil.join(it.contentRoot.path, "build") } + val buildDirectories = moveProjects.map { FileUtil.join(it.contentRoot.path, "build") } for (event in events) { - if (builds.any { event.pathStartsWith(it) }) { + if (buildDirectories.any { event.pathStartsWith(it) }) { onChange() return } diff --git a/src/main/kotlin/org/move/cli/MoveTomlWatcher.kt b/src/main/kotlin/org/move/cli/MoveTomlWatcher.kt index 864935755..5c5486665 100644 --- a/src/main/kotlin/org/move/cli/MoveTomlWatcher.kt +++ b/src/main/kotlin/org/move/cli/MoveTomlWatcher.kt @@ -17,8 +17,10 @@ class MoveTomlWatcher( } } -fun VFileEvent.pathStartsWith(prefix: String): Boolean = path.startsWith(prefix) || - this is VFilePropertyChangeEvent && oldPath.startsWith(prefix) +fun VFileEvent.pathStartsWith(prefix: String): Boolean = + path.startsWith(prefix) || + this is VFilePropertyChangeEvent && oldPath.startsWith(prefix) -fun VFileEvent.pathEndsWith(suffix: String): Boolean = path.endsWith(suffix) || - this is VFilePropertyChangeEvent && oldPath.endsWith(suffix) +fun VFileEvent.pathEndsWith(suffix: String): Boolean = + path.endsWith(suffix) || + this is VFilePropertyChangeEvent && oldPath.endsWith(suffix) diff --git a/src/main/kotlin/org/move/lang/core/completion/providers/MvPathCompletionProvider.kt b/src/main/kotlin/org/move/lang/core/completion/providers/MvPathCompletionProvider.kt index 58de35df0..aa2a2409a 100644 --- a/src/main/kotlin/org/move/lang/core/completion/providers/MvPathCompletionProvider.kt +++ b/src/main/kotlin/org/move/lang/core/completion/providers/MvPathCompletionProvider.kt @@ -120,7 +120,7 @@ object TypesCompletionProvider : MvPathCompletionProvider() { return ItemVis( setOf(Namespace.TYPE), Visibility.none(), - mslScope = MslScope.NONE, + mslScope = pathElement.mslScope, itemScope = pathElement.itemScope, ) } diff --git a/src/main/kotlin/org/move/lang/core/psi/ext/PsiElement.kt b/src/main/kotlin/org/move/lang/core/psi/ext/PsiElement.kt index 629a352e0..59414e064 100644 --- a/src/main/kotlin/org/move/lang/core/psi/ext/PsiElement.kt +++ b/src/main/kotlin/org/move/lang/core/psi/ext/PsiElement.kt @@ -186,6 +186,10 @@ fun PsiElement.equalsTo(another: PsiElement): Boolean = fun PsiElement.isMsl(): Boolean { return getProjectPsiDependentCache(this) { if (it !is MvElement) return@getProjectPsiDependentCache false + + // use items always non-msl, otherwise import resolution doesn't work correctly + if (it is MvUseItem) return@getProjectPsiDependentCache false + val specElement = PsiTreeUtil.findFirstParent(it, false) { parent -> parent is MvSpecFunction || parent is MvItemSpecBlockExpr diff --git a/src/main/kotlin/org/move/lang/core/resolve/MatchingProcessor.kt b/src/main/kotlin/org/move/lang/core/resolve/MatchingProcessor.kt index d2c66b0a0..81809852a 100644 --- a/src/main/kotlin/org/move/lang/core/resolve/MatchingProcessor.kt +++ b/src/main/kotlin/org/move/lang/core/resolve/MatchingProcessor.kt @@ -1,6 +1,7 @@ package org.move.lang.core.resolve import org.move.lang.core.psi.MvNamedElement +import org.move.lang.core.psi.ext.isMsl data class SimpleScopeEntry( val name: String, @@ -11,7 +12,9 @@ fun interface MatchingProcessor { fun match(entry: SimpleScopeEntry): Boolean fun match(itemVis: ItemVis, element: T): Boolean { + if (element.isMsl() && !itemVis.isMsl) return false if (!element.isVisibleInScope(itemVis.itemScope)) return false + val name = element.name ?: return false val entry = SimpleScopeEntry(name, element) return match(entry) diff --git a/src/test/kotlin/org/move/lang/resolve/ResolveSpecsTest.kt b/src/test/kotlin/org/move/lang/resolve/ResolveSpecsTest.kt index 2b0a103a5..cf25bf9e8 100644 --- a/src/test/kotlin/org/move/lang/resolve/ResolveSpecsTest.kt +++ b/src/test/kotlin/org/move/lang/resolve/ResolveSpecsTest.kt @@ -512,4 +512,46 @@ class ResolveSpecsTest: ResolveTestCase() { } } """) + + fun `test spec functions not available in main code`() = checkByCode(""" + module 0x1::main { + fun call() { + spec_add(); + //^ unresolved + } + } + spec 0x1::main { + spec fun spec_add(): u8 { 1 } + } + """) + + fun `test spec functions are available in spec code`() = checkByCode(""" + module 0x1::main { + fun call() { + } + spec call { + spec_add(); + //^ + } + } + spec 0x1::main { + spec fun spec_add(): u8 { 1 } + //X + } + """) + + fun `test spec functions are available in spec module code`() = checkByCode(""" + module 0x1::main { + fun call() { + } + } + spec 0x1::main { + spec fun spec_add(): u8 { 1 } + //X + spec call { + spec_add(); + //^ + } + } + """) }