Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
- fixed callable and string type compatibility
- fixed support for new 2022.2 int<X,Y> type
- fixed cases with any
- added KPHP tests
  • Loading branch information
i582 committed Jun 7, 2022
1 parent 897f64d commit 02dc6a7
Show file tree
Hide file tree
Showing 19 changed files with 1,238 additions and 12 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ intellij {
type = 'IU'
// for release versions: https://www.jetbrains.com/intellij-repository/releases (com.jetbrains.intellij.idea)
// for EAPs: https://www.jetbrains.com/intellij-repository/snapshots
version = '222.2680-EAP-CANDIDATE-SNAPSHOT'
version = '222.2889-EAP-CANDIDATE-SNAPSHOT'
// version = '2022.1.1'
// version = '2021.3.1'
plugins = [
'com.jetbrains.php:222.2680.8', // https://plugins.jetbrains.com/plugin/6610-php/versions
'com.jetbrains.php:222.2889.14', // https://plugins.jetbrains.com/plugin/6610-php/versions
// 'com.jetbrains.php:221.5591.58',
// 'com.jetbrains.php:213.5744.223'
]
Expand Down
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");
Loading

0 comments on commit 02dc6a7

Please sign in to comment.