Example #1
0
 /**
  * @return string
  * A unique and stable name for an anonymous class
  */
 public function getUnqualifiedNameForAnonymousClass() : string
 {
     assert((bool) ($this->node->flags & \ast\flags\CLASS_ANONYMOUS), "Node must be an anonymous class node");
     $class_name = 'anonymous_class_' . substr(md5(implode('|', [$this->context->getFile(), $this->context->getLineNumberStart()])), 0, 8);
     return $class_name;
 }
 public static function fromClosureInContext(Context $context) : FullyQualifiedFunctionName
 {
     $name = 'closure_' . substr(md5(implode('|', [$context->getFile(), $context->getLineNumberStart()])), 0, 12);
     return static::fromStringInContext($name, $context);
 }
Example #3
0
File: Plugin.php Project: etsy/phan
 /**
  * Emit an issue if it is not suppressed
  *
  * @param CodeBase $code_base
  * The code base in which the issue was found
  *
  * @param Context $context
  * The context in which the issue was found
  *
  * @param string $issue_type
  * A name for the type of issue such as 'PhanPluginMyIssue'
  *
  * @param string $issue_message
  * The complete issue message to emit such as 'class with
  * fqsen \NS\Name is broken in some fashion'.
  *
  * @param int $severity
  * A value from the set {Issue::SEVERITY_LOW,
  * Issue::SEVERITY_NORMAL, Issue::SEVERITY_HIGH}.
  *
  * @param int $remediation_difficulty
  * A guess at how hard the issue will be to fix from the
  * set {Issue:REMEDIATION_A, Issue:REMEDIATION_B, ...
  * Issue::REMEDIATION_F} with F being the hardest.
  */
 public function emitIssue(CodeBase $code_base, Context $context, string $issue_type, string $issue_message, int $severity = Issue::SEVERITY_NORMAL, int $remediation_difficulty = Issue::REMEDIATION_B, int $issue_type_id = Issue::TYPE_ID_UNKNOWN)
 {
     $issue = new Issue($issue_type, Issue::CATEGORY_PLUGIN, $severity, $issue_message, $remediation_difficulty, $issue_type_id);
     $issue_instance = new IssueInstance($issue, $context->getFile(), $context->getLineNumberStart(), []);
     Issue::maybeEmitInstance($code_base, $context, $issue_instance);
 }
Example #4
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 #5
0
 /**
  * @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
 {
     // Check to see if we have the property
     if (!$code_base->hasProperty($this->getFQSEN(), $name)) {
         // If we don't have the property but do have a
         // __get method, then we can create the property
         if ($this->hasMethodWithName($code_base, '__get')) {
             $property = new Property($context, $name, new UnionType(), 0);
             $property->setFQSEN(FullyQualifiedPropertyName::make($this->getFQSEN(), $name));
             $this->addProperty($code_base, $property);
         } else {
             throw new IssueException(Issue::fromType(Issue::UndeclaredProperty)($context->getFile(), $context->getLineNumberStart(), ["{$this->getFQSEN()}::\${$name}}"]));
         }
     }
     $property = $code_base->getProperty($this->getFQSEN(), $name);
     // If we're getting the property from outside of this
     // class and the property isn't public and we don't
     // have a getter or setter, emit an access error
     if ((!$context->hasClassFQSEN() || $context->getClassFQSEN() != $this->getFQSEN()) && !$property->isPublic() && !$this->hasMethodWithName($code_base, '__get') && !$this->hasMethodWithName($code_base, '__set')) {
         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()}"]));
         }
     }
     return $property;
 }
Example #6
0
 /**
  * @param CodeBase $code_base
  * The code base in which to find classes
  *
  * @param Context $context
  * The context in which we're resolving this union
  * type.
  *
  * @return Clazz[]
  * A list of classes representing the non-native types
  * associated with this UnionType
  *
  * @throws CodeBaseException
  * An exception is thrown if a non-native type does not have
  * an associated class
  */
 public function asClassList(CodeBase $code_base, Context $context)
 {
     // Iterate over each viable class type to see if any
     // have the constant we're looking for
     foreach ($this->nonNativeTypes()->getTypeSet() as $class_type) {
         // Get the class FQSEN
         $class_fqsen = $class_type->asFQSEN();
         if ($class_type->isStaticType()) {
             if (!$context->isInClassScope()) {
                 throw new IssueException(Issue::fromType(Issue::ContextNotObject)($context->getFile(), $context->getLineNumberStart(), [(string) $class_type]));
             }
             (yield $context->getClassInScope($code_base));
         } else {
             // See if the class exists
             if (!$code_base->hasClassWithFQSEN($class_fqsen)) {
                 throw new CodeBaseException($class_fqsen, "Cannot find class {$class_fqsen}");
             }
             (yield $code_base->getClassByFQSEN($class_fqsen));
         }
     }
 }