PSI Pattern Matching: Add support of weak matching
This commit is contained in:
@@ -53,7 +53,6 @@ import org.jetbrains.jet.lang.psi.JetLabelReferenceExpression
|
|||||||
import org.jetbrains.jet.lang.resolve.calls.callUtil.getCall
|
import org.jetbrains.jet.lang.resolve.calls.callUtil.getCall
|
||||||
import org.jetbrains.jet.lang.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.jet.lang.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclaration
|
import org.jetbrains.jet.lang.psi.JetDeclaration
|
||||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
|
|
||||||
import org.jetbrains.jet.lang.types.ErrorUtils
|
import org.jetbrains.jet.lang.types.ErrorUtils
|
||||||
import com.intellij.lang.ASTNode
|
import com.intellij.lang.ASTNode
|
||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
@@ -63,38 +62,30 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver
|
|||||||
import org.jetbrains.jet.lang.psi.JetThisExpression
|
import org.jetbrains.jet.lang.psi.JetThisExpression
|
||||||
import org.jetbrains.jet.lang.psi.JetStringTemplateEntryWithExpression
|
import org.jetbrains.jet.lang.psi.JetStringTemplateEntryWithExpression
|
||||||
import org.jetbrains.jet.plugin.util.psi.patternMatching.JetPsiRange.Empty
|
import org.jetbrains.jet.plugin.util.psi.patternMatching.JetPsiRange.Empty
|
||||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral
|
|
||||||
import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor
|
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.jet.lang.psi.JetMultiDeclaration
|
import org.jetbrains.jet.lang.psi.JetMultiDeclaration
|
||||||
import org.jetbrains.jet.lang.psi.JetFunction
|
import org.jetbrains.jet.lang.psi.JetFunction
|
||||||
import org.jetbrains.jet.lang.psi.JetClassBody
|
import org.jetbrains.jet.lang.psi.JetClassBody
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
|
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
|
||||||
import org.jetbrains.jet.lang.psi.JetProperty
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor
|
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor
|
||||||
import org.jetbrains.jet.lang.psi.JetWithExpressionInitializer
|
import org.jetbrains.jet.lang.psi.JetWithExpressionInitializer
|
||||||
import org.jetbrains.jet.lang.psi.JetPropertyAccessor
|
|
||||||
import org.jetbrains.jet.lang.psi.JetMultiDeclarationEntry
|
|
||||||
import org.jetbrains.jet.lang.psi.JetParameter
|
import org.jetbrains.jet.lang.psi.JetParameter
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
||||||
import org.jetbrains.jet.lang.psi.JetCallableDeclaration
|
import org.jetbrains.jet.lang.psi.JetCallableDeclaration
|
||||||
import org.jetbrains.jet.lang.psi.JetClassObject
|
import org.jetbrains.jet.lang.psi.JetClassObject
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassKind
|
|
||||||
import org.jetbrains.jet.lang.psi.JetTypeParameter
|
import org.jetbrains.jet.lang.psi.JetTypeParameter
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.jet.lang.types.fqName
|
|
||||||
import org.jetbrains.jet.renderer.DescriptorRenderer
|
import org.jetbrains.jet.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil
|
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
|
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.jet.lang.psi.JetClass
|
import org.jetbrains.jet.lang.psi.JetClass
|
||||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.jet.lang.psi.JetFile
|
import org.jetbrains.jet.lang.psi.JetFile
|
||||||
import org.jetbrains.jet.lang.psi.JetClassInitializer
|
import org.jetbrains.jet.lang.psi.JetClassInitializer
|
||||||
import java.util.ArrayList
|
|
||||||
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner
|
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner
|
||||||
import org.jetbrains.jet.lang.psi.doNotAnalyze
|
import org.jetbrains.jet.lang.psi.doNotAnalyze
|
||||||
|
import org.jetbrains.jet.lang.psi.JetReturnExpression
|
||||||
|
import org.jetbrains.jet.lang.psi.JetProperty
|
||||||
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperClass
|
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperClass
|
||||||
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier
|
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier
|
||||||
|
|
||||||
@@ -115,10 +106,18 @@ public trait UnificationResult {
|
|||||||
override val status: Status get() = UNMATCHED
|
override val status: Status get() = UNMATCHED
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Matched(val substitution: Map<UnifierParameter, JetExpression>): UnificationResult {
|
trait Matched: UnificationResult {
|
||||||
|
val substitution: Map<UnifierParameter, JetExpression>
|
||||||
override val status: Status get() = MATCHED
|
override val status: Status get() = MATCHED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class StronglyMatched(override val substitution: Map<UnifierParameter, JetExpression>): Matched
|
||||||
|
|
||||||
|
class WeaklyMatched(
|
||||||
|
override val substitution: Map<UnifierParameter, JetExpression>,
|
||||||
|
val weakMatches: Map<JetElement, JetElement>
|
||||||
|
): Matched
|
||||||
|
|
||||||
val status: Status
|
val status: Status
|
||||||
val matched: Boolean get() = status != UNMATCHED
|
val matched: Boolean get() = status != UNMATCHED
|
||||||
}
|
}
|
||||||
@@ -129,7 +128,8 @@ public class UnifierParameter(
|
|||||||
)
|
)
|
||||||
|
|
||||||
public class JetPsiUnifier(
|
public class JetPsiUnifier(
|
||||||
parameters: Collection<UnifierParameter> = Collections.emptySet()
|
parameters: Collection<UnifierParameter> = Collections.emptySet(),
|
||||||
|
val allowWeakMatches: Boolean = false
|
||||||
) {
|
) {
|
||||||
class object {
|
class object {
|
||||||
val DEFAULT = JetPsiUnifier()
|
val DEFAULT = JetPsiUnifier()
|
||||||
@@ -141,6 +141,7 @@ public class JetPsiUnifier(
|
|||||||
) {
|
) {
|
||||||
val substitution = HashMap<UnifierParameter, JetExpression>()
|
val substitution = HashMap<UnifierParameter, JetExpression>()
|
||||||
val declarationPatternsToTargets = MultiMap<DeclarationDescriptor, DeclarationDescriptor>()
|
val declarationPatternsToTargets = MultiMap<DeclarationDescriptor, DeclarationDescriptor>()
|
||||||
|
val weakMatches = HashMap<JetElement, JetElement>()
|
||||||
var checkEquivalence: Boolean = false
|
var checkEquivalence: Boolean = false
|
||||||
|
|
||||||
private fun matchDescriptors(d1: DeclarationDescriptor?, d2: DeclarationDescriptor?): Boolean {
|
private fun matchDescriptors(d1: DeclarationDescriptor?, d2: DeclarationDescriptor?): Boolean {
|
||||||
@@ -720,6 +721,35 @@ public class JetPsiUnifier(
|
|||||||
private fun ASTNode.getChildrenRange(): JetPsiRange =
|
private fun ASTNode.getChildrenRange(): JetPsiRange =
|
||||||
getChildren(null).map { it.getPsi() }.filterNotNull().toRange()
|
getChildren(null).map { it.getPsi() }.filterNotNull().toRange()
|
||||||
|
|
||||||
|
private fun PsiElement.unwrapWeakly(): JetElement? {
|
||||||
|
return when {
|
||||||
|
this is JetReturnExpression -> getReturnedExpression()
|
||||||
|
this is JetProperty -> getInitializer()
|
||||||
|
JetPsiUtil.isOrdinaryAssignment(this) -> (this as JetBinaryExpression).getRight()
|
||||||
|
this is JetExpression && this !is JetDeclaration -> this
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doUnifyWeakly(
|
||||||
|
targetElement: JetElement,
|
||||||
|
patternElement: JetElement
|
||||||
|
): Status {
|
||||||
|
if (!allowWeakMatches) return UNMATCHED
|
||||||
|
|
||||||
|
val targetElementUnwrapped = targetElement.unwrapWeakly()
|
||||||
|
val patternElementUnwrapped = patternElement.unwrapWeakly()
|
||||||
|
if (targetElementUnwrapped == null || patternElementUnwrapped == null) return UNMATCHED
|
||||||
|
if (targetElementUnwrapped == targetElement && patternElementUnwrapped == patternElement) return UNMATCHED
|
||||||
|
|
||||||
|
val status = doUnify(targetElementUnwrapped, patternElementUnwrapped)
|
||||||
|
if (status == MATCHED && allowWeakMatches) {
|
||||||
|
weakMatches[patternElement] = targetElement
|
||||||
|
}
|
||||||
|
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
fun doUnify(
|
fun doUnify(
|
||||||
targetElement: PsiElement?,
|
targetElement: PsiElement?,
|
||||||
patternElement: PsiElement?
|
patternElement: PsiElement?
|
||||||
@@ -761,10 +791,17 @@ public class JetPsiUnifier(
|
|||||||
if (targetNode == null || patternNode == null) return UNMATCHED
|
if (targetNode == null || patternNode == null) return UNMATCHED
|
||||||
|
|
||||||
val resolvedStatus = matchResolvedInfo(targetElementUnwrapped, patternElementUnwrapped)
|
val resolvedStatus = matchResolvedInfo(targetElementUnwrapped, patternElementUnwrapped)
|
||||||
if (resolvedStatus != null) return resolvedStatus
|
if (resolvedStatus == MATCHED) return resolvedStatus
|
||||||
|
|
||||||
|
if (targetElementUnwrapped is JetElement && patternElementUnwrapped is JetElement) {
|
||||||
|
val weakStatus = doUnifyWeakly(targetElementUnwrapped, patternElementUnwrapped)
|
||||||
|
if (weakStatus != UNMATCHED) return weakStatus
|
||||||
|
}
|
||||||
|
|
||||||
if (targetNode.getElementType() != patternNode.getElementType()) return UNMATCHED
|
if (targetNode.getElementType() != patternNode.getElementType()) return UNMATCHED
|
||||||
|
|
||||||
|
if (resolvedStatus != null) return resolvedStatus
|
||||||
|
|
||||||
val targetChildren = targetNode.getChildrenRange()
|
val targetChildren = targetNode.getChildrenRange()
|
||||||
val patternChildren = patternNode.getChildrenRange()
|
val patternChildren = patternNode.getChildrenRange()
|
||||||
|
|
||||||
@@ -798,7 +835,7 @@ public class JetPsiUnifier(
|
|||||||
substitution.size != descriptorToParameter.size ->
|
substitution.size != descriptorToParameter.size ->
|
||||||
Unmatched
|
Unmatched
|
||||||
status == MATCHED ->
|
status == MATCHED ->
|
||||||
Matched(substitution)
|
if (weakMatches.isEmpty()) StronglyMatched(substitution) else WeaklyMatched(substitution, weakMatches)
|
||||||
else ->
|
else ->
|
||||||
Unmatched
|
Unmatched
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user