88use PhpParser \Node \Stmt \Declare_ ;
99use PhpParser \Node \Stmt \Namespace_ ;
1010use PHPStan \Analyser \NodeScopeResolver ;
11+ use PHPStan \Analyser \OutOfClassScope ;
1112use PHPStan \Analyser \ScopeContext ;
1213use PHPStan \Analyser \ScopeFactory ;
1314use PHPStan \BetterReflection \Reflection \Adapter \ReflectionMethod ;
2122use PHPStan \Reflection \Annotations \AnnotationsPropertiesClassReflectionExtension ;
2223use PHPStan \Reflection \Assertions ;
2324use PHPStan \Reflection \AttributeReflectionFactory ;
25+ use PHPStan \Reflection \ClassMemberAccessAnswerer ;
2426use PHPStan \Reflection \ClassReflection ;
2527use PHPStan \Reflection \Deprecation \DeprecationProvider ;
2628use PHPStan \Reflection \ExtendedFunctionVariant ;
@@ -155,19 +157,23 @@ public function hasProperty(ClassReflection $classReflection, string $propertyNa
155157 return $ classReflection ->getNativeReflection ()->hasProperty ($ propertyName );
156158 }
157159
158- public function getProperty (ClassReflection $ classReflection , string $ propertyName ): PhpPropertyReflection
160+ public function getProperty (ClassReflection $ classReflection , string $ propertyName, ClassMemberAccessAnswerer $ scope ): PhpPropertyReflection
159161 {
160- if (!isset ($ this ->propertiesIncludingAnnotations [$ classReflection ->getCacheKey ()][$ propertyName ])) {
161- $ this ->propertiesIncludingAnnotations [$ classReflection ->getCacheKey ()][$ propertyName ] = $ this ->createProperty ($ classReflection , $ propertyName , true );
162+ $ cacheKey = $ classReflection ->getCacheKey ();
163+ if ($ scope ->isInClass ()) {
164+ $ cacheKey = sprintf ('%s-%s ' , $ cacheKey , $ scope ->getClassReflection ()->getCacheKey ());
165+ }
166+ if (!isset ($ this ->propertiesIncludingAnnotations [$ cacheKey ][$ propertyName ])) {
167+ $ this ->propertiesIncludingAnnotations [$ cacheKey ][$ propertyName ] = $ this ->createProperty ($ classReflection , $ propertyName , $ scope , true );
162168 }
163169
164- return $ this ->propertiesIncludingAnnotations [$ classReflection -> getCacheKey () ][$ propertyName ];
170+ return $ this ->propertiesIncludingAnnotations [$ cacheKey ][$ propertyName ];
165171 }
166172
167173 public function getNativeProperty (ClassReflection $ classReflection , string $ propertyName ): PhpPropertyReflection
168174 {
169175 if (!isset ($ this ->nativeProperties [$ classReflection ->getCacheKey ()][$ propertyName ])) {
170- $ property = $ this ->createProperty ($ classReflection , $ propertyName , false );
176+ $ property = $ this ->createProperty ($ classReflection , $ propertyName , new OutOfClassScope (), false );
171177 $ this ->nativeProperties [$ classReflection ->getCacheKey ()][$ propertyName ] = $ property ;
172178 }
173179
@@ -177,6 +183,7 @@ public function getNativeProperty(ClassReflection $classReflection, string $prop
177183 private function createProperty (
178184 ClassReflection $ classReflection ,
179185 string $ propertyName ,
186+ ClassMemberAccessAnswerer $ scope ,
180187 bool $ includingAnnotations ,
181188 ): PhpPropertyReflection
182189 {
@@ -213,7 +220,7 @@ private function createProperty(
213220 $ types [] = $ value ;
214221 }
215222
216- return new PhpPropertyReflection ($ declaringClassReflection , null , null , TypeCombinator::union (...$ types ), $ classReflection ->getNativeReflection ()->getProperty ($ propertyName ), null , null , null , false , false , false , false , [], false , true , false );
223+ return new PhpPropertyReflection ($ declaringClassReflection , null , null , TypeCombinator::union (...$ types ), $ classReflection ->getNativeReflection ()->getProperty ($ propertyName ), null , null , null , false , false , false , false , [], false , true , false , false , true );
217224 }
218225 }
219226
@@ -393,12 +400,34 @@ private function createProperty(
393400 }
394401 }
395402
403+ $ nativeProperty = new PhpPropertyReflection (
404+ $ declaringClassReflection ,
405+ $ declaringTrait ,
406+ $ nativeType ,
407+ $ phpDocType ,
408+ $ propertyReflection ,
409+ $ getHook ,
410+ $ setHook ,
411+ $ deprecatedDescription ,
412+ $ isDeprecated ,
413+ $ isInternal ,
414+ $ isReadOnlyByPhpDoc ,
415+ $ isAllowedPrivateMutation ,
416+ $ this ->attributeReflectionFactory ->fromNativeReflection ($ propertyReflection ->getAttributes (), InitializerExprContext::fromClass ($ declaringClassReflection ->getName (), $ declaringClassReflection ->getFileName ())),
417+ $ isFinal ,
418+ true ,
419+ true ,
420+ $ propertyReflection ->isPrivate (),
421+ $ propertyReflection ->isPublic (),
422+ );
423+
396424 if (
397425 $ includingAnnotations
398426 && !$ declaringClassReflection ->isEnum ()
399427 && !$ propertyReflection ->isStatic ()
400428 && ($ classReflection ->allowsDynamicProperties () || !$ propertyReflection ->isPrivate ())
401429 && $ this ->annotationsPropertiesClassReflectionExtension ->hasProperty ($ classReflection , $ propertyName )
430+ && (!$ scope ->canReadProperty ($ nativeProperty ) || $ nativeProperty ->isPublic ())
402431 ) {
403432 $ hierarchyDistances = $ classReflection ->getClassHierarchyDistances ();
404433 $ annotationProperty = $ this ->annotationsPropertiesClassReflectionExtension ->getProperty ($ classReflection , $ propertyName );
@@ -415,7 +444,9 @@ private function createProperty(
415444 throw new ShouldNotHappenException ();
416445 }
417446
418- if ($ hierarchyDistances [$ annotationProperty ->getDeclaringClass ()->getName ()] <= $ hierarchyDistances [$ distanceDeclaringClass ]) {
447+ if (
448+ $ hierarchyDistances [$ annotationProperty ->getDeclaringClass ()->getName ()] <= $ hierarchyDistances [$ distanceDeclaringClass ]
449+ ) {
419450 return new PhpPropertyReflection (
420451 $ annotationProperty ->getDeclaringClass (),
421452 $ declaringTrait ,
@@ -433,28 +464,13 @@ private function createProperty(
433464 $ isFinal ,
434465 $ annotationProperty ->isReadable (),
435466 $ annotationProperty ->isWritable (),
467+ false ,
468+ true ,
436469 );
437470 }
438471 }
439472
440- return new PhpPropertyReflection (
441- $ declaringClassReflection ,
442- $ declaringTrait ,
443- $ nativeType ,
444- $ phpDocType ,
445- $ propertyReflection ,
446- $ getHook ,
447- $ setHook ,
448- $ deprecatedDescription ,
449- $ isDeprecated ,
450- $ isInternal ,
451- $ isReadOnlyByPhpDoc ,
452- $ isAllowedPrivateMutation ,
453- $ this ->attributeReflectionFactory ->fromNativeReflection ($ propertyReflection ->getAttributes (), InitializerExprContext::fromClass ($ declaringClassReflection ->getName (), $ declaringClassReflection ->getFileName ())),
454- $ isFinal ,
455- true ,
456- true ,
457- );
473+ return $ nativeProperty ;
458474 }
459475
460476 public function hasMethod (ClassReflection $ classReflection , string $ methodName ): bool
0 commit comments