@@ -3,27 +3,69 @@ package org.arend.inspection
33import com.intellij.codeInspection.ProblemsHolder
44import com.intellij.psi.PsiElement
55import 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
611import 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
716import org.arend.util.ArendBundle
817
918class 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}
0 commit comments