Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: added support for generics #5

Open
wants to merge 61 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
c01af26
initial implementation
i582 Mar 14, 2022
d373f2f
fixed situation when it was necessary to resolve a function during ty…
i582 Mar 14, 2022
1d35cff
added initial support for class generics
i582 Mar 15, 2022
df53c16
fixed type inference for shape with unresolved types
i582 Mar 15, 2022
19943d0
fixed type inference for non-template classes
i582 Mar 15, 2022
015d276
fixed NullPointerException when generic comment contains syntacticall…
i582 Mar 15, 2022
ebfa25c
added class TypeTestBase for type testing and added several tests for…
i582 Mar 15, 2022
3c0674a
fixed class-string comparison with other types
i582 Mar 15, 2022
6b749b7
added more tests
i582 Mar 15, 2022
f8220bc
wip
i582 Mar 27, 2022
26102d0
fixed tests
i582 Mar 27, 2022
87ce1f2
extended generic inspections for method and constructor calls and add…
i582 Mar 27, 2022
62b1369
added initial support for generic types bounds
i582 Mar 28, 2022
afa6442
removed old generic type provider
i582 Mar 28, 2022
9c274bc
added Map and Pair generic classes
i582 Mar 28, 2022
a248737
update
i582 Apr 22, 2022
cba4ab1
implementation of generics instantiation is redesigned through the in…
i582 May 23, 2022
48f300a
fixed tests
i582 May 23, 2022
afc47aa
update (wip)
i582 May 26, 2022
6887870
added initial support for default generic types
i582 May 26, 2022
c2b5be2
added AddExplicitInstantiationComment quick fix
i582 May 27, 2022
dec32ed
added support for static methods
i582 May 27, 2022
96c502f
reworked complex type resolution system, now all tests are green
i582 May 28, 2022
829cd14
added optimisation for non-generic symbols
i582 May 28, 2022
18b65d5
added more tests
i582 May 28, 2022
7c12652
added checks for generic type duplication with class types and added …
i582 May 28, 2022
b746f71
fixed bug with class-string
i582 May 28, 2022
8c9feab
added type inference for parameters when they have a generic type tha…
i582 May 28, 2022
c1140f7
wip
i582 May 29, 2022
707a475
update
i582 May 29, 2022
1dc21d7
added support for generic name in generic isntantiation list
i582 May 29, 2022
43a2bb5
refactor
i582 May 30, 2022
f78a639
refactor
i582 May 30, 2022
969e0f7
small refactor
i582 May 30, 2022
8511964
dropped kphp-template-class support
i582 May 30, 2022
b806f49
Merge branch 'master' into pmakhnev/generic
i582 May 30, 2022
2f846c8
added fields tests
i582 May 30, 2022
3d83f60
fixed @var tag
i582 May 30, 2022
96af2be
added tests for callback
i582 May 30, 2022
00d923a
now generic names in static fields are treated as a usual class inste…
i582 May 30, 2022
57f898a
small fix
i582 Jun 6, 2022
897f64d
update
i582 Jun 7, 2022
02dc6a7
update
i582 Jun 7, 2022
6fd074a
fixed stubs
i582 Jun 7, 2022
80500cf
small fixes
i582 Jun 7, 2022
77a4003
added type inference for a class methods parameters
i582 Jun 7, 2022
810956f
fixed type inference for tuples and shapes for simple cases
i582 Jun 8, 2022
3e2195e
fixed check for union extends class
i582 Jun 8, 2022
4e7bac8
added type inference from extends/default types for fields
i582 Jun 8, 2022
37bc52c
added check for generic instantiation count in PHPDoc
i582 Jun 9, 2022
2820bba
added highlight for @kphp-generic parts
i582 Jun 9, 2022
5f203d3
small rename
i582 Jun 9, 2022
7b6f053
added initial support for @kphp-inherit tag
i582 Jun 9, 2022
363a80e
small fixes
i582 Jun 9, 2022
25a39b8
added more checks and tests
i582 Jun 10, 2022
f7b998d
added initial support for class inherit
i582 Jun 10, 2022
cbc91b1
refactored
i582 Jun 12, 2022
37d5b3a
added generics T names settings for color scheme
i582 Jun 12, 2022
d967da2
fixed several KPHP tests
i582 Jun 12, 2022
80330d1
improved test bases
i582 Jun 12, 2022
9da0627
added support for depth inheritance
i582 Jun 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
plugins {
id 'java'
id 'idea'
id 'org.jetbrains.intellij' version '1.5.3' // https://github.com/JetBrains/gradle-intellij-plugin
id 'org.jetbrains.kotlin.jvm' version '1.6.10' // https://plugins.gradle.org/plugin/org.jetbrains.kotlin.jvm
id 'org.jetbrains.intellij' version '1.6.0' // https://github.com/JetBrains/gradle-intellij-plugin
id 'org.jetbrains.kotlin.jvm' version "1.7.0-RC" // https://plugins.gradle.org/plugin/org.jetbrains.kotlin.jvm
}

