Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
i582 committed Jun 7, 2022
1 parent 897f64d commit ce65366
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ExPhpTypeCallable(val argTypes: List<ExPhpType>, val returnType: ExPhpType
is ExPhpTypeAny -> true
// TODO: добавить полноценную проверку?
is ExPhpTypeCallable -> true
is ExPhpTypePrimitive -> rhs == ExPhpType.CALLABLE
is ExPhpTypePrimitive -> rhs == ExPhpType.CALLABLE || rhs == ExPhpType.STRING
is ExPhpTypeNullable -> isAssignableFrom(rhs.inner, project)
else -> false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ExPhpTypePrimitive(val typeStr: String) : ExPhpType {
is ExPhpTypeInstance -> this === ExPhpType.OBJECT
is ExPhpTypeForcing -> isAssignableFrom(rhs.inner, project)
is ExPhpTypeClassString -> this === ExPhpType.STRING
is ExPhpTypeCallable -> this === ExPhpType.CALLABLE
is ExPhpTypeCallable -> this === ExPhpType.CALLABLE || this === ExPhpType.STRING
else -> false
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ object PhpTypeToExPhpTypeParsing {
return eq
}

fun advance(): Boolean {
skipWhitespace()
if (offset >= type.length) {
return false
}
offset++
return true
}

fun parseFQN(): String? {
skipWhitespace()
val cur = if (offset < type.length) type[offset] else '\b'
Expand Down Expand Up @@ -303,8 +312,13 @@ object PhpTypeToExPhpTypeParsing {
// вернуть для него всегда просто \int, а не \int<0, 100>
// Если использовать не typesWithParametrisedParts, а types
// то это не нужно, но тогда не будет работать вывод типов callable.
if (fqn == "\\int")
if (fqn == "\\int" && builder.compare('<')) {
for (i in 0..20) {
if (builder.compareAndEat('>')) break
builder.advance()
}
return FQN_PREPARSED[fqn]
}

if (fqn == "tuple" && builder.compare('(')) {
val items = parseTupleContents(builder) ?: return null
Expand Down
23 changes: 17 additions & 6 deletions src/main/kotlin/com/vk/kphpstorm/generics/GenericsReifier.kt
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,18 @@ class GenericsReifier(val project: Project) {
private fun reifyArgumentGenericsT(argExType: ExPhpType, paramExType: ExPhpType) {
if (paramExType is ExPhpTypeGenericsT) {
val prevReifiedType = implicitSpecializationNameMap[paramExType.nameT]
if (prevReifiedType != null && prevReifiedType.toString() != argExType.toString()) {
// Особые случаи, когда несколько типов это не ошибка
val isAny = argExType == ExPhpType.ANY || prevReifiedType == ExPhpType.ANY
val isNull = argExType == ExPhpType.NULL || prevReifiedType == ExPhpType.NULL
if (prevReifiedType != null && !isAny && !isNull && prevReifiedType.toString() != argExType.toString()) {
// В таком случае мы получаем ситуацию когда один шаблонный тип
// имеет несколько возможных вариантов типа, что является ошибкой.
implicitSpecializationErrors[paramExType.nameT] = Pair(argExType, prevReifiedType)
}

implicitSpecializationNameMap[paramExType.nameT] = argExType
if (prevReifiedType == null || argExType != ExPhpType.ANY && argExType != ExPhpType.NULL) {
implicitSpecializationNameMap[paramExType.nameT] = argExType
}
}

if (paramExType is ExPhpTypeNullable) {
Expand All @@ -116,14 +121,20 @@ class GenericsReifier(val project: Project) {
if (paramExType is ExPhpTypePipe) {
// если случай paramExType это Vector|Vector<%T> и argExType это Vector|Vector<A>
val instantiationParamType =
paramExType.items.find { it is ExPhpTypeTplInstantiation } as ExPhpTypeTplInstantiation?
if (instantiationParamType != null && argExType is ExPhpTypeTplInstantiation) {
paramExType.items.find { it is ExPhpTypeTplInstantiation } as? ExPhpTypeTplInstantiation
val instantiationArgType =
if (argExType is ExPhpTypePipe)
argExType.items.find { it is ExPhpTypeTplInstantiation } as? ExPhpTypeTplInstantiation
else
argExType as? ExPhpTypeTplInstantiation

if (instantiationParamType != null && instantiationArgType != null) {
for (i in 0 until min(
argExType.specializationList.size,
instantiationArgType.specializationList.size,
instantiationParamType.specializationList.size
)) {
reifyArgumentGenericsT(
argExType.specializationList[i],
instantiationArgType.specializationList[i],
instantiationParamType.specializationList[i]
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ class IndexingGenericFunctionCall(
if (it.typesWithParametrisedParts.firstOrNull()?.startsWith("\\Closure<") == true) {
val rawType = it.typesWithParametrisedParts.first()
val parts = PhpType.getParametrizedParts(rawType).map { type -> type.replace("", "/") }
.map {type ->
if (type.startsWith("\\int<") && type.endsWith("int")) {
"int"
} else {
type
}
}

val returnType = parts.last()
val paramTypes = parts.dropLast(1).map { type -> type.ifEmpty { "mixed" } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@ function takeTypedCallable($a) {
return $a;
}

$b = takeCallable(function() {});
$b = takeTypedCallable(function() {});
expr_type($b, "callable");

$b = takeTypedCallable("");
expr_type($b, "string");
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,38 @@ class GenericsGeneralTest : GenericTestBase() {
fun testGenericInGeneric() {
runFixture("generics/general/generic_in_generic.fixture.php")
}

fun testFromKphp() {
val classes = arrayOf(
"generics/kphp/Classes/A.php",
"generics/kphp/Classes/B.php",
"generics/kphp/Classes/TemplateMagic.php",
"generics/kphp/Classes/TemplateMagicStatic.php",
)

runFixture(
"generics/kphp/016_kphp_param_depends_T.php",
*classes,
)

runFixture(
"generics/kphp/017_templates_primitives.php",
*classes,
)

runFixture(
"generics/kphp/018_classof_keyword.php",
*classes,
)

runFixture(
"generics/kphp/016_kphp_param_depends_T.php",
*classes,
)

runFixture(
"generics/kphp/016_kphp_param_depends_T.php",
*classes,
)
}
}

0 comments on commit ce65366

Please sign in to comment.