3333 *
3434 * @author Mathias Arlaud <mathias.arlaud@gmail.com>
3535 * @author Baptiste Leduc <baptiste.leduc@gmail.com>
36+ * @author Pierre-Yves Landuré <landure@gmail.com>
3637 */
3738final class TypeContextFactory
3839{
@@ -41,6 +42,16 @@ final class TypeContextFactory
4142 */
4243 private static array $ reflectionClassCache = [];
4344
45+ /**
46+ * @var array<string,array<string,TypeContext>
47+ */
48+ private array $ intermediateTypeContextCache = [];
49+
50+ /**
51+ * @var array<string,array<string,TypeContext>
52+ */
53+ private array $ typeContextCache = [];
54+
4455 private ?Lexer $ phpstanLexer = null ;
4556 private ?PhpDocParser $ phpstanParser = null ;
4657
@@ -53,26 +64,9 @@ public function createFromClassName(string $calledClassName, ?string $declaringC
5364 {
5465 $ declaringClassName ??= $ calledClassName ;
5566
56- $ calledClassPath = explode ('\\' , $ calledClassName );
57- $ declaringClassPath = explode ('\\' , $ declaringClassName );
58-
59- $ declaringClassReflection = self ::$ reflectionClassCache [$ declaringClassName ] ??= new \ReflectionClass ($ declaringClassName );
67+ $ this ->typeContextCache [$ declaringClassName ][$ calledClassName ] ??= $ this ->createNewInstanceFromClassName ($ calledClassName , $ declaringClassName );
6068
61- $ typeContext = new TypeContext (
62- end ($ calledClassPath ),
63- end ($ declaringClassPath ),
64- trim ($ declaringClassReflection ->getNamespaceName (), '\\' ),
65- $ this ->collectUses ($ declaringClassReflection ),
66- );
67-
68- return new TypeContext (
69- $ typeContext ->calledClassName ,
70- $ typeContext ->declaringClassName ,
71- $ typeContext ->namespace ,
72- $ typeContext ->uses ,
73- $ this ->collectTemplates ($ declaringClassReflection , $ typeContext ),
74- $ this ->collectTypeAliases ($ declaringClassReflection , $ typeContext ),
75- );
69+ return $ this ->typeContextCache [$ declaringClassName ][$ calledClassName ];
7670 }
7771
7872 public function createFromReflection (\Reflector $ reflection ): ?TypeContext
@@ -90,12 +84,7 @@ public function createFromReflection(\Reflector $reflection): ?TypeContext
9084 return null ;
9185 }
9286
93- $ typeContext = new TypeContext (
94- $ declaringClassReflection ->getShortName (),
95- $ declaringClassReflection ->getShortName (),
96- $ declaringClassReflection ->getNamespaceName (),
97- $ this ->collectUses ($ declaringClassReflection ),
98- );
87+ $ typeContext = $ this ->createIntermediateTypeContext ($ declaringClassReflection ->getShortName (), $ declaringClassReflection );
9988
10089 $ templates = match (true ) {
10190 $ reflection instanceof \ReflectionFunctionAbstract => $ this ->collectTemplates ($ reflection , $ typeContext ) + $ this ->collectTemplates ($ declaringClassReflection , $ typeContext ),
@@ -113,6 +102,39 @@ public function createFromReflection(\Reflector $reflection): ?TypeContext
113102 );
114103 }
115104
105+ private function createNewInstanceFromClassName (string $ calledClassName , string $ declaringClassName ): TypeContext
106+ {
107+ $ calledClassPath = explode ('\\' , $ calledClassName );
108+ $ declaringClassPath = explode ('\\' , $ declaringClassName );
109+
110+ $ declaringClassReflection = self ::$ reflectionClassCache [$ declaringClassName ] ??= new \ReflectionClass ($ declaringClassName );
111+
112+ $ typeContext = $ this ->createIntermediateTypeContext (end ($ calledClassPath ), $ declaringClassReflection );
113+
114+ return new TypeContext (
115+ $ typeContext ->calledClassName ,
116+ $ typeContext ->declaringClassName ,
117+ $ typeContext ->namespace ,
118+ $ typeContext ->uses ,
119+ $ this ->collectTemplates ($ declaringClassReflection , $ typeContext ),
120+ $ this ->collectTypeAliases ($ declaringClassReflection , $ typeContext ),
121+ );
122+ }
123+
124+ private function createIntermediateTypeContext (string $ calledClassShortName , \ReflectionClass $ declaringClassReflection ): TypeContext
125+ {
126+ $ declaringClassName = $ declaringClassReflection ->getName ();
127+
128+ self ::$ intermediateTypeContextCache [$ declaringClassName ][$ calledClassShortName ] ??= new TypeContext (
129+ $ calledClassShortName ,
130+ $ declaringClassReflection ->getShortName (),
131+ trim ($ declaringClassReflection ->getNamespaceName (), '\\' ),
132+ $ this ->collectUses ($ declaringClassReflection ),
133+ );
134+
135+ return self ::$ intermediateTypeContextCache [$ declaringClassName ][$ calledClassShortName ];
136+ }
137+
116138 /**
117139 * @return array<string, string>
118140 */
0 commit comments