group 'com.vk'
Expand All @@ -15,8 +15,12 @@ repositories {
url 'https://www.jetbrains.com/intellij-repository/snapshots'
}
}

dependencies {
testImplementation group: 'junit', name: 'junit', version: '4.13.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.8.2'
testCompileOnly 'junit:junit:4.13.2'
}

idea {
Expand All @@ -30,26 +34,45 @@ idea {
}
}

compileKotlin {
sourceCompatibility = 11
targetCompatibility = 11
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += '-Xjvm-default=all'
jvmTarget = '11'
}
}

wrapper {
gradleVersion = "7.4"
}

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 = '2022.1'
version = '222.2964-EAP-CANDIDATE-SNAPSHOT'
// version = '2022.1.1'
// version = '2021.3.1'
plugins = [
'com.jetbrains.php:221.5080.224', // https://plugins.jetbrains.com/plugin/6610-php/versions
'com.jetbrains.php:222.2964.55', // https://plugins.jetbrains.com/plugin/6610-php/versions
// 'com.jetbrains.php:221.5591.58',
// 'com.jetbrains.php:213.5744.223'
]
}
runIde {
ideDir.set(file("/Users/alexandr.kirsanov/Library/Application Support/JetBrains/Toolbox/apps/PhpStorm/ch-0/213.5744.279/PhpStorm.app/Contents"))
// ideDir.set(file("/Users/alexandr.kirsanov/Library/Application Support/JetBrains/Toolbox/apps/PhpStorm/ch-0/213.5744.279/PhpStorm.app/Contents"))
}

patchPluginXml {
// see https://github.com/JetBrains/gradle-intellij-plugin#patching-dsl
// <change-notes> is only for LATEST version and should be updated on every version bump
changeNotes = """
<ul>
<li>support ffi_scope and ffi_cdata in phpdoc</li>
<li>track calls to 'end()' and 'reset()', suggesting replacing them</li>
<li>adapt code for 2022.2</li>
</ul>
"""
}
Expand All @@ -65,6 +88,8 @@ sourceSets {
}
}
test {
useJUnitPlatform()

exclude 'com/vk/kphpstorm/testing/infrastructure/**'
include "**/*Test.class"
scanForTestClasses false
Expand Down
16 changes: 16 additions & 0 deletions src/main/kotlin/com/vk/kphpstorm/KphpStormASTFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.vk.kphpstorm

import com.intellij.lang.DefaultASTFactoryImpl
import com.intellij.psi.impl.source.tree.LeafElement
import com.intellij.psi.tree.IElementType
import com.vk.kphpstorm.generics.psi.GenericInstantiationPsiCommentImpl

class KphpStormASTFactory : DefaultASTFactoryImpl() {
override fun createComment(type: IElementType, text: CharSequence): LeafElement {
if (text.startsWith("/*<") && text.endsWith(">*/")) {
return GenericInstantiationPsiCommentImpl(type, text)
}

return super.createComment(type, text)
}
}
85 changes: 66 additions & 19 deletions src/main/kotlin/com/vk/kphpstorm/KphpStormParserDefinition.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
package com.vk.kphpstorm

import com.intellij.lang.ASTNode
import com.intellij.lang.injection.MultiHostInjector
import com.intellij.lang.injection.MultiHostRegistrar
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.source.tree.PsiCommentImpl
import com.intellij.psi.util.parentOfType
import com.jetbrains.php.lang.PhpLanguage
import com.jetbrains.php.lang.documentation.phpdoc.parser.tags.PhpDocTagParserRegistry
import com.jetbrains.php.lang.parser.PhpParserDefinition
import com.jetbrains.php.lang.parser.PhpPsiElementCreator
import com.jetbrains.php.lang.psi.PhpFile
import com.jetbrains.php.lang.psi.elements.Function
import com.jetbrains.php.lang.psi.elements.PhpClass
import com.jetbrains.php.lang.psi.elements.PhpUse
import com.vk.kphpstorm.exphptype.psi.*
import com.vk.kphpstorm.generics.GenericUtil.genericNames
import com.vk.kphpstorm.generics.psi.GenericInstantiationPsiCommentImpl
import com.vk.kphpstorm.kphptags.ALL_KPHPDOC_TAGS
import com.vk.kphpstorm.kphptags.psi.*

Expand All @@ -30,25 +42,28 @@ class KphpStormParserDefinition() : PhpParserDefinition() {
*/
override fun createElement(node: ASTNode): PsiElement {
return when (node.elementType) {
KphpDocElementTypes.kphpDocTagSimple -> KphpDocTagSimplePsiImpl(node)
KphpDocElementTypes.kphpDocTagTemplateClass -> KphpDocTagTemplateClassPsiImpl(node)
KphpDocTplParameterDeclPsiImpl.elementType -> KphpDocTplParameterDeclPsiImpl(node)
KphpDocElementTypes.kphpDocTagWarnPerformance -> KphpDocTagWarnPerformancePsiImpl(node)
KphpDocWarnPerformanceItemPsiImpl.elementType -> KphpDocWarnPerformanceItemPsiImpl(node)

ExPhpTypePrimitivePsiImpl.elementType -> ExPhpTypePrimitivePsiImpl(node)
ExPhpTypeInstancePsiImpl.elementType -> ExPhpTypeInstancePsiImpl(node)
ExPhpTypePipePsiImpl.elementType -> ExPhpTypePipePsiImpl(node)
ExPhpTypeAnyPsiImpl.elementType -> ExPhpTypeAnyPsiImpl(node)
ExPhpTypeArrayPsiImpl.elementType -> ExPhpTypeArrayPsiImpl(node)
ExPhpTypeTuplePsiImpl.elementType -> ExPhpTypeTuplePsiImpl(node)
ExPhpTypeShapePsiImpl.elementType -> ExPhpTypeShapePsiImpl(node)
ExPhpTypeNullablePsiImpl.elementType -> ExPhpTypeNullablePsiImpl(node)
ExPhpTypeTplInstantiationPsiImpl.elementType -> ExPhpTypeTplInstantiationPsiImpl(node)
ExPhpTypeCallablePsiImpl.elementType -> ExPhpTypeCallablePsiImpl(node)
ExPhpTypeForcingPsiImpl.elementType -> ExPhpTypeForcingPsiImpl(node)

else -> PhpPsiElementCreator.create(node)
KphpDocElementTypes.kphpDocTagSimple -> KphpDocTagSimplePsiImpl(node)
KphpDocElementTypes.kphpDocTagGeneric -> KphpDocTagGenericPsiImpl(node)
KphpDocGenericParameterDeclPsiImpl.elementType -> KphpDocGenericParameterDeclPsiImpl(node)
KphpDocInheritParameterDeclPsiImpl.elementType -> KphpDocInheritParameterDeclPsiImpl(node)
KphpDocElementTypes.kphpDocTagInherit -> KphpDocTagInheritPsiImpl(node)
KphpDocElementTypes.kphpDocTagWarnPerformance -> KphpDocTagWarnPerformancePsiImpl(node)
KphpDocWarnPerformanceItemPsiImpl.elementType -> KphpDocWarnPerformanceItemPsiImpl(node)

ExPhpTypePrimitivePsiImpl.elementType -> ExPhpTypePrimitivePsiImpl(node)
ExPhpTypeInstancePsiImpl.elementType -> ExPhpTypeInstancePsiImpl(node)
ExPhpTypePipePsiImpl.elementType -> ExPhpTypePipePsiImpl(node)
ExPhpTypeAnyPsiImpl.elementType -> ExPhpTypeAnyPsiImpl(node)
ExPhpTypeArrayPsiImpl.elementType -> ExPhpTypeArrayPsiImpl(node)
ExPhpTypeTuplePsiImpl.elementType -> ExPhpTypeTuplePsiImpl(node)
ExPhpTypeShapePsiImpl.elementType -> ExPhpTypeShapePsiImpl(node)
ExPhpTypeNullablePsiImpl.elementType -> ExPhpTypeNullablePsiImpl(node)
ExPhpTypeTplInstantiationPsiImpl.elementType -> ExPhpTypeTplInstantiationPsiImpl(node)
ExPhpTypeCallablePsiImpl.elementType -> ExPhpTypeCallablePsiImpl(node)
ExPhpTypeClassStringPsiImpl.elementType -> ExPhpTypeClassStringPsiImpl(node)
ExPhpTypeForcingPsiImpl.elementType -> ExPhpTypeForcingPsiImpl(node)

else -> PhpPsiElementCreator.create(node)
}
}
}
Expand All @@ -58,3 +73,35 @@ class KphpStormParserDefinition() : PhpParserDefinition() {
* This has no sense but correct plugin.xml validity while development
*/
class FakePhpLanguage : com.intellij.lang.Language("PHP")

class GenericsInstantiationInjector : MultiHostInjector {
override fun getLanguagesToInject(registrar: MultiHostRegistrar, context: PsiElement) {
if (context is GenericInstantiationPsiCommentImpl) {
val file = context.containingFile as? PhpFile ?: return

val namespace = file.mainNamespaceName?.trim('\\') ?: ""
val usesText = file.topLevelDefs.values().filterIsInstance<PhpUse>().joinToString("\n") { it.parent.text }

val parentFunctionGenericT = context.parentOfType<Function>()?.genericNames() ?: emptyList()
val parentClassGenericT = context.parentOfType<PhpClass>()?.genericNames() ?: emptyList()
val genericT = (parentFunctionGenericT + parentClassGenericT).joinToString(", ") { it.name }

val start = context.startOffset - context.textOffset
val range = TextRange(start + 3, start + context.textLength - 3)
registrar.startInjecting(PhpLanguage.INSTANCE)
.addPlace(
"""<?php
namespace $namespace;

$usesText

/**
* @kphp-generic $genericT
* @var tuple(""", ") \$_*/\$_;", context, range
)
.doneInjecting()
}
}

override fun elementsToInjectIn() = listOf(PsiCommentImpl::class.java)
}
2 changes: 1 addition & 1 deletion src/main/kotlin/com/vk/kphpstorm/exphptype/ExPhpType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ interface ExPhpType {
fun toPhpType(): PhpType
fun toHumanReadable(expr: PhpPsiElement): String
fun getSubkeyByIndex(indexKey: String): ExPhpType?
fun instantiateTemplate(nameMap: Map<String, ExPhpType>): ExPhpType
fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType
fun isAssignableFrom(rhs: ExPhpType, project: Project): Boolean

companion object {
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/vk/kphpstorm/exphptype/ExPhpTypeAny.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ExPhpTypeAny : ExPhpType {
return this
}

override fun instantiateTemplate(nameMap: Map<String, ExPhpType>): ExPhpType {
override fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType {
return this
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/com/vk/kphpstorm/exphptype/ExPhpTypeArray.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ class ExPhpTypeArray(val inner: ExPhpType) : ExPhpType {
return inner
}

override fun instantiateTemplate(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypeArray(inner.instantiateTemplate(nameMap))
override fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypeArray(inner.instantiateGeneric(nameMap))
}

override fun isAssignableFrom(rhs: ExPhpType, project: Project): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ class ExPhpTypeCallable(val argTypes: List<ExPhpType>, val returnType: ExPhpType
return null
}

override fun instantiateTemplate(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypeCallable(argTypes.map { it.instantiateTemplate(nameMap) }, returnType?.instantiateTemplate(nameMap))
override fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypeCallable(argTypes.map { it.instantiateGeneric(nameMap) }, returnType?.instantiateGeneric(nameMap))
}

override fun isAssignableFrom(rhs: ExPhpType, project: Project): Boolean = when (rhs) {
is ExPhpTypeAny -> true
// TODO: добавить полноценную проверку?
is ExPhpTypeCallable -> true
is ExPhpTypePrimitive -> rhs == ExPhpType.CALLABLE || rhs == ExPhpType.STRING
is ExPhpTypeNullable -> isAssignableFrom(rhs.inner, project)
else -> false
}
Expand Down
45 changes: 45 additions & 0 deletions src/main/kotlin/com/vk/kphpstorm/exphptype/ExPhpTypeClassString.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.vk.kphpstorm.exphptype

import com.intellij.openapi.project.Project
import com.jetbrains.php.lang.psi.elements.PhpPsiElement
import com.jetbrains.php.lang.psi.resolve.types.PhpType

/**
* Type of special class constant (e.g. `Foo::class`).
*/
class ExPhpTypeClassString(val inner: ExPhpType) : ExPhpType {
override fun toString() = "class-string($inner)"

override fun toHumanReadable(expr: PhpPsiElement) = "class-string($inner)"

override fun equals(other: Any?) = other is ExPhpTypeClassString && inner == other.inner

override fun hashCode() = 35

override fun toPhpType() = PhpType().add("class-string(${inner.toPhpType()})")

override fun getSubkeyByIndex(indexKey: String) = this

override fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType {
// TODO: подумать тут
val fqn = when (inner) {
is ExPhpTypeInstance -> inner.fqn
is ExPhpTypeGenericsT -> inner.nameT
else -> ""
}

val name = nameMap[fqn] ?: return this
if (name is ExPhpTypeGenericsT) {
return ExPhpTypeClassString(ExPhpTypeGenericsT(name.toString()))
}

return ExPhpTypeClassString(ExPhpTypeInstance(name.toString()))
}

override fun isAssignableFrom(rhs: ExPhpType, project: Project): Boolean = when (rhs) {
// class-string<T> is only compatible with class-string<E>
// if class E is compatible with class T.
is ExPhpTypeClassString -> inner.isAssignableFrom(rhs.inner, project)
else -> false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ class ExPhpTypeForcing(val inner: ExPhpType) : ExPhpType {
return ExPhpTypeForcing(inner.getSubkeyByIndex(indexKey) ?: return null)
}

override fun instantiateTemplate(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypeForcing(inner.instantiateTemplate(nameMap))
override fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypeForcing(inner.instantiateGeneric(nameMap))
}

override fun isAssignableFrom(rhs: ExPhpType, project: Project): Boolean {
Expand Down
29 changes: 29 additions & 0 deletions src/main/kotlin/com/vk/kphpstorm/exphptype/ExPhpTypeGenericsT.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.vk.kphpstorm.exphptype

import com.intellij.openapi.project.Project
import com.jetbrains.php.lang.psi.elements.PhpPsiElement
import com.jetbrains.php.lang.psi.resolve.types.PhpType

/**
* 'T' — is genericsT when it's defined in @kphp-generic, then it's genericsT on resolve, not class T
* @see com.vk.kphpstorm.exphptype.psi.ExPhpTypeInstancePsiImpl.getType
*/
class ExPhpTypeGenericsT(val nameT: String) : ExPhpType {
override fun toString() = "%$nameT"

override fun toHumanReadable(expr: PhpPsiElement) = "%$nameT"

override fun toPhpType(): PhpType = PhpType.EMPTY

override fun getSubkeyByIndex(indexKey: String) = null

override fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType {
return nameMap[nameT] ?: this
}

override fun isAssignableFrom(rhs: ExPhpType, project: Project): Boolean = when (rhs) {
is ExPhpTypeAny -> true
// todo shall we add any strict rules here?
else -> true
}
}
16 changes: 15 additions & 1 deletion src/main/kotlin/com/vk/kphpstorm/exphptype/ExPhpTypeInstance.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ExPhpTypeInstance(val fqn: String) : ExPhpType {
return null
}

override fun instantiateTemplate(nameMap: Map<String, ExPhpType>): ExPhpType {
override fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType {
return nameMap[fqn] ?: this
}

Expand All @@ -50,6 +50,20 @@ class ExPhpTypeInstance(val fqn: String) : ExPhpType {
rhsIsChild
}

is ExPhpTypeTplInstantiation -> rhs.classFqn == fqn || run {
val phpIndex = PhpIndex.getInstance(project)
val lhsClass = phpIndex.getAnyByFQN(fqn).firstOrNull() ?: return false
var rhsIsChild = false
phpIndex.getAnyByFQN(rhs.classFqn).forEach { rhsClass ->
PhpClassHierarchyUtils.processSuperWithoutMixins(rhsClass, true, true) { clazz ->
if (PhpClassHierarchyUtils.classesEqual(lhsClass, clazz))
rhsIsChild = true
!rhsIsChild
}
}
rhsIsChild
}

else -> false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class ExPhpTypeNullable(val inner: ExPhpType) : ExPhpType {
return inner.getSubkeyByIndex(indexKey)
}

override fun instantiateTemplate(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypeNullable(inner.instantiateTemplate(nameMap))
override fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypeNullable(inner.instantiateGeneric(nameMap))
}

override fun isAssignableFrom(rhs: ExPhpType, project: Project): Boolean = when (rhs) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/com/vk/kphpstorm/exphptype/ExPhpTypePipe.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ class ExPhpTypePipe(val items: List<ExPhpType>) : ExPhpType {
}
}

override fun instantiateTemplate(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypePipe(items.map { it.instantiateTemplate(nameMap) })
override fun instantiateGeneric(nameMap: Map<String, ExPhpType>): ExPhpType {
return ExPhpTypePipe(items.map { it.instantiateGeneric(nameMap) })
}

override fun isAssignableFrom(rhs: ExPhpType, project: Project): Boolean {
Expand Down
Loading