diff --git a/META-INF/plugin.xml b/META-INF/plugin.xml
index 40027f0ca..dd608ba88 100644
--- a/META-INF/plugin.xml
+++ b/META-INF/plugin.xml
@@ -94,6 +94,7 @@
+
diff --git a/src/fr/adrienbrault/idea/symfony2plugin/SymfonyInterfacesHelper.java b/src/fr/adrienbrault/idea/symfony2plugin/SymfonyInterfacesHelper.java
index 92bf9d223..89e518895 100644
--- a/src/fr/adrienbrault/idea/symfony2plugin/SymfonyInterfacesHelper.java
+++ b/src/fr/adrienbrault/idea/symfony2plugin/SymfonyInterfacesHelper.java
@@ -26,6 +26,14 @@ public static boolean isTemplatingRenderCall(PsiElement e) {
});
}
+ public static boolean isRepositoryCall(PsiElement e) {
+ // EntityManager is needed for symfony 2.0?
+ return isCallTo(e, new String[] {
+ "\\Doctrine\\ORM\\EntityManager.getRepository",
+ "\\Doctrine\\Common\\Persistence\\ObjectManager.getRepository"
+ });
+ }
+
private static boolean isCallTo(PsiElement e, String expectedMethodFQN) {
return isCallTo(e, new String[] { expectedMethodFQN }, 1);
}
diff --git a/src/fr/adrienbrault/idea/symfony2plugin/doctrine/DoctrineEntityReferenceContributor.java b/src/fr/adrienbrault/idea/symfony2plugin/doctrine/DoctrineEntityReferenceContributor.java
new file mode 100644
index 000000000..a69c56d3c
--- /dev/null
+++ b/src/fr/adrienbrault/idea/symfony2plugin/doctrine/DoctrineEntityReferenceContributor.java
@@ -0,0 +1,45 @@
+package fr.adrienbrault.idea.symfony2plugin.doctrine;
+
+import com.intellij.patterns.PlatformPatterns;
+import com.intellij.psi.*;
+import com.intellij.util.ProcessingContext;
+import com.jetbrains.php.lang.psi.elements.MethodReference;
+import com.jetbrains.php.lang.psi.elements.ParameterList;
+import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
+import fr.adrienbrault.idea.symfony2plugin.SymfonyInterfacesHelper;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Daniel Espendiller
+ */
+public class DoctrineEntityReferenceContributor extends PsiReferenceContributor {
+
+ @Override
+ public void registerReferenceProviders(PsiReferenceRegistrar psiReferenceRegistrar) {
+ psiReferenceRegistrar.registerReferenceProvider(
+ PlatformPatterns.psiElement(StringLiteralExpression.class),
+ new PsiReferenceProvider() {
+ @NotNull
+ @Override
+ public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) {
+ if (!(psiElement.getContext() instanceof ParameterList)) {
+ return new PsiReference[0];
+ }
+ ParameterList parameterList = (ParameterList) psiElement.getContext();
+
+ if (!(parameterList.getContext() instanceof MethodReference)) {
+ return new PsiReference[0];
+ }
+ MethodReference method = (MethodReference) parameterList.getContext();
+
+ if (!SymfonyInterfacesHelper.isRepositoryCall(method)) {
+ return new PsiReference[0];
+ }
+
+ return new PsiReference[]{ new EntityReference((StringLiteralExpression) psiElement) };
+ }
+ }
+ );
+ }
+
+}
diff --git a/src/fr/adrienbrault/idea/symfony2plugin/doctrine/EntityHelper.java b/src/fr/adrienbrault/idea/symfony2plugin/doctrine/EntityHelper.java
new file mode 100644
index 000000000..388db0ac4
--- /dev/null
+++ b/src/fr/adrienbrault/idea/symfony2plugin/doctrine/EntityHelper.java
@@ -0,0 +1,65 @@
+package fr.adrienbrault.idea.symfony2plugin.doctrine;
+
+import com.intellij.openapi.project.Project;
+import com.jetbrains.php.PhpIndex;
+import com.jetbrains.php.lang.psi.elements.PhpClass;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Daniel Espendiller
+ */
+public class EntityHelper {
+
+ /**
+ *
+ * @param project PHPStorm projects
+ * @param shortcutName name as MyBundle\Entity\Model or MyBundle:Model
+ * @return null|PhpClass
+ */
+ public static PhpClass resolveShortcutName(Project project, String shortcutName) {
+
+ PhpIndex phpIndex = PhpIndex.getInstance(project);
+ Collection phpClasses = phpIndex.getAllSubclasses("\\Symfony\\Component\\HttpKernel\\Bundle\\Bundle");
+
+ Map bundlesDirectories = new HashMap();
+ for (PhpClass phpClass : phpClasses) {
+ bundlesDirectories.put(phpClass.getName(), phpClass.getNamespaceName());
+ }
+
+ String entity_name = null;
+
+ // resolve:
+ // MyBundle:Model -> MyBundle\Entity\Model
+ // MyBundle:Folder\Model -> MyBundle\Entity\Folder\Model
+ if (shortcutName.contains(":")) {
+
+ int firstDirectorySeparatorIndex = shortcutName.indexOf(":");
+
+ String bundlename = shortcutName.substring(0, firstDirectorySeparatorIndex);
+ String entityName = shortcutName.substring(firstDirectorySeparatorIndex + 1);
+
+ String namespace = bundlesDirectories.get(bundlename);
+
+ if(namespace == null) {
+ return null;
+ }
+
+ entity_name = namespace + "Entity\\" + entityName;
+
+ } else {
+ entity_name = shortcutName;
+ }
+
+ // dont we have any unique class getting method here?
+ Collection entity_classes = phpIndex.getClassesByFQN(entity_name);
+ if(!entity_classes.isEmpty()){
+ return entity_classes.iterator().next();
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/fr/adrienbrault/idea/symfony2plugin/doctrine/EntityReference.java b/src/fr/adrienbrault/idea/symfony2plugin/doctrine/EntityReference.java
new file mode 100644
index 000000000..09870f95d
--- /dev/null
+++ b/src/fr/adrienbrault/idea/symfony2plugin/doctrine/EntityReference.java
@@ -0,0 +1,78 @@
+package fr.adrienbrault.idea.symfony2plugin.doctrine;
+
+import com.intellij.psi.*;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.psi.PsiElement;
+import com.jetbrains.php.PhpIndex;
+import com.jetbrains.php.lang.psi.elements.PhpClass;
+import com.jetbrains.php.lang.psi.elements.PhpNamespace;
+import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
+import fr.adrienbrault.idea.symfony2plugin.doctrine.dict.DoctrineEntityLookupElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Daniel Espendiller
+ */
+public class EntityReference extends PsiReferenceBase implements PsiReference {
+ private String entityName;
+
+ public EntityReference(@NotNull StringLiteralExpression element) {
+ super(element);
+
+ entityName = element.getText().substring(
+ element.getValueRange().getStartOffset(),
+ element.getValueRange().getEndOffset()
+ );
+ }
+
+ @Nullable
+ @Override
+ public PsiElement resolve() {
+
+ PhpClass entity = EntityHelper.resolveShortcutName(getElement().getProject(), this.entityName);
+ if(entity != null) {
+ return new PsiElementResolveResult(entity).getElement();
+ }
+
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public Object[] getVariants() {
+
+ PhpIndex phpIndex = PhpIndex.getInstance(getElement().getProject());
+ Collection phpClasses = phpIndex.getAllSubclasses("\\Symfony\\Component\\HttpKernel\\Bundle\\Bundle");
+
+ List results = new ArrayList();
+ for (PhpClass phpClass : phpClasses) {
+
+ // search for classes that match the symfony2 namings
+ String ns = phpClass.getNamespaceName() + "Entity";
+ Collection entities = phpIndex.getNamespacesByName(ns);
+
+ // @TODO: it looks like PhpIndex cant search for classes like \ns\Path\*\...
+ // temporary only use flat entities and dont support "MyBundle:Folder\Entity"
+ for (PhpNamespace entity_files : entities) {
+
+ // build our symfony2 shortcut
+ System.out.println(entity_files.getContainingFile().getContainingDirectory());
+ String filename = entity_files.getContainingFile().getName();
+ String className = filename.substring(0, filename.lastIndexOf('.'));
+ String repoName = phpClass.getName() + ':' + className;
+
+ for (PhpClass entity_phpclass : phpIndex.getClassesByFQN(ns + "\\" + className)) {
+ results.add(new DoctrineEntityLookupElement(repoName, entity_phpclass));
+ }
+
+ }
+
+ }
+
+ return results.toArray();
+ }
+
+}
diff --git a/src/fr/adrienbrault/idea/symfony2plugin/doctrine/dict/DoctrineEntityLookupElement.java b/src/fr/adrienbrault/idea/symfony2plugin/doctrine/dict/DoctrineEntityLookupElement.java
new file mode 100644
index 000000000..9f5e2278e
--- /dev/null
+++ b/src/fr/adrienbrault/idea/symfony2plugin/doctrine/dict/DoctrineEntityLookupElement.java
@@ -0,0 +1,36 @@
+package fr.adrienbrault.idea.symfony2plugin.doctrine.dict;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementPresentation;
+import com.jetbrains.php.PhpIcons;
+import com.jetbrains.php.lang.psi.elements.PhpClass;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Daniel Espendiller
+ */
+public class DoctrineEntityLookupElement extends LookupElement {
+
+ private String entityName;
+ private PhpClass className;
+
+ public DoctrineEntityLookupElement(String entityName, PhpClass className) {
+ this.entityName = entityName;
+ this.className = className;
+ }
+
+ @NotNull
+ @Override
+ public String getLookupString() {
+ return entityName;
+ }
+
+ public void renderElement(LookupElementPresentation presentation) {
+ presentation.setItemText(getLookupString());
+ presentation.setTypeText(className.getPresentableFQN());
+ presentation.setTypeGrayed(true);
+ presentation.setIcon(PhpIcons.CLASS);
+ }
+
+}
+
diff --git a/src/fr/adrienbrault/idea/symfony2plugin/templating/TemplateHelper.java b/src/fr/adrienbrault/idea/symfony2plugin/templating/TemplateHelper.java
index 412dedc4f..d220edd0b 100644
--- a/src/fr/adrienbrault/idea/symfony2plugin/templating/TemplateHelper.java
+++ b/src/fr/adrienbrault/idea/symfony2plugin/templating/TemplateHelper.java
@@ -53,9 +53,13 @@ public static Map getTwigFilesByName(Project project) {
String templateDirectory = null; // xxx:XXX:xxx
String templateFile = null; // xxx:xxx:XXX
if (templatePath.contains("/")) {
- int lastDirectorySeparatorIndex = templatePath.lastIndexOf("/");
- templateDirectory = templatePath.substring(0, lastDirectorySeparatorIndex);
- templateFile = templatePath.substring(lastDirectorySeparatorIndex + 1);
+
+ // remap twig folder shortcut:
+ // Folder/Subfolder/file.html.twig -> BundleName:Folder/Subfolder:file.html.twig
+
+ int firstDirectorySeparatorIndex = templatePath.indexOf("/");
+ templateDirectory = templatePath.substring(0, firstDirectorySeparatorIndex);
+ templateFile = templatePath.substring(firstDirectorySeparatorIndex + 1);
} else {
templateDirectory = "";
templateFile = templatePath;