getStdClassFQSEN() public static method

public static getStdClassFQSEN ( ) : FullyQualifiedClassName
return FullyQualifiedClassName The FQSEN for \stdClass.
Example #1
0
File: Clazz.php Project: etsy/phan
 /**
  * @param string $name
  * The name of the property
  *
  * @param Context $context
  * The context of the caller requesting the property
  *
  * @return Property
  * A property with the given name
  *
  * @throws IssueException
  * An exception may be thrown if the caller does not
  * have access to the given property from the given
  * context
  */
 public function getPropertyByNameInContext(CodeBase $code_base, string $name, Context $context) : Property
 {
     // Get the FQSEN of the property we're looking for
     $property_fqsen = FullyQualifiedPropertyName::make($this->getFQSEN(), $name);
     $property = null;
     // Figure out if we have the property
     $has_property = $code_base->hasPropertyWithFQSEN($property_fqsen);
     // Figure out if the property is accessible
     $is_property_accessible = false;
     if ($has_property) {
         $property = $code_base->getPropertyByFQSEN($property_fqsen);
         $is_remote_access = !$context->isInClassScope() || !$context->getClassInScope($code_base)->getUnionType()->canCastToExpandedUnionType($this->getUnionType(), $code_base);
         $is_property_accessible = !$is_remote_access || $property->isPublic();
     }
     // If the property exists and is accessible, return it
     if ($is_property_accessible) {
         return $property;
     }
     // Check to see if we can use a __get magic method
     if ($this->hasMethodWithName($code_base, '__get')) {
         $method = $this->getMethodByName($code_base, '__get');
         // Make sure the magic method is accessible
         if ($method->isPrivate()) {
             throw new IssueException(Issue::fromType(Issue::AccessPropertyPrivate)($context->getFile(), $context->getLineNumberStart(), [(string) $property_fqsen]));
         } else {
             if ($method->isProtected()) {
                 throw new IssueException(Issue::fromType(Issue::AccessPropertyProtected)($context->getFile(), $context->getLineNumberStart(), [(string) $property_fqsen]));
             }
         }
         $property = new Property($context, $name, $method->getUnionType(), 0, $property_fqsen);
         $this->addProperty($code_base, $property, new None());
         return $property;
     } else {
         if ($has_property) {
             // If we have a property, but its inaccessible, emit
             // an issue
             if ($property->isPrivate()) {
                 throw new IssueException(Issue::fromType(Issue::AccessPropertyPrivate)($context->getFile(), $context->getLineNumberStart(), ["{$this->getFQSEN()}::\${$property->getName()}"]));
             }
             if ($property->isProtected()) {
                 throw new IssueException(Issue::fromType(Issue::AccessPropertyProtected)($context->getFile(), $context->getLineNumberStart(), ["{$this->getFQSEN()}::\${$property->getName()}"]));
             }
         }
     }
     // Check to see if missing properties are allowed
     // or we're stdclass
     if (Config::get()->allow_missing_properties || $this->getFQSEN() == FullyQualifiedClassName::getStdClassFQSEN()) {
         $property = new Property($context, $name, new UnionType(), 0, $property_fqsen);
         $this->addProperty($code_base, $property, new None());
         return $property;
     }
     throw new IssueException(Issue::fromType(Issue::UndeclaredProperty)($context->getFile(), $context->getLineNumberStart(), ["{$this->getFQSEN()}::\${$name}}"]));
 }
