Skip to content

Commit bf7ffe0

Browse files
committed
Fix #388
1 parent 69c9ffd commit bf7ffe0

File tree

3 files changed

+95
-13
lines changed

3 files changed

+95
-13
lines changed

src/main/kotlin/org/arend/inspection/UnresolvedArendPatternInspection.kt

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,69 @@ package org.arend.inspection
33
import com.intellij.codeInspection.ProblemsHolder
44
import com.intellij.psi.PsiElement
55
import com.intellij.psi.PsiElementVisitor
6+
import com.intellij.psi.stubs.StubIndex
7+
import com.intellij.psi.util.childrenOfType
8+
import org.arend.psi.ArendFile
9+
import org.arend.psi.ArendFileScope
10+
import org.arend.psi.ancestor
611
import org.arend.psi.ext.*
12+
import org.arend.psi.stubs.index.ArendDefinitionIndex
13+
import org.arend.refactoring.isPrelude
14+
import org.arend.term.abs.Abstract
15+
import org.arend.term.group.Group
716
import org.arend.util.ArendBundle
817

918
class UnresolvedArendPatternInspection : ArendInspectionBase() {
1019
override fun buildArendVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
1120
return object : PsiElementVisitor() {
21+
22+
fun registerProblem(element: PsiElement) {
23+
val message = ArendBundle.message("arend.inspection.unresolved.pattern", element.text)
24+
holder.registerProblem(element, message)
25+
}
26+
1227
override fun visitElement(element: PsiElement) {
1328
super.visitElement(element)
14-
if (element is ArendPattern && element.parent !is ArendPattern) {
15-
val parent = element.parent
16-
if ((parent is ArendClause && parent.patterns.size > 1) || parent.parent is ArendFunctionClauses ||
17-
(parent.parent is ArendDataBody && (parent.parent as ArendDataBody).elim != null)) {
18-
return
19-
}
20-
val resolve = element.singleReferable?.reference?.resolve() ?: return
21-
if (resolve !is ArendConstructor && resolve !is ArendDefInstance) {
22-
val message = ArendBundle.message("arend.inspection.unresolved.pattern", element.text)
23-
holder.registerProblem(element, message)
29+
if (element !is ArendPattern) {
30+
return
31+
}
32+
33+
val identifier = element.singleReferable ?: return
34+
val name = identifier.refName
35+
val project = element.project
36+
val constructors = StubIndex.getElements(ArendDefinitionIndex.KEY, name, project, ArendFileScope(project), PsiReferable::class.java).filterIsInstance<ArendConstructor>()
37+
val resolve = identifier.reference?.resolve() ?: return
38+
39+
if (constructors.isNotEmpty() && (!constructors.contains(resolve) &&
40+
(resolve.containingFile as? ArendFile?)?.let { isPrelude(it) } == false)) {
41+
val group = (getTypeOfPattern(element) as? ArendLiteral?)?.longName?.resolve as? Group?
42+
val groupConstructors = group?.constructors ?: emptyList()
43+
if (groupConstructors.any { constructors.contains(it) }) {
44+
registerProblem(element)
2445
}
2546
}
2647
}
48+
49+
private fun getTypeOfPattern(pattern: ArendPattern): PsiElement? {
50+
val patterns = pattern.parent?.childrenOfType<ArendPattern>()
51+
val firstPattern = patterns?.first()
52+
val firstPatternResolve = firstPattern?.singleReferable?.reference?.resolve()
53+
val index = patterns?.indexOf(pattern) ?: -1
54+
return if (firstPatternResolve is Abstract.ParametersHolder) {
55+
val parameter = firstPatternResolve.parameters[index - 1]
56+
parameter?.type as? PsiElement
57+
} else if (pattern.parent is ArendPattern) {
58+
val parentGroup = getTypeOfPattern(pattern.parent as ArendPattern) as? Abstract.ParametersHolder?
59+
parentGroup?.parameters?.get(index)?.type as? PsiElement?
60+
} else if (pattern.ancestor<ArendCaseExpr>() != null) {
61+
val caseArg = pattern.ancestor<ArendCaseExpr>()?.caseArguments?.get(index)
62+
val resolve = (caseArg?.expression as? ArendNewExpr?)?.argumentAppExpr?.atomFieldsAcc?.atom?.literal?.longName?.resolve
63+
?: caseArg?.eliminatedReference?.resolve
64+
(resolve?.ancestor<ArendNameTele>()?.type as? ArendNewExpr?)?.argumentAppExpr?.atomFieldsAcc?.atom?.literal
65+
} else {
66+
null
67+
}
68+
}
2769
}
2870
}
2971
}

src/main/kotlin/org/arend/psi/ArendFileScope.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import com.intellij.openapi.project.Project
44
import com.intellij.openapi.vfs.VirtualFile
55
import com.intellij.psi.PsiManager
66
import com.intellij.psi.search.ProjectAndLibrariesScope
7+
import org.arend.prelude.Prelude
78

89
class ArendFileScope(project: Project): ProjectAndLibrariesScope(project) {
910
override fun contains(file: VirtualFile): Boolean {
10-
if (!super.contains(file)) return false
1111
val project = project ?: return false
12-
val psiFile = PsiManager.getInstance(project).findFile(file)
13-
return psiFile is ArendFile && psiFile.moduleLocation != null
12+
val psiFile = PsiManager.getInstance(project).findFile(file) as? ArendFile ?: return false
13+
if (psiFile.libraryName == Prelude.LIBRARY_NAME) {
14+
return true
15+
}
16+
if (!super.contains(file)) return false
17+
return psiFile.moduleLocation != null
1418
}
1519
}

src/test/kotlin/org/arend/inspection/UnresolvedArendPatternInspectionTest.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,42 @@ class UnresolvedArendPatternInspectionTest : QuickFixTestBase() {
2424
}
2525
""")
2626

27+
fun testBoolBar() = doWarningsCheck(myFixture, """
28+
-- ! Bool.ard
29+
\import Data.Bool(Bool, if)
30+
31+
\data Bool | false | true
32+
33+
-- ! Main.ard
34+
\import Bool(Bool)
35+
36+
\data Foo
37+
| cons Bool Bool
38+
39+
\func bar (b : Foo) : Nat => \case b \with {
40+
| cons ${uapWarning("false")} ${uapWarning("true")} => 1
41+
| cons ${uapWarning("true")} ${uapWarning("false")} => 0
42+
}
43+
""")
44+
45+
fun testBoolSigma() = doWarningsCheck(myFixture, """
46+
-- ! Bool.ard
47+
\import Data.Bool(Bool, if)
48+
49+
\data Bool | false | true
50+
51+
-- ! Main.ard
52+
\import Bool(Bool)
53+
54+
\data Foo
55+
| cons (\Sigma Bool Bool)
56+
57+
\func bar (b : Foo) : Nat => \case b \with {
58+
| cons (f, ${uapWarning("true")}) => 1
59+
| cons (t, ${uapWarning("false")}) => 0
60+
}
61+
""")
62+
2763
companion object {
2864
fun uapWarning(text: String) = "<warning descr=\"${ArendBundle.message("arend.inspection.unresolved.pattern", text)}\" textAttributesKey=\"WARNING_ATTRIBUTES\">$text</warning>"
2965
}

0 commit comments

Comments
 (0)