-
-
Couldn't load subscription status.
- Fork 142
[WIP]Feature/doctrine support #25
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
Merged
adrienbrault
merged 16 commits into
Haehnchen:master
from
Haehnchen:feature/doctrine-support
May 4, 2013
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
88be504
doctrine getRepository now knows its entities and supports autocomple…
Haehnchen dd46f64
dont add Repository and abstract entities to doctrine autocomplete
Haehnchen a6fbfe1
repository classes are used as return types for getRepository, if the…
Haehnchen 059b0c1
find and findOneBy returns the entity
Haehnchen 60ed439
get available entitynamespaces directly from compiled container xml f…
Haehnchen 24ed394
Merge branch 'forked_master' into feature/doctrine-support
Haehnchen b42231a
use new Symfony2InterfacesUtil, which can check for interface, too. n…
Haehnchen a9f63cc
adding support for doctrine findAll and findBy
Haehnchen 8bb6f31
cleaning up Repository calls to use only the interface, revert adding…
Haehnchen 11d3af2
allow entities equals Repository
Haehnchen ca2b58f
renaming of doctrine EntityNamesParserTest to reflection file structure
Haehnchen f00493e
using xpath to find all setEntityNamespaces calls and allow ObjectMan…
Haehnchen 4117de1
Merge branch 'forked_master' into feature/doctrine-support
Haehnchen dec9b34
using isInstanceOf to check of Repository classes
Haehnchen 0ba8adc
Merge branch 'forked_master' into feature/doctrine-support
Haehnchen 846f5f2
using doctrine icons for entity lookups
Haehnchen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
src/fr/adrienbrault/idea/symfony2plugin/doctrine/DoctrineEntityReferenceContributor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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.Symfony2InterfacesUtil; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| /** | ||
| * @author Daniel Espendiller <daniel@espendiller.net> | ||
| */ | ||
| 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(); | ||
| Symfony2InterfacesUtil interfacesUtil = new Symfony2InterfacesUtil(); | ||
| if (!interfacesUtil.isGetRepositoryCall(method)) { | ||
| return new PsiReference[0]; | ||
| } | ||
|
|
||
| return new PsiReference[]{ new EntityReference((StringLiteralExpression) psiElement) }; | ||
| } | ||
| } | ||
| ); | ||
| } | ||
|
|
||
| } |
67 changes: 67 additions & 0 deletions
67
src/fr/adrienbrault/idea/symfony2plugin/doctrine/EntityHelper.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| 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 fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent; | ||
|
|
||
| import java.util.Collection; | ||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * @author Daniel Espendiller <daniel@espendiller.net> | ||
| */ | ||
| 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) { | ||
|
|
||
| if(shortcutName == null) { | ||
| return null; | ||
| } | ||
|
|
||
| String entity_name = shortcutName; | ||
|
|
||
| // resolve: | ||
| // MyBundle:Model -> MyBundle\Entity\Model | ||
| // MyBundle:Folder\Model -> MyBundle\Entity\Folder\Model | ||
| if (shortcutName.contains(":")) { | ||
|
|
||
| Symfony2ProjectComponent symfony2ProjectComponent = project.getComponent(Symfony2ProjectComponent.class); | ||
| Map<String, String> em = symfony2ProjectComponent.getEntityNamespacesMap(); | ||
|
|
||
| int firstDirectorySeparatorIndex = shortcutName.indexOf(":"); | ||
|
|
||
| String bundlename = shortcutName.substring(0, firstDirectorySeparatorIndex); | ||
| String entityName = shortcutName.substring(firstDirectorySeparatorIndex + 1); | ||
|
|
||
| String namespace = em.get(bundlename); | ||
|
|
||
| if(namespace == null) { | ||
| return null; | ||
| } | ||
|
|
||
| entity_name = namespace + "\\" + entityName; | ||
| } | ||
|
|
||
| // only use them on entity namespace | ||
| if(!entity_name.contains("\\")) { | ||
| return null; | ||
| } | ||
|
|
||
| // dont we have any unique class getting method here? | ||
| PhpIndex phpIndex = PhpIndex.getInstance(project); | ||
| Collection<PhpClass> entity_classes = phpIndex.getClassesByFQN(entity_name); | ||
| if(!entity_classes.isEmpty()){ | ||
| return entity_classes.iterator().next(); | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| } |
109 changes: 109 additions & 0 deletions
109
src/fr/adrienbrault/idea/symfony2plugin/doctrine/EntityReference.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| 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.*; | ||
| import fr.adrienbrault.idea.symfony2plugin.Symfony2InterfacesUtil; | ||
| import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent; | ||
| import fr.adrienbrault.idea.symfony2plugin.doctrine.dict.DoctrineEntityLookupElement; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.jetbrains.annotations.Nullable; | ||
|
|
||
| import java.util.*; | ||
|
|
||
| /** | ||
| * @author Daniel Espendiller <daniel@espendiller.net> | ||
| */ | ||
| public class EntityReference extends PsiReferenceBase<PsiElement> 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()); | ||
|
|
||
| Symfony2ProjectComponent symfony2ProjectComponent = getElement().getProject().getComponent(Symfony2ProjectComponent.class); | ||
| Map<String, String> entityNamespaces = symfony2ProjectComponent.getEntityNamespacesMap(); | ||
|
|
||
| List<LookupElement> results = new ArrayList<LookupElement>(); | ||
|
|
||
| // find Repository interface to filter RepositoryClasses out | ||
| PhpClass repositoryClass = getRepositoryClass(phpIndex); | ||
| if(null == repositoryClass) { | ||
| return results.toArray(); | ||
| } | ||
|
|
||
| for (Map.Entry<String, String> entry : entityNamespaces.entrySet()) { | ||
|
|
||
| // search for classes that match the symfony2 namings | ||
| Collection<PhpNamespace> entities = phpIndex.getNamespacesByName(entry.getValue()); | ||
|
|
||
| // @TODO: it looks like PhpIndex cant search for classes like \ns\Path\*\... | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replacing |
||
| // temporary only use flat entities and dont support "MyBundle:Folder\Entity" | ||
| for (PhpNamespace entity_files : entities) { | ||
|
|
||
| // build our symfony2 shortcut | ||
| String filename = entity_files.getContainingFile().getName(); | ||
| String className = filename.substring(0, filename.lastIndexOf('.')); | ||
| String repoName = entry.getKey() + ':' + className; | ||
|
|
||
| // dont add Repository classes and abstract entities | ||
| PhpClass entityClass = getClass(phpIndex, entityNamespaces.get(entry.getKey()) + "\\" + className); | ||
| if(null != entityClass && isEntity(entityClass, repositoryClass)) { | ||
| results.add(new DoctrineEntityLookupElement(repoName, entityClass)); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| return results.toArray(); | ||
| } | ||
|
|
||
| @Nullable | ||
| protected PhpClass getRepositoryClass(PhpIndex phpIndex) { | ||
| Collection<PhpClass> classes = phpIndex.getInterfacesByFQN("\\Doctrine\\Common\\Persistence\\ObjectRepository"); | ||
| return classes.isEmpty() ? null : classes.iterator().next(); | ||
| } | ||
|
|
||
| @Nullable | ||
| protected PhpClass getClass(PhpIndex phpIndex, String className) { | ||
| Collection<PhpClass> classes = phpIndex.getClassesByFQN(className); | ||
| return classes.isEmpty() ? null : classes.iterator().next(); | ||
| } | ||
|
|
||
| protected boolean isEntity(PhpClass entityClass, PhpClass repositoryClass) { | ||
|
|
||
| if(entityClass.isAbstract()) { | ||
| return false; | ||
| } | ||
|
|
||
| Symfony2InterfacesUtil symfony2Util = new Symfony2InterfacesUtil(); | ||
| return !symfony2Util.isInstanceOf(entityClass, repositoryClass); | ||
| } | ||
|
|
||
| } | ||
61 changes: 61 additions & 0 deletions
61
src/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package fr.adrienbrault.idea.symfony2plugin.doctrine; | ||
|
|
||
| import com.intellij.openapi.project.DumbService; | ||
| import com.intellij.psi.PsiElement; | ||
| import com.jetbrains.php.lang.psi.elements.MethodReference; | ||
| import com.jetbrains.php.lang.psi.elements.PhpClass; | ||
| import com.jetbrains.php.lang.psi.resolve.types.PhpType; | ||
| import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider; | ||
| import fr.adrienbrault.idea.symfony2plugin.Symfony2InterfacesUtil; | ||
| import org.jetbrains.annotations.Nullable; | ||
|
|
||
| /** | ||
| * @author Daniel Espendiller <daniel@espendiller.net> | ||
| */ | ||
| public class ObjectRepositoryResultTypeProvider implements PhpTypeProvider { | ||
|
|
||
| @Nullable | ||
| @Override | ||
| public PhpType getType(PsiElement e) { | ||
| if (DumbService.getInstance(e.getProject()).isDumb()) { | ||
| return null; | ||
| } | ||
|
|
||
| Symfony2InterfacesUtil interfacesUtil = new Symfony2InterfacesUtil(); | ||
| if (!interfacesUtil.isObjectRepositoryCall(e)) { | ||
| return null; | ||
| } | ||
|
|
||
| MethodReference met = (MethodReference) e; | ||
| String methodName = met.getName(); | ||
|
|
||
| // at least one parameter is necessary on some finds | ||
| if(null != methodName && !methodName.equals("findAll")) { | ||
| PsiElement[] parameters = met.getParameters(); | ||
| if(parameters.length == 0) { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| // @TODO: find the previously defined type instead of try it on the parameter, we now can rely on it! | ||
| // find the called repository name on method before | ||
| if(!(met.getFirstChild() instanceof MethodReference)) { | ||
| return null; | ||
| } | ||
|
|
||
| String repositoryName = Symfony2InterfacesUtil.getFirstArgumentStringValue((MethodReference) met.getFirstChild()); | ||
| PhpClass phpClass = EntityHelper.resolveShortcutName(e.getProject(), repositoryName); | ||
|
|
||
| if(phpClass == null) { | ||
| return null; | ||
| } | ||
|
|
||
|
|
||
| if(null != methodName && (methodName.equals("findAll") || methodName.equals("findBy"))) { | ||
| return new PhpType().add(phpClass.getFQN() + "[]"); | ||
| } | ||
|
|
||
| return new PhpType().add(phpClass); | ||
| } | ||
|
|
||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should also support
\\Doctrine\\Common\\Persistence\\ObjectManager::getRepositoryfor people getting the repository from the EntityManager