diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5eb5c53 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +out/ +*.jar diff --git a/META-INF/plugin.xml b/META-INF/plugin.xml new file mode 100644 index 0000000..b168ad4 --- /dev/null +++ b/META-INF/plugin.xml @@ -0,0 +1,44 @@ + + cz.matej21.intellij.kdyby.doctrine + Kdyby Doctrine support + 0.1.0 + David Matejka + + com.intellij.modules.lang + com.jetbrains.php + + Kdyby Doctrine library + ]]> + + 0.1.0 + + + ]]> + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intellij-kdyby-doctrine.iml b/intellij-kdyby-doctrine.iml new file mode 100644 index 0000000..b2f3591 --- /dev/null +++ b/intellij-kdyby-doctrine.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/php-project/doctrine.php b/php-project/doctrine.php new file mode 100644 index 0000000..421f337 --- /dev/null +++ b/php-project/doctrine.php @@ -0,0 +1,63 @@ +fooDao = $entityManager->getDao(FooEntity::class); + } + + /** + * @return FooEntity|object + */ + public function doSth() + { + return $this->fooDao->find(); + } +} + + + +/** @var \Kdyby\Doctrine\EntityManager $entityManager */ +$entityDao = $entityManager->getDao(FooEntity::class); +$entityDao->find()->id; + + +foreach($entityDao->findAll() as $entity) { + $entity->id; +} + +$result = $entityDao->fetch(); +$result->applyPaginator(); +foreach($result as $entity) { + $entity->id; +} \ No newline at end of file diff --git a/php-project/model.php b/php-project/model.php new file mode 100644 index 0000000..59a3ec2 --- /dev/null +++ b/php-project/model.php @@ -0,0 +1,12 @@ + getClasses(PhpTypedElement element, Project project) { + PhpIndex phpIndex = PhpIndex.getInstance(project); + Collection classes = new ArrayList(); + for (String className : element.getType().getTypes()) { + classes.addAll(phpIndex.getClassesByFQN(className)); + } + + return classes; + } + + private class UnresolvableValueException extends Exception { + } +} + diff --git a/src/cz/matej21/intellij/kdyby/doctrine/ForeachEntityTypeProvider.java b/src/cz/matej21/intellij/kdyby/doctrine/ForeachEntityTypeProvider.java new file mode 100644 index 0000000..4e8c53d --- /dev/null +++ b/src/cz/matej21/intellij/kdyby/doctrine/ForeachEntityTypeProvider.java @@ -0,0 +1,68 @@ +package cz.matej21.intellij.kdyby.doctrine; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.jetbrains.php.PhpIndex; +import com.jetbrains.php.lang.psi.elements.ForeachStatement; +import com.jetbrains.php.lang.psi.elements.PhpNamedElement; +import com.jetbrains.php.lang.psi.elements.PhpTypedElement; +import com.jetbrains.php.lang.psi.elements.Variable; +import com.jetbrains.php.lang.psi.resolve.types.PhpType; +import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider2; +import com.jetbrains.php.lang.psi.resolve.types.PhpTypeSignatureKey; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + + +public class ForeachEntityTypeProvider implements PhpTypeProvider2 { + + @Override + public char getKey() { + return '\u2102'; + } + + @Nullable + @Override + public String getType(PsiElement psiElement) { + if (!(psiElement instanceof Variable)) { + return null; + } + Variable variable = (Variable) psiElement; + PsiElement arrayAccessExpression = variable.getParent(); + if (!(arrayAccessExpression instanceof ForeachStatement)) { + return null; + } + ForeachStatement arrayIndex = (ForeachStatement) arrayAccessExpression; + PsiElement operation = arrayIndex.getArray(); + if (!(operation instanceof PhpTypedElement)) { + return null; + } + PhpType value = ((PhpTypedElement) operation).getType(); + if (variable == arrayIndex.getKey()) { + return null; + } + + if (variable != arrayIndex.getValue()) { + return null; + } + for (String strType : value.elementType().getTypes()) { + if (strType.length() < 2 + || strType.charAt(0) != '#' + || strType.indexOf(RepositoryMethodTypeProvider.KEY) == -1 + || !strType.contains("[]")) { + continue; + } + if (PhpTypeSignatureKey.ARRAY_ELEMENT.is(strType.charAt(1))) { + strType = strType.substring(2); + } + return strType.substring(strType.indexOf(RepositoryMethodTypeProvider.KEY) + 1, strType.indexOf("[]")); + } + return null; + } + + @Override + public Collection getBySignature(String s, Project project) { + return PhpIndex.getInstance(project).getAnyByFQN(s); + } +} diff --git a/src/cz/matej21/intellij/kdyby/doctrine/RepositoryMethodTypeProvider.java b/src/cz/matej21/intellij/kdyby/doctrine/RepositoryMethodTypeProvider.java new file mode 100644 index 0000000..d2f48a9 --- /dev/null +++ b/src/cz/matej21/intellij/kdyby/doctrine/RepositoryMethodTypeProvider.java @@ -0,0 +1,87 @@ +package cz.matej21.intellij.kdyby.doctrine; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.jetbrains.php.PhpIndex; +import com.jetbrains.php.lang.psi.elements.MethodReference; +import com.jetbrains.php.lang.psi.elements.PhpNamedElement; +import com.jetbrains.php.lang.psi.elements.PhpTypedElement; +import com.jetbrains.php.lang.psi.resolve.types.PhpType; +import com.jetbrains.php.lang.psi.resolve.types.PhpTypeAnalyserVisitor; +import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider2; +import com.jetbrains.php.lang.psi.resolve.types.PhpTypeSignatureKey; +import gnu.trove.THashSet; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; + +public class RepositoryMethodTypeProvider implements PhpTypeProvider2 { + public static final char KEY = '\u2101'; + private static final HashSet singleEntityMethods = new HashSet(Arrays.asList("find", "findOneBy")); + private static final HashSet setEntityMethods = new HashSet(Arrays.asList("findAll", "findBy", "fetch")); + + + @Override + public char getKey() { + return KEY; + } + + + @Nullable + @Override + public String getType(PsiElement psiElement) { + if (!(psiElement instanceof MethodReference)) { + return null; + } + MethodReference ref = (MethodReference) psiElement; + if (!singleEntityMethods.contains(ref.getName()) && !setEntityMethods.contains(ref.getName())) { + return null; + } + if (psiElement.getChildren().length == 0) { + return null; + } + PhpType type = ((PhpTypedElement) psiElement.getChildren()[0]).getType(); + PhpTypeAnalyserVisitor analyzer = new PhpTypeAnalyserVisitor(0); + psiElement.accept(analyzer); + for (String strType : type.getTypes()) { + if (strType.length() < 2 && strType.charAt(0) == '#' || strType.charAt(1) != RepositoryTypeProvider.KEY) { + continue; + } + String entityType = strType.substring(2, strType.indexOf(".")); + if (setEntityMethods.contains(ref.getName())) { + entityType += "[]"; + } + String originalType = strType.substring(strType.indexOf(".") + 1); + if (originalType.contains("|")) { + originalType = originalType.substring(0, originalType.indexOf("|")); + } + if (originalType.charAt(0) == '#') { + originalType = "." + PhpTypeSignatureKey.METHOD.sign(originalType + "." + ref.getName()); + } else { + originalType = ""; + } + return entityType + originalType; + } + + return null; + } + + @Override + public Collection getBySignature(String s, Project project) { + Collection result = new THashSet(); + PhpIndex phpIndex = PhpIndex.getInstance(project); + String entityName = s.substring(0, s.indexOf(".")); + if (!entityName.endsWith("[]")) { + result.addAll(phpIndex.getAnyByFQN(entityName)); + } + String signature = s.substring(s.indexOf(".") + 1); + if (signature.contains("|")) { + signature = signature.substring(0, signature.indexOf("|")); + } + result.addAll(phpIndex.getBySignature(signature)); + + return result; + } +} diff --git a/src/cz/matej21/intellij/kdyby/doctrine/RepositoryTypeProvider.java b/src/cz/matej21/intellij/kdyby/doctrine/RepositoryTypeProvider.java new file mode 100644 index 0000000..29dd549 --- /dev/null +++ b/src/cz/matej21/intellij/kdyby/doctrine/RepositoryTypeProvider.java @@ -0,0 +1,70 @@ +package cz.matej21.intellij.kdyby.doctrine; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.jetbrains.php.PhpIndex; +import com.jetbrains.php.lang.psi.elements.MethodReference; +import com.jetbrains.php.lang.psi.elements.ParameterList; +import com.jetbrains.php.lang.psi.elements.PhpNamedElement; +import com.jetbrains.php.lang.psi.elements.PhpTypedElement; +import com.jetbrains.php.lang.psi.resolve.types.PhpType; +import com.jetbrains.php.lang.psi.resolve.types.PhpTypeAnalyserVisitor; +import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider2; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + + +public class RepositoryTypeProvider implements PhpTypeProvider2 { + + public static final char KEY = '\u2100'; + private static final PhpType entityManager = new PhpType().add("Kdyby\\Doctrine\\EntityManager").add("Doctrine\\ORM\\EntityManager"); + + @Override + public char getKey() { + return KEY; + } + + @Nullable + @Override + public String getType(PsiElement psiElement) { + if (!(psiElement instanceof MethodReference)) { + return null; + } + MethodReference ref = (MethodReference) psiElement; + if (ref.getName() == null || (!ref.getName().equals("getDao") && !ref.getName().equals("getRepository"))) { + return null; + } + if (psiElement.getChildren().length == 0) { + return null; + } + PhpType type = ((PhpTypedElement) psiElement.getChildren()[0]).getType(); + if (!type.isConvertibleFrom(entityManager, PhpIndex.getInstance(psiElement.getProject()))) { + return null; + } + ParameterList list = ref.getParameterList(); + if (list == null || list.getChildren().length == 0) { + return null; + } + String className = ElementValueResolver.resolve(list.getFirstChild()); + if (className == null) { + return null; + } + + PhpTypeAnalyserVisitor analyzer = new PhpTypeAnalyserVisitor(0); + psiElement.accept(analyzer); + return className + "." + analyzer.getType().toString(); + } + + @Override + public Collection getBySignature(String s, Project project) { + String signature = s.substring(s.indexOf(".") + 1); + if (signature.contains("|")) { + signature = signature.substring(0, signature.indexOf("|")); + } + + return PhpIndex.getInstance(project).getBySignature(signature); + } + + +}