/
TypeResolver.kt
79 lines (67 loc) · 2.57 KB
/
TypeResolver.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package app.cash.sqldelight.dialect.api
import com.alecstrong.sql.psi.core.psi.SqlExpr
import com.alecstrong.sql.psi.core.psi.SqlFunctionExpr
import com.alecstrong.sql.psi.core.psi.SqlStmt
import com.alecstrong.sql.psi.core.psi.SqlTypeName
import com.intellij.psi.PsiElement
interface TypeResolver {
/**
* @param expr The expression to be resolved to a type.
* @return The type for [expr] for null if this resolver cannot solve.
*/
fun resolvedType(expr: SqlExpr): IntermediateType
/**
* In the context of [parent], @return the type [argument] (which is a child expression) should have.
*/
fun argumentType(parent: PsiElement, argument: SqlExpr): IntermediateType
/**
* Resolves the type of dialect specific functions
*/
fun functionType(functionExpr: SqlFunctionExpr): IntermediateType?
/**
* @return the dialect specific (or [PrimitiveType]) for a type name.
*/
fun definitionType(typeName: SqlTypeName): IntermediateType
/**
* Enables a dialect to simplify a pure SQLDelight Intermediate Type into something the
* dialect can deal with natively. (ie Integer AS Boolean in SQLite can be handled without an
* adapter).
*/
fun simplifyType(intermediateType: IntermediateType): IntermediateType = intermediateType
fun queryWithResults(sqlStmt: SqlStmt): QueryWithResults?
}
/**
* @return the type from the expr list which is the highest order in the typeOrder list
*/
fun TypeResolver.encapsulatingType(
exprList: List<SqlExpr>,
vararg typeOrder: DialectType,
) = encapsulatingType(exprList = exprList, nullableIfAny = false, typeOrder = typeOrder)
/**
* @return the type from the expr list which is the highest order in the typeOrder list
*/
fun TypeResolver.encapsulatingType(
exprList: List<SqlExpr>,
nullableIfAny: Boolean,
vararg typeOrder: DialectType,
): IntermediateType {
val types = exprList.map { resolvedType(it) }
val sqlTypes = types.map { it.dialectType }
if (PrimitiveType.ARGUMENT in sqlTypes) {
if (typeOrder.size == 1) {
return IntermediateType(typeOrder.single())
}
val otherFunctionParameters = sqlTypes.distinct() - PrimitiveType.ARGUMENT
if (otherFunctionParameters.size == 1) {
return IntermediateType(otherFunctionParameters.single())
}
error("The Kotlin type of the argument cannot be inferred, use CAST instead.")
}
val type = typeOrder.last { it in sqlTypes }
if (!nullableIfAny && types.all { it.javaType.isNullable } ||
nullableIfAny && types.any { it.javaType.isNullable }
) {
return IntermediateType(type).asNullable()
}
return IntermediateType(type)
}