in psi/src/com/intellij/r/psi/classes/s4/RS4TypeResolver.kt [25:98]
fun resolveS4TypeClass(element: RPsiElement): List<String> {
return when (element) {
is RNumericLiteralExpression, is RBoundaryLiteral -> NUMERIC
is RStringLiteralExpression -> CHARACTER
is RNullLiteral -> NULL
is RNaLiteral -> when (element.elementType) {
RElementTypes.R_NA -> LOGICAL
RElementTypes.R_NA_CHARACTER_ -> CHARACTER
RElementTypes.R_NA_COMPLEX_ -> COMPLEX
RElementTypes.R_NA_INTEGER_ -> INTEGER
RElementTypes.R_NA_REAL_ -> NUMERIC
else -> emptyList()
}
is RFunctionExpression -> FUNCTION
is RAssignmentStatement -> element.assignedValue?.let { resolveS4TypeClass(it) }
is RParameter -> {
val fn = PsiTreeUtil.getParentOfType(element, RFunctionExpression::class.java) ?: return emptyList()
val context = RS4ContextProvider.getS4Context(fn, RS4SetMethodDefinitionContext::class) ?: return emptyList()
val params = context.functionCall.associatedS4MethodInfo?.getParameters(RSearchScopeUtil.getScope(element))
params?.firstOrNull { it.name == element.name }?.type?.let { listOf(it) }
}
is RIdentifierExpression -> {
val newSlotContext = RS4ContextProvider.getS4Context(element, RS4NewObjectSlotNameContext::class)
if (newSlotContext != null) {
RS4ClassInfoUtil.getAssociatedClassName(newSlotContext.functionCall)?.let { listOf(it) }
}
else element.reference.multiResolve(false).flatMap {
(it.element as? RPsiElement)?.let { it1 -> resolveS4TypeClass(it1) } ?: emptyList()
}
}
is RAtExpression -> {
val ownerIdentifier = element.rightExpr as? RIdentifierExpression ?: return emptyList()
ownerIdentifier.reference.multiResolve(false).mapNotNull { resolveResult ->
when (val resolveElement = resolveResult.element) {
is RNamedArgument -> resolveElement.assignedValue?.name
is PomTargetPsiElement -> {
when (val target = resolveElement.target) {
is RSkeletonS4SlotPomTarget -> target.setClass.stub.s4ClassInfo.slots.firstOrNull { it.name == target.name }?.type
is RS4ComplexSlotPomTarget -> target.slot.type
is RStringLiteralPomTarget -> "ANY"
else -> null
}
}
else -> null
}
}
}
is RCallExpression -> when {
element.isFunctionFromLibrarySoft("new", "methods") -> {
val className = RS4ClassInfoUtil.getAssociatedClassName(element) ?: return emptyList()
listOf(className)
}
element.isFunctionFromLibrarySoft("list", "base") -> LIST
element.isFunctionFromLibrarySoft("c", "base") ->
element.argumentList.expressionList.asSequence().map { resolveS4TypeClass(it) }.filter { it.isNotEmpty() }.firstOrNull()
element.isFunctionFromLibrarySoft("data.frame", "base") -> DATA_FRAME
element.isFunctionFromLibrarySoft("tibble", "tibble") -> TBL
element.isFunctionFromLibrarySoft("data.table", "data.table") -> DATA_TABLE
else -> null
}
is ROperatorExpression -> when(element.operator) {
is RCompareOperator, is ROrOperator, is RAndOperator, is RNotOperator -> LOGICAL
is RPlusminusOperator, is RMuldivOperator, is RExpOperator -> {
val leftType by lazy { element.leftExpr?.let { resolveS4TypeClass(it) } ?: NUMERIC }
val rightType by lazy { element.rightExpr?.let { resolveS4TypeClass(it) } ?: NUMERIC }
val unaryType by lazy { element.expr?.let { resolveS4TypeClass(it) } ?: NUMERIC }
if (leftType == NUMERIC && rightType == NUMERIC && unaryType == NUMERIC) NUMERIC
else null
}
else -> null
}
else -> null
} ?: return emptyList()
}