Example #2
0
 /**
  * @param Node $node
  * A node to parse
  *
  * @return Context
  * A new or an unchanged context resulting from
  * parsing the node
  */
 public function visitProp(Node $node) : Context
 {
     $property_name = $node->children['prop'];
     // Things like $foo->$bar
     if (!is_string($property_name)) {
         return $this->context;
     }
     assert(is_string($property_name), "Property must be string");
     try {
         $class_list = (new ContextNode($this->code_base, $this->context, $node->children['expr']))->getClassList();
     } catch (CodeBaseException $exception) {
         // This really shouldn't happen since the code
         // parsed cleanly. This should fatal.
         // throw $exception;
         return $this->context;
     } catch (\Exception $exception) {
         // If we can't figure out what kind of a class
         // this is, don't worry about it
         return $this->context;
     }
     foreach ($class_list as $clazz) {
         // Check to see if this class has the property or
         // a setter
         if (!$clazz->hasPropertyWithName($this->code_base, $property_name)) {
             if (!$clazz->hasMethodWithName($this->code_base, '__set')) {
                 continue;
             }
         }
         try {
             $property = $clazz->getPropertyByNameInContext($this->code_base, $property_name, $this->context);
         } catch (IssueException $exception) {
             Issue::maybeEmitInstance($this->code_base, $this->context, $exception->getIssueInstance());
             return $this->context;
         }
         if (!$this->right_type->canCastToExpandedUnionType($property->getUnionType(), $this->code_base)) {
             $this->emitIssue(Issue::TypeMismatchProperty, $node->lineno ?? 0, (string) $this->right_type, "{$clazz->getFQSEN()}::{$property->getName()}", (string) $property->getUnionType());
             return $this->context;
         } else {
             // If we're assigning to an array element then we don't
             // know what the constitutation of the parameter is
             // outside of the scope of this assignment, so we add to
             // its union type rather than replace it.
             if ($this->is_dim_assignment) {
                 $property->getUnionType()->addUnionType($this->right_type);
             }
         }
         // After having checked it, add this type to it
         $property->getUnionType()->addUnionType($this->right_type);
         return $this->context;
     }
     $std_class_fqsen = FullyQualifiedClassName::getStdClassFQSEN();
     if (Config::get()->allow_missing_properties || !empty($class_list) && $class_list[0]->getFQSEN() == $std_class_fqsen) {
         try {
             // Create the property
             $property = (new ContextNode($this->code_base, $this->context, $node))->getOrCreateProperty($property_name);
             $property->getUnionType()->addUnionType($this->right_type);
         } catch (\Exception $exception) {
             // swallow it
         }
     } elseif (!empty($class_list)) {
         $this->emitIssue(Issue::UndeclaredProperty, $node->lineno ?? 0, "{$class_list[0]->getFQSEN()}->{$property_name}");
     } else {
         // If we hit this part, we couldn't figure out
         // the class, so we ignore the issue
     }
     return $this->context;
 }
Example #3
0
 /**
  * @param string|Node $property_name
  * The name of the property we're looking up
  *
  * @return Property
  * A variable in scope or a new variable
  *
  * @throws NodeException
  * An exception is thrown if we can't understand the node
  *
  * @throws IssueException
  * An exception is thrown if we can't find the given
  * class or if we don't have access to the property (its
  * private or protected).
  *
  * @throws TypeException
  * An exception may be thrown if the only viable candidate
  * is a non-class type.
  *
  * @throws UnanalyzableException
  * An exception is thrown if we hit a construct in which
  * we can't determine if the property exists or not
  */
 public function getProperty($property_name) : Property
 {
     $property_name = $this->node->children['prop'];
     // Give up for things like C::$prop_name
     if (!is_string($property_name)) {
         throw new NodeException($this->node, "Cannot figure out non-string property name");
     }
     $class_fqsen = null;
     try {
         $class_list = (new ContextNode($this->code_base, $this->context, $this->node->children['expr'] ?? $this->node->children['class']))->getClassList(true);
     } catch (CodeBaseException $exception) {
         throw new IssueException(Issue::fromType(Issue::UndeclaredProperty)($this->context->getFile(), $this->node->lineno ?? 0, ["{$exception->getFQSEN()}->{$property_name}"]));
     }
     foreach ($class_list as $i => $class) {
         $class_fqsen = $class->getFQSEN();
         // Keep hunting if this class doesn't have the given
         // property
         if (!$class->hasPropertyWithName($this->code_base, $property_name)) {
             // If there's a getter on properties then all
             // bets are off.
             if ($class->hasGetMethod($this->code_base)) {
                 throw new UnanalyzableException($this->node, "Can't determine if property {$property_name} exists in class {$class->getFQSEN()} with __get defined");
             }
             continue;
         }
         $property = $class->getPropertyByNameInContext($this->code_base, $property_name, $this->context);
         if ($property->isDeprecated()) {
             throw new IssueException(Issue::fromType(Issue::DeprecatedProperty)($this->context->getFile(), $this->node->lineno ?? 0, [(string) $property->getFQSEN(), $property->getFileRef()->getFile(), $property->getFileRef()->getLineNumberStart()]));
         }
         return $property;
     }
     $std_class_fqsen = FullyQualifiedClassName::getStdClassFQSEN();
     // If missing properties are cool, create it on
     // the first class we found
     if ($class_fqsen && $class_fqsen === $std_class_fqsen || Config::get()->allow_missing_properties) {
         if (count($class_list) > 0) {
             $class = $class_list[0];
             return $class->getPropertyByNameInContext($this->code_base, $property_name, $this->context);
         }
     }
     // If the class isn't found, we'll get the message elsewhere
     if ($class_fqsen) {
         throw new IssueException(Issue::fromType(Issue::UndeclaredProperty)($this->context->getFile(), $this->node->lineno ?? 0, ["{$class_fqsen}->{$property_name}"]));
     }
     throw new NodeException($this->node, "Cannot figure out property from {$this->context}");
 }