2
2
3
3
import com .intellij .openapi .extensions .ExtensionPointName ;
4
4
import com .intellij .openapi .project .Project ;
5
+ import com .intellij .openapi .util .Key ;
5
6
import com .intellij .openapi .util .Pair ;
6
7
import com .intellij .openapi .vfs .VirtualFile ;
7
8
import com .intellij .psi .PsiElement ;
8
9
import com .intellij .psi .PsiFile ;
9
10
import com .intellij .psi .PsiManager ;
10
- import com .intellij .psi .util .PsiTreeUtil ;
11
+ import com .intellij .psi .util .* ;
11
12
import com .intellij .psi .xml .XmlFile ;
12
13
import com .intellij .psi .xml .XmlTag ;
13
14
import com .intellij .util .Function ;
@@ -45,6 +46,8 @@ public class EntityHelper {
45
46
46
47
public static final ExtensionPointName <DoctrineModelProvider > MODEL_POINT_NAME = new ExtensionPointName <>("fr.adrienbrault.idea.symfony2plugin.extension.DoctrineModelProvider" );
47
48
49
+ private static final Key <CachedValue <Collection <DoctrineModelCached >>> SYMFONY_DOCTRINE_MODEL_CACHE = new Key <>("SYMFONY_DOCTRINE_MODEL_CACHE" );
50
+
48
51
final public static String [] ANNOTATION_FIELDS = new String [] {
49
52
"\\ Doctrine\\ ORM\\ Mapping\\ Column" ,
50
53
"\\ Doctrine\\ ORM\\ Mapping\\ OneToOne" ,
@@ -693,11 +696,10 @@ public static void attachAnnotationInformation(@NotNull PhpClass phpClass, @NotN
693
696
694
697
}
695
698
696
- /**
697
- * One PhpClass can have multiple targets and names @TODO: refactor
698
- */
699
- public static Collection <DoctrineModel > getModelClasses (final Project project ) {
699
+ private record DoctrineModelCached (@ NotNull String phpClass , @ Nullable String doctrineShortcut , @ Nullable String doctrineNamespace ) {
700
+ }
700
701
702
+ private static Collection <DoctrineModelCached > getModelClassesInner (final Project project ) {
701
703
HashMap <String , String > shortcutNames = new HashMap <>() {{
702
704
putAll (ServiceXmlParserFactory .getInstance (project , EntityNamesServiceParser .class ).getEntityNameMap ());
703
705
putAll (ServiceXmlParserFactory .getInstance (project , DocumentNamespacesParser .class ).getNamespaceMap ());
@@ -715,7 +717,7 @@ public static Collection<DoctrineModel> getModelClasses(final Project project) {
715
717
// class fqn fallback
716
718
Collection <DoctrineModel > doctrineModels = getModelClasses (project , shortcutNames );
717
719
for (PhpClass phpClass : DoctrineMetadataUtil .getModels (project )) {
718
- if (containsDoctrineModelClass (doctrineModels , phpClass )) {
720
+ if (containsDoctrineModelClass (doctrineModels , phpClass )) {
719
721
continue ;
720
722
}
721
723
@@ -729,6 +731,40 @@ public static Collection<DoctrineModel> getModelClasses(final Project project) {
729
731
}
730
732
}
731
733
734
+ return doctrineModels .stream ().map (
735
+ doctrineModel -> new DoctrineModelCached (doctrineModel .getPhpClass ().getFQN (), doctrineModel .getDoctrineShortcut (), doctrineModel .getDoctrineNamespace ())
736
+ ).toList ();
737
+ }
738
+
739
+ /**
740
+ * One PhpClass can have multiple targets and names @TODO: refactor
741
+ */
742
+ public static Collection <DoctrineModel > getModelClasses (@ NotNull final Project project ) {
743
+ Collection <DoctrineModelCached > modelClasses = CachedValuesManager .getManager (project ).getCachedValue (
744
+ project ,
745
+ SYMFONY_DOCTRINE_MODEL_CACHE ,
746
+ () -> CachedValueProvider .Result .create (getModelClassesInner (project ), PsiModificationTracker .MODIFICATION_COUNT ),
747
+ false
748
+ );
749
+
750
+ PhpIndex phpIndex = PhpIndex .getInstance (project );
751
+ Collection <DoctrineModel > doctrineModels = new ArrayList <>();
752
+ for (DoctrineModelCached doctrineModelCached : modelClasses ) {
753
+ Collection <PhpClass > classesByFQN = phpIndex .getClassesByFQN (doctrineModelCached .phpClass );
754
+ if (classesByFQN .isEmpty ()) {
755
+ continue ;
756
+ }
757
+
758
+ doctrineModels .add (new DoctrineModel (classesByFQN .iterator ().next (), doctrineModelCached .doctrineShortcut , doctrineModelCached .doctrineNamespace ));
759
+ }
760
+
761
+ DoctrineModelProviderParameter containerLoaderExtensionParameter = new DoctrineModelProviderParameter (project , new ArrayList <>());
762
+ for (DoctrineModelProvider provider : EntityHelper .MODEL_POINT_NAME .getExtensions ()) {
763
+ for (DoctrineModelProviderParameter .DoctrineModel doctrineModel : provider .collectModels (containerLoaderExtensionParameter )) {
764
+ doctrineModels .add (new DoctrineModel (doctrineModel .getPhpClass (), doctrineModel .getName ()));
765
+ }
766
+ }
767
+
732
768
return doctrineModels ;
733
769
}
734
770
@@ -742,18 +778,17 @@ private static boolean containsDoctrineModelClass(@NotNull Collection<DoctrineMo
742
778
return false ;
743
779
}
744
780
745
- public static Collection <DoctrineModel > getModelClasses (Project project , Map <String , String > shortcutNames ) {
746
-
781
+ public static Collection <DoctrineModel > getModelClasses (@ NotNull Project project , @ NotNull Map <String , String > shortcutNames ) {
747
782
PhpClass repositoryInterface = PhpElementsUtil .getInterface (PhpIndex .getInstance (project ), DoctrineTypes .REPOSITORY_INTERFACE );
748
783
749
- if (repositoryInterface == null ) {
784
+ if (repositoryInterface == null ) {
750
785
repositoryInterface = PhpElementsUtil .getInterface (PhpIndex .getInstance (project ), "\\ Doctrine\\ Persistence\\ ObjectRepository" );
751
786
}
752
787
753
788
Collection <DoctrineModel > models = new ArrayList <>();
754
789
for (Map .Entry <String , String > entry : shortcutNames .entrySet ()) {
755
- for (PhpClass phpClass : PhpIndexUtil .getPhpClassInsideNamespace (project , entry .getValue ())) {
756
- if (repositoryInterface != null && !isEntity (phpClass , repositoryInterface )) {
790
+ for (PhpClass phpClass : PhpIndexUtil .getPhpClassInsideNamespace (project , entry .getValue (), true )) {
791
+ if (repositoryInterface != null && !isEntity (phpClass , repositoryInterface )) {
757
792
continue ;
758
793
}
759
794
0 commit comments