From ea462d1e327cef66b97352bd42e788bd1e2270dd Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Wed, 22 Nov 2023 21:09:44 +0300 Subject: [PATCH 01/11] prototype of the bugfix --- .../services/ModuliteDependenciesCollector.kt | 86 ++++++++++++++++++- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt index 210fd63..6749a50 100644 --- a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt +++ b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt @@ -7,8 +7,10 @@ import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.containers.TreeNodeProcessingResult import com.jetbrains.php.lang.PhpLangUtil +import com.jetbrains.php.lang.documentation.phpdoc.PhpDocUtil.getReturnType import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocType import com.jetbrains.php.lang.psi.PhpFile import com.jetbrains.php.lang.psi.elements.ClassConstantReference @@ -19,6 +21,7 @@ import com.jetbrains.php.lang.psi.elements.FunctionReference import com.jetbrains.php.lang.psi.elements.Global import com.jetbrains.php.lang.psi.elements.MethodReference import com.jetbrains.php.lang.psi.elements.NewExpression +import com.jetbrains.php.lang.psi.elements.PhpClass import com.jetbrains.php.lang.psi.elements.PhpNamedElement import com.jetbrains.php.lang.psi.elements.PhpNamespace import com.jetbrains.php.lang.psi.elements.PhpNamespaceReference @@ -28,6 +31,7 @@ import com.jetbrains.php.lang.psi.elements.Variable import com.jetbrains.php.lang.psi.elements.impl.FieldImpl import com.jetbrains.php.lang.psi.elements.impl.FunctionImpl import com.jetbrains.php.lang.psi.elements.impl.MethodImpl +import com.jetbrains.php.lang.psi.elements.impl.MethodReferenceImpl import com.vk.modulite.Namespace import com.vk.modulite.SymbolName import com.vk.modulite.actions.dialogs.DepsRegenerationResultDialog @@ -213,7 +217,6 @@ class ModuliteDependenciesCollector(val project: Project) { val composerPackages = ComposerPackagesIndex.getInstance(project).getPackages() val moduliteConfig = dir.findChild(".modulite.yaml") - dir.forEachFilesEx(project) { file -> // Проверяем не отменил ои пользователь операцию. ProgressManager.checkCanceled() @@ -226,6 +229,8 @@ class ModuliteDependenciesCollector(val project: Project) { psiFile.accept(object : PhpRecursiveElementVisitor() { override fun visitPhpClassReference(reference: ClassReference) { + /* reference as PhpClass + reference.isInterface*/ when (reference.context) { is PhpUse, is MethodReference, is ClassConstantReference -> { return @@ -358,6 +363,66 @@ class ModuliteDependenciesCollector(val project: Project) { } } + private fun hasReferenceInPsiTree(targetReference: PhpNamedElement, psiFile: PhpFile?): Boolean { + return psiFile?.let { findReferenceInPsiTree(targetReference, it) } == true + } + + private fun findReferenceInPsiTree(targetReference: PhpNamedElement, element: PsiElement): Boolean { + var child = element.firstChild + + while (child != null) { + when (child) { + is PhpClass -> { + if (child.isEquivalentTo(targetReference)) { + return true + } + if(child.isInterface){ + child.methods.forEach { method -> + val d = method.returnType + val c = getReturnType(method) + val t =method.type + val v = targetReference.type + if(c == v){ + return true + } + println() + } + }else{ + child.methods.forEach { method -> + if (method.isEquivalentTo(targetReference)) { + return true + } + } + } + } + + is MethodReferenceImpl -> { + val value = child.resolve() + if (value != null) { + if(value.isEquivalentTo(targetReference)){ + return true + } + } + /* if (child.isEquivalentTo(targetReference)) { + return true + }*/ + } + + is FunctionImpl -> { + if (child.isEquivalentTo(targetReference)) { + return true + } + } + } + + // Рекурсивный обход дочерних элементов + if (findReferenceInPsiTree(targetReference, child)) return true + child = child.nextSibling + } + + return false + } + private fun addReferenceModuleIfNeeded(reference: PhpNamedElement): Boolean { if (reference is Variable) { // Глобальные переменные не могут содержаться в некотором модуле, @@ -386,8 +451,23 @@ class ModuliteDependenciesCollector(val project: Project) { val modulite = containingFile.containingModulite(project, modulites) if (modulite != null) { - addSymbol(modulite.symbolName()) - return collapseModuleSymbols + // val d = file + if (reference.context?.containingModulite() == dir.containingModulite(project)) { + println() + addSymbol(modulite.symbolName()) + return collapseModuleSymbols + } + + if (dir.containingModulite(project) != modulite) { + val psiCurrentFile = file.psiFile(project) + if (hasReferenceInPsiTree(reference, psiCurrentFile)) { + addSymbol(modulite.symbolName()) + return collapseModuleSymbols + } + } + /* val d = file.psiFile(project) + addSymbol(modulite.symbolName()) + return collapseModuleSymbols*/ } val composerPackage = containingFile.containingComposerPackage(project, composerPackages) From fe6bdb83f6d625ec321f614000d56f33d38ba4d9 Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Thu, 23 Nov 2023 15:18:00 +0300 Subject: [PATCH 02/11] removed unused parts of the code --- .../services/ModuliteDependenciesCollector.kt | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt index 6749a50..48abf12 100644 --- a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt +++ b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt @@ -30,6 +30,7 @@ import com.jetbrains.php.lang.psi.elements.PhpUse import com.jetbrains.php.lang.psi.elements.Variable import com.jetbrains.php.lang.psi.elements.impl.FieldImpl import com.jetbrains.php.lang.psi.elements.impl.FunctionImpl +import com.jetbrains.php.lang.psi.elements.impl.FunctionReferenceImpl import com.jetbrains.php.lang.psi.elements.impl.MethodImpl import com.jetbrains.php.lang.psi.elements.impl.MethodReferenceImpl import com.vk.modulite.Namespace @@ -376,18 +377,14 @@ class ModuliteDependenciesCollector(val project: Project) { if (child.isEquivalentTo(targetReference)) { return true } - if(child.isInterface){ + if (child.isInterface) { child.methods.forEach { method -> - val d = method.returnType - val c = getReturnType(method) - val t =method.type - val v = targetReference.type - if(c == v){ + if (method.type == targetReference.type) { return true } println() } - }else{ + } else { child.methods.forEach { method -> if (method.isEquivalentTo(targetReference)) { return true @@ -399,18 +396,18 @@ class ModuliteDependenciesCollector(val project: Project) { is MethodReferenceImpl -> { val value = child.resolve() if (value != null) { - if(value.isEquivalentTo(targetReference)){ + if (value.isEquivalentTo(targetReference)) { return true } } - /* if (child.isEquivalentTo(targetReference)) { - return true - }*/ } - is FunctionImpl -> { - if (child.isEquivalentTo(targetReference)) { - return true + is FunctionReferenceImpl -> { + val value = child.resolve() + if (value != null) { + if (value.isEquivalentTo(targetReference)) { + return true + } } } } @@ -451,7 +448,6 @@ class ModuliteDependenciesCollector(val project: Project) { val modulite = containingFile.containingModulite(project, modulites) if (modulite != null) { - // val d = file if (reference.context?.containingModulite() == dir.containingModulite(project)) { println() addSymbol(modulite.symbolName()) @@ -465,9 +461,6 @@ class ModuliteDependenciesCollector(val project: Project) { return collapseModuleSymbols } } - /* val d = file.psiFile(project) - addSymbol(modulite.symbolName()) - return collapseModuleSymbols*/ } val composerPackage = containingFile.containingComposerPackage(project, composerPackages) From 78c0faf09cd1ef04e7734aed3469646a4e5e75b8 Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Fri, 24 Nov 2023 22:48:16 +0300 Subject: [PATCH 03/11] added new conditions, new logic for module return value --- .../services/ModuliteDependenciesCollector.kt | 97 +++++++++++++++---- 1 file changed, 78 insertions(+), 19 deletions(-) diff --git a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt index 48abf12..61a2193 100644 --- a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt +++ b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt @@ -13,26 +13,16 @@ import com.jetbrains.php.lang.PhpLangUtil import com.jetbrains.php.lang.documentation.phpdoc.PhpDocUtil.getReturnType import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocType import com.jetbrains.php.lang.psi.PhpFile -import com.jetbrains.php.lang.psi.elements.ClassConstantReference -import com.jetbrains.php.lang.psi.elements.ClassReference -import com.jetbrains.php.lang.psi.elements.ConstantReference -import com.jetbrains.php.lang.psi.elements.FieldReference -import com.jetbrains.php.lang.psi.elements.FunctionReference -import com.jetbrains.php.lang.psi.elements.Global -import com.jetbrains.php.lang.psi.elements.MethodReference -import com.jetbrains.php.lang.psi.elements.NewExpression -import com.jetbrains.php.lang.psi.elements.PhpClass -import com.jetbrains.php.lang.psi.elements.PhpNamedElement -import com.jetbrains.php.lang.psi.elements.PhpNamespace -import com.jetbrains.php.lang.psi.elements.PhpNamespaceReference -import com.jetbrains.php.lang.psi.elements.PhpReference -import com.jetbrains.php.lang.psi.elements.PhpUse -import com.jetbrains.php.lang.psi.elements.Variable +import com.jetbrains.php.lang.psi.elements.* +import com.jetbrains.php.lang.psi.elements.Function +import com.jetbrains.php.lang.psi.elements.impl.ConstantReferenceImpl import com.jetbrains.php.lang.psi.elements.impl.FieldImpl import com.jetbrains.php.lang.psi.elements.impl.FunctionImpl import com.jetbrains.php.lang.psi.elements.impl.FunctionReferenceImpl import com.jetbrains.php.lang.psi.elements.impl.MethodImpl import com.jetbrains.php.lang.psi.elements.impl.MethodReferenceImpl +import com.jetbrains.php.lang.psi.elements.impl.VariableImpl +import com.jetbrains.php.lang.psi.resolve.types.PhpType import com.vk.modulite.Namespace import com.vk.modulite.SymbolName import com.vk.modulite.actions.dialogs.DepsRegenerationResultDialog @@ -368,6 +358,24 @@ class ModuliteDependenciesCollector(val project: Project) { return psiFile?.let { findReferenceInPsiTree(targetReference, it) } == true } + private fun isPrimitiveType(phpType: PhpType): Boolean { + val primitiveTypes = setOf("int", "integer", "string", "?string", "bool", "boolean", "float", "double", "void", "null", "mixed[]", "mixed") + return primitiveTypes.contains(phpType.toString()) + // return phpType.types.any { it in primitiveTypes } + } + + private fun areTypesEquivalentIgnoringNullable(type1: PhpType, type2: PhpType): Boolean { + if(isPrimitiveType(type1) || isPrimitiveType(type2)){ + return false + } + // Проверяем, совпадают ли основные типы + val baseTypes1 = type1.filterNull().types + val baseTypes2 = type2.filterNull().types + + // Сравнение наборов типов + return baseTypes1 == baseTypes2 + } + private fun findReferenceInPsiTree(targetReference: PhpNamedElement, element: PsiElement): Boolean { var child = element.firstChild @@ -377,20 +385,28 @@ class ModuliteDependenciesCollector(val project: Project) { if (child.isEquivalentTo(targetReference)) { return true } + if (child.isInterface) { child.methods.forEach { method -> - if (method.type == targetReference.type) { + // тут тоже потенциальна ошибка, что если тип - примитив? Ложное срабатывание? + if (areTypesEquivalentIgnoringNullable(method.type, targetReference.type)) { return true } + // аналогично тут + method.parameters.forEach { param-> + if(areTypesEquivalentIgnoringNullable(param.type, targetReference.type)){ + return true + } + } println() } - } else { + } /*else { child.methods.forEach { method -> if (method.isEquivalentTo(targetReference)) { return true } } - } + }*/ } is MethodReferenceImpl -> { @@ -399,6 +415,22 @@ class ModuliteDependenciesCollector(val project: Project) { if (value.isEquivalentTo(targetReference)) { return true } + value as Method + if (areTypesEquivalentIgnoringNullable(value.type, targetReference.type)) { + val potentialInterface = value.context as PhpClass + if(potentialInterface.isInterface){ + return false + } + if(value.context == targetReference.context){ + return true + } + } + + value.parameters.forEach { param-> + if(areTypesEquivalentIgnoringNullable(param.type, targetReference.type)){ + return true + } + } } } @@ -408,10 +440,36 @@ class ModuliteDependenciesCollector(val project: Project) { if (value.isEquivalentTo(targetReference)) { return true } + /////////////////////////////////// + value as Function + value.parameters.forEach { param-> + if(areTypesEquivalentIgnoringNullable(param.type, targetReference.type)){ + return true + } + } } } - } + is VariableImpl -> { + val value = child.resolve() + if(value != null){ + if(value is Variable){ + // val variable = value as Variable + if(areTypesEquivalentIgnoringNullable(value.type, targetReference.type)){ + return true + } + } + /* if (value.isEquivalentTo(targetReference)) { + return true + }*/ + } + } + + is ConstantReferenceImpl -> { + + } + } + //////////////////////////////////// // Рекурсивный обход дочерних элементов if (findReferenceInPsiTree(targetReference, child)) return true child = child.nextSibling @@ -461,6 +519,7 @@ class ModuliteDependenciesCollector(val project: Project) { return collapseModuleSymbols } } + return collapseModuleSymbols } val composerPackage = containingFile.containingComposerPackage(project, composerPackages) From 5ec2e5a70abe8970b5feaa1b1a712fcda5cebd8a Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Tue, 28 Nov 2023 16:54:56 +0300 Subject: [PATCH 04/11] added additional logic for classes that implemented interfaces removed comments --- .../services/ModuliteDependenciesCollector.kt | 73 ++++++++----------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt index 61a2193..ecd23d9 100644 --- a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt +++ b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt @@ -7,15 +7,12 @@ import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiElement -import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.containers.TreeNodeProcessingResult import com.jetbrains.php.lang.PhpLangUtil -import com.jetbrains.php.lang.documentation.phpdoc.PhpDocUtil.getReturnType import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocType import com.jetbrains.php.lang.psi.PhpFile import com.jetbrains.php.lang.psi.elements.* import com.jetbrains.php.lang.psi.elements.Function -import com.jetbrains.php.lang.psi.elements.impl.ConstantReferenceImpl import com.jetbrains.php.lang.psi.elements.impl.FieldImpl import com.jetbrains.php.lang.psi.elements.impl.FunctionImpl import com.jetbrains.php.lang.psi.elements.impl.FunctionReferenceImpl @@ -360,8 +357,7 @@ class ModuliteDependenciesCollector(val project: Project) { private fun isPrimitiveType(phpType: PhpType): Boolean { val primitiveTypes = setOf("int", "integer", "string", "?string", "bool", "boolean", "float", "double", "void", "null", "mixed[]", "mixed") - return primitiveTypes.contains(phpType.toString()) - // return phpType.types.any { it in primitiveTypes } + return primitiveTypes.contains(phpType.toString()) } private fun areTypesEquivalentIgnoringNullable(type1: PhpType, type2: PhpType): Boolean { @@ -388,25 +384,24 @@ class ModuliteDependenciesCollector(val project: Project) { if (child.isInterface) { child.methods.forEach { method -> - // тут тоже потенциальна ошибка, что если тип - примитив? Ложное срабатывание? if (areTypesEquivalentIgnoringNullable(method.type, targetReference.type)) { return true } - // аналогично тут - method.parameters.forEach { param-> - if(areTypesEquivalentIgnoringNullable(param.type, targetReference.type)){ + + method.parameters.forEach { param -> + if (areTypesEquivalentIgnoringNullable(param.type, targetReference.type)) { return true } } - println() } - } /*else { - child.methods.forEach { method -> - if (method.isEquivalentTo(targetReference)) { + }else{ + val implInterfaces = child.implementedInterfaces + implInterfaces.forEach { t -> + if(t.isEquivalentTo(targetReference)){ return true } } - }*/ + } } is MethodReferenceImpl -> { @@ -415,20 +410,21 @@ class ModuliteDependenciesCollector(val project: Project) { if (value.isEquivalentTo(targetReference)) { return true } - value as Method - if (areTypesEquivalentIgnoringNullable(value.type, targetReference.type)) { - val potentialInterface = value.context as PhpClass - if(potentialInterface.isInterface){ - return false - } - if(value.context == targetReference.context){ - return true + if (value is Method) { + if (areTypesEquivalentIgnoringNullable(value.type, targetReference.type)) { + val potentialInterface = value.context as PhpClass + if (potentialInterface.isInterface) { + return false + } + if (value.context == targetReference.context) { + return true + } } - } - value.parameters.forEach { param-> - if(areTypesEquivalentIgnoringNullable(param.type, targetReference.type)){ - return true + value.parameters.forEach { param -> + if (areTypesEquivalentIgnoringNullable(param.type, targetReference.type)) { + return true + } } } } @@ -440,11 +436,11 @@ class ModuliteDependenciesCollector(val project: Project) { if (value.isEquivalentTo(targetReference)) { return true } - /////////////////////////////////// - value as Function - value.parameters.forEach { param-> - if(areTypesEquivalentIgnoringNullable(param.type, targetReference.type)){ - return true + if (value is Function) { + value.parameters.forEach { param -> + if (areTypesEquivalentIgnoringNullable(param.type, targetReference.type)) { + return true + } } } } @@ -452,24 +448,15 @@ class ModuliteDependenciesCollector(val project: Project) { is VariableImpl -> { val value = child.resolve() - if(value != null){ - if(value is Variable){ - // val variable = value as Variable - if(areTypesEquivalentIgnoringNullable(value.type, targetReference.type)){ + if (value != null) { + if (value is Variable) { + if (areTypesEquivalentIgnoringNullable(value.type, targetReference.type)) { return true } } - /* if (value.isEquivalentTo(targetReference)) { - return true - }*/ } } - - is ConstantReferenceImpl -> { - - } } - //////////////////////////////////// // Рекурсивный обход дочерних элементов if (findReferenceInPsiTree(targetReference, child)) return true child = child.nextSibling From 60e03c9a870c2697ff036320008a2e026e3134d9 Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Wed, 29 Nov 2023 19:06:38 +0300 Subject: [PATCH 05/11] added test --- .../MainFolder/.modulite.yaml.expected | 21 +++++++++++ .../MainFolder/Impl/.modulite.yaml.expected | 18 ++++++++++ .../MainFolder/Impl/ImplTester.php | 11 ++++++ .../MainFolder/Impl1/.modulite.yaml.expected | 18 ++++++++++ .../MainFolder/Impl1/Impl1.php | 12 +++++++ .../Interfaces/.modulite.yaml.expected | 19 ++++++++++ .../MainFolder/Interfaces/Icaller.php | 11 ++++++ .../MainFolder/Interfaces/Task.php | 7 ++++ .../MainFolder/Tester.php | 11 ++++++ .../tests/integration/CreateModuliteTest.kt | 35 +++++++++++++++++++ 10 files changed, 163 insertions(+) create mode 100644 src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/.modulite.yaml.expected create mode 100644 src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl/.modulite.yaml.expected create mode 100644 src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl/ImplTester.php create mode 100644 src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl1/.modulite.yaml.expected create mode 100644 src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl1/Impl1.php create mode 100644 src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Interfaces/.modulite.yaml.expected create mode 100644 src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Interfaces/Icaller.php create mode 100644 src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Interfaces/Task.php create mode 100644 src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Tester.php diff --git a/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/.modulite.yaml.expected b/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/.modulite.yaml.expected new file mode 100644 index 0000000..d3395d4 --- /dev/null +++ b/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/.modulite.yaml.expected @@ -0,0 +1,21 @@ +name: "@main-folder" +description: "" +namespace: "" + +# "Public API" of the modulite: classes, functions, constants, etc. +# Symbols not listed here will be internal. +export: + - "@main-folder/impl" + - "@main-folder/impl1" + - "@main-folder/interfaces" + - "MainFolder\\Tester" + +# Class members to exclude, they override "export". +force-internal: + +# Dependencies: other modulites, global classes, defines, etc. +require: + - "@main-folder/interfaces" + +# Granting partial access to internal symbols, "as an exception". +allow-internal-access: diff --git a/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl/.modulite.yaml.expected b/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl/.modulite.yaml.expected new file mode 100644 index 0000000..5419559 --- /dev/null +++ b/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl/.modulite.yaml.expected @@ -0,0 +1,18 @@ +name: "@main-folder/impl" +description: "" +namespace: "Impl\\" + +# "Public API" of the modulite: classes, functions, constants, etc. +# Symbols not listed here will be internal. +export: + - "ImplTester" + +# Class members to exclude, they override "export". +force-internal: + +# Dependencies: other modulites, global classes, defines, etc. +require: + - "@main-folder/interfaces" + +# Granting partial access to internal symbols, "as an exception". +allow-internal-access: diff --git a/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl/ImplTester.php b/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl/ImplTester.php new file mode 100644 index 0000000..2b02bea --- /dev/null +++ b/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Impl/ImplTester.php @@ -0,0 +1,11 @@ +getSerializedTaskDataJson(); + } +} diff --git a/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Interfaces/Task.php b/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Interfaces/Task.php new file mode 100644 index 0000000..07bc8c8 --- /dev/null +++ b/src/test/fixtures/integration/CreateModulite/InterfaceDependencies/MainFolder/Interfaces/Task.php @@ -0,0 +1,7 @@ + Date: Mon, 4 Dec 2023 19:46:36 +0300 Subject: [PATCH 06/11] removed comment --- .../com/vk/modulite/services/ModuliteDependenciesCollector.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt index ecd23d9..ff3db6e 100644 --- a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt +++ b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt @@ -217,8 +217,6 @@ class ModuliteDependenciesCollector(val project: Project) { psiFile.accept(object : PhpRecursiveElementVisitor() { override fun visitPhpClassReference(reference: ClassReference) { - /* reference as PhpClass - reference.isInterface*/ when (reference.context) { is PhpUse, is MethodReference, is ClassConstantReference -> { return From 164d0cf03951602fa152c914baa1833719b4a678 Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Mon, 12 Feb 2024 12:57:06 +0300 Subject: [PATCH 07/11] base prototype solution for right solving packages inheritance methods\classes --- .../services/ModuliteDependenciesCollector.kt | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt index ff3db6e..afd0c32 100644 --- a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt +++ b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt @@ -13,12 +13,7 @@ import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocType import com.jetbrains.php.lang.psi.PhpFile import com.jetbrains.php.lang.psi.elements.* import com.jetbrains.php.lang.psi.elements.Function -import com.jetbrains.php.lang.psi.elements.impl.FieldImpl -import com.jetbrains.php.lang.psi.elements.impl.FunctionImpl -import com.jetbrains.php.lang.psi.elements.impl.FunctionReferenceImpl -import com.jetbrains.php.lang.psi.elements.impl.MethodImpl -import com.jetbrains.php.lang.psi.elements.impl.MethodReferenceImpl -import com.jetbrains.php.lang.psi.elements.impl.VariableImpl +import com.jetbrains.php.lang.psi.elements.impl.* import com.jetbrains.php.lang.psi.resolve.types.PhpType import com.vk.modulite.Namespace import com.vk.modulite.SymbolName @@ -200,6 +195,7 @@ class ModuliteDependenciesCollector(val project: Project) { val ownSymbolsSet = ownSymbols?.toSet() ?: ModuliteSymbolsCollector.getInstance(project).collect(dir).toSet() val symbols = mutableSetOf() + lateinit var currentClassMethodOwner : ClassReferenceImpl val modulites = ModuliteIndex.getInstance(project).getModulites() val composerPackages = ComposerPackagesIndex.getInstance(project).getPackages() @@ -231,6 +227,7 @@ class ModuliteDependenciesCollector(val project: Project) { } override fun visitPhpMethodReference(reference: MethodReference) { + currentClassMethodOwner = reference.classReference as ClassReferenceImpl handleReference(reference) } @@ -509,7 +506,18 @@ class ModuliteDependenciesCollector(val project: Project) { val composerPackage = containingFile.containingComposerPackage(project, composerPackages) if (composerPackage != null) { - addSymbol(composerPackage.symbolName()) + + if (reference is MethodImpl) { + val methodOwner = currentClassMethodOwner// + val methodSignature = methodOwner.fqn?.let { SymbolName(it + "::${reference.name}()") } + + if (methodSignature != null) { + addSymbol(methodSignature) + } + } else { + addSymbol(composerPackage.symbolName()) + return collapseModuleSymbols + } return collapseModuleSymbols } From 6e322426e9800371eed98f76a7617665c3cfaa47 Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Mon, 12 Feb 2024 13:14:37 +0300 Subject: [PATCH 08/11] dangerous fix --- .../com/vk/modulite/services/ModuliteDependenciesCollector.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt index afd0c32..e93448e 100644 --- a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt +++ b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt @@ -227,7 +227,9 @@ class ModuliteDependenciesCollector(val project: Project) { } override fun visitPhpMethodReference(reference: MethodReference) { - currentClassMethodOwner = reference.classReference as ClassReferenceImpl + if (reference.classReference is ClassReferenceImpl) { + currentClassMethodOwner = reference.classReference as ClassReferenceImpl + } handleReference(reference) } From ad16a37b57f2b928e05c7cd6272ebd649dad3936 Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Fri, 28 Jun 2024 14:12:42 +0300 Subject: [PATCH 09/11] formatting --- .../services/ModuliteDependenciesCollector.kt | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt index e93448e..37a385f 100644 --- a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt +++ b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt @@ -353,12 +353,25 @@ class ModuliteDependenciesCollector(val project: Project) { } private fun isPrimitiveType(phpType: PhpType): Boolean { - val primitiveTypes = setOf("int", "integer", "string", "?string", "bool", "boolean", "float", "double", "void", "null", "mixed[]", "mixed") + val primitiveTypes = setOf( + "int", + "integer", + "string", + "?string", + "bool", + "boolean", + "float", + "double", + "void", + "null", + "mixed[]", + "mixed" + ) return primitiveTypes.contains(phpType.toString()) } private fun areTypesEquivalentIgnoringNullable(type1: PhpType, type2: PhpType): Boolean { - if(isPrimitiveType(type1) || isPrimitiveType(type2)){ + if (isPrimitiveType(type1) || isPrimitiveType(type2)) { return false } // Проверяем, совпадают ли основные типы @@ -391,10 +404,10 @@ class ModuliteDependenciesCollector(val project: Project) { } } } - }else{ - val implInterfaces = child.implementedInterfaces + } else { + val implInterfaces = child.implementedInterfaces implInterfaces.forEach { t -> - if(t.isEquivalentTo(targetReference)){ + if (t.isEquivalentTo(targetReference)) { return true } } @@ -508,7 +521,6 @@ class ModuliteDependenciesCollector(val project: Project) { val composerPackage = containingFile.containingComposerPackage(project, composerPackages) if (composerPackage != null) { - if (reference is MethodImpl) { val methodOwner = currentClassMethodOwner// val methodSignature = methodOwner.fqn?.let { SymbolName(it + "::${reference.name}()") } From 884915b2a3d73c75d802c1561ec1862c21a0ca55 Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Tue, 2 Jul 2024 19:32:40 +0300 Subject: [PATCH 10/11] simplify some condition, fixed bug with ::class dependencies --- .../services/ModuliteDependenciesCollector.kt | 72 +++++++++---------- .../tests/integration/CreateModuliteTest.kt | 2 +- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt index 37a385f..ed73a07 100644 --- a/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt +++ b/src/main/kotlin/com/vk/modulite/services/ModuliteDependenciesCollector.kt @@ -214,7 +214,13 @@ class ModuliteDependenciesCollector(val project: Project) { psiFile.accept(object : PhpRecursiveElementVisitor() { override fun visitPhpClassReference(reference: ClassReference) { when (reference.context) { - is PhpUse, is MethodReference, is ClassConstantReference -> { + is PhpUse -> { + if (reference is ClassReferenceImpl) { + handleReference(reference) + } + } + + is MethodReference, is ClassConstantReference -> { return } } @@ -415,54 +421,48 @@ class ModuliteDependenciesCollector(val project: Project) { } is MethodReferenceImpl -> { - val value = child.resolve() - if (value != null) { - if (value.isEquivalentTo(targetReference)) { - return true - } - if (value is Method) { - if (areTypesEquivalentIgnoringNullable(value.type, targetReference.type)) { - val potentialInterface = value.context as PhpClass - if (potentialInterface.isInterface) { - return false - } - if (value.context == targetReference.context) { - return true - } + val value = child.resolve() ?: return false + if (value.isEquivalentTo(targetReference)) { + return true + } + if (value is Method) { + if (areTypesEquivalentIgnoringNullable(value.type, targetReference.type)) { + val potentialInterface = value.context as PhpClass + if (potentialInterface.isInterface) { + return false + } + if (value.context == targetReference.context) { + return true } + } - value.parameters.forEach { param -> - if (areTypesEquivalentIgnoringNullable(param.type, targetReference.type)) { - return true - } + value.parameters.forEach { param -> + if (areTypesEquivalentIgnoringNullable(param.type, targetReference.type)) { + return true } } } } is FunctionReferenceImpl -> { - val value = child.resolve() - if (value != null) { - if (value.isEquivalentTo(targetReference)) { - return true - } - if (value is Function) { - value.parameters.forEach { param -> - if (areTypesEquivalentIgnoringNullable(param.type, targetReference.type)) { - return true - } + val value = child.resolve() ?: return false + if (value.isEquivalentTo(targetReference)) { + return true + } + if (value is Function) { + value.parameters.forEach { param -> + if (areTypesEquivalentIgnoringNullable(param.type, targetReference.type)) { + return true } } } } is VariableImpl -> { - val value = child.resolve() - if (value != null) { - if (value is Variable) { - if (areTypesEquivalentIgnoringNullable(value.type, targetReference.type)) { - return true - } + val value = child.resolve() ?: return false + if (value is Variable) { + if (areTypesEquivalentIgnoringNullable(value.type, targetReference.type)) { + return true } } } @@ -504,7 +504,6 @@ class ModuliteDependenciesCollector(val project: Project) { val modulite = containingFile.containingModulite(project, modulites) if (modulite != null) { if (reference.context?.containingModulite() == dir.containingModulite(project)) { - println() addSymbol(modulite.symbolName()) return collapseModuleSymbols } @@ -515,6 +514,7 @@ class ModuliteDependenciesCollector(val project: Project) { addSymbol(modulite.symbolName()) return collapseModuleSymbols } + addSymbol(modulite.symbolName()) } return collapseModuleSymbols } diff --git a/src/test/kotlin/com/vk/modulite/tests/integration/CreateModuliteTest.kt b/src/test/kotlin/com/vk/modulite/tests/integration/CreateModuliteTest.kt index 1c283e1..dc7da82 100644 --- a/src/test/kotlin/com/vk/modulite/tests/integration/CreateModuliteTest.kt +++ b/src/test/kotlin/com/vk/modulite/tests/integration/CreateModuliteTest.kt @@ -134,7 +134,7 @@ class CreateModuliteTest : IntegrationTestBase() { } } - fun `test module dependencies when interface has realisation`() = integrationTest("InterfaceDependencies"){ + fun `test module dependencies when interface has realisation`() = integrationTest("InterfaceDependencies") { step("create modulite") { createModuliteFromSource("MainFolder") { makeAllExported() From 6bf8c6d9e09594665d4f55d53bd75ba4fd84fcc6 Mon Sep 17 00:00:00 2001 From: Richardas Kuchinskas Date: Tue, 2 Jul 2024 19:43:27 +0300 Subject: [PATCH 11/11] new test --- .../ClassRequireWithColonColon/index.php | 8 +++++++ .../mod_a/.modulite.yaml.expected | 18 ++++++++++++++++ .../ClassRequireWithColonColon/mod_a/Foo.php | 12 +++++++++++ .../mod_b/.modulite.yaml.expected | 17 +++++++++++++++ .../ClassRequireWithColonColon/mod_b/Bar.php | 5 +++++ .../tests/integration/CreateModuliteTest.kt | 21 +++++++++++++++++++ 6 files changed, 81 insertions(+) create mode 100644 src/test/fixtures/integration/CreateModulite/ClassRequireWithColonColon/index.php create mode 100644 src/test/fixtures/integration/CreateModulite/ClassRequireWithColonColon/mod_a/.modulite.yaml.expected create mode 100644 src/test/fixtures/integration/CreateModulite/ClassRequireWithColonColon/mod_a/Foo.php create mode 100644 src/test/fixtures/integration/CreateModulite/ClassRequireWithColonColon/mod_b/.modulite.yaml.expected create mode 100644 src/test/fixtures/integration/CreateModulite/ClassRequireWithColonColon/mod_b/Bar.php diff --git a/src/test/fixtures/integration/CreateModulite/ClassRequireWithColonColon/index.php b/src/test/fixtures/integration/CreateModulite/ClassRequireWithColonColon/index.php new file mode 100644 index 0000000..bcbfa34 --- /dev/null +++ b/src/test/fixtures/integration/CreateModulite/ClassRequireWithColonColon/index.php @@ -0,0 +1,8 @@ +