Phan\Parse\ParseVisitor::visitPropDecl PHP Method

visitPropDecl() public method

Visit a node with kind \ast\AST_PROP_DECL
public visitPropDecl ( ast\Node $node ) : Context
$node ast\Node A node to parse
return Phan\Language\Context A new or an unchanged context resulting from parsing the node
    public function visitPropDecl(Node $node) : Context
    {
        // Bomb out if we're not in a class context
        $class = $this->getContextClass();
        // Get a comment on the property declaration
        $comment = Comment::fromStringInContext($node->children[0]->docComment ?? '', $this->context);
        foreach ($node->children ?? [] as $i => $child_node) {
            // Ignore children which are not property elements
            if (!$child_node || $child_node->kind != \ast\AST_PROP_ELEM) {
                continue;
            }
            // If something goes wrong will getting the type of
            // a property, we'll store it as a future union
            // type and try to figure it out later
            $future_union_type = null;
            try {
                // Get the type of the default
                $union_type = UnionType::fromNode($this->context, $this->code_base, $child_node->children['default'], false);
            } catch (IssueException $exception) {
                $future_union_type = new FutureUnionType($this->code_base, $this->context, $child_node->children['default']);
                $union_type = new UnionType();
            }
            // Don't set 'null' as the type if thats the default
            // given that its the default default.
            if ($union_type->isType(NullType::instance())) {
                $union_type = new UnionType();
            }
            $property_name = $child_node->children['name'];
            assert(is_string($property_name), 'Property name must be a string. ' . 'Got ' . print_r($property_name, true) . ' at ' . $this->context);
            $property_name = is_string($child_node->children['name']) ? $child_node->children['name'] : '_error_';
            $property_fqsen = FullyQualifiedPropertyName::make($class->getFQSEN(), $property_name);
            $property = new Property(clone $this->context->withLineNumberStart($child_node->lineno ?? 0), $property_name, $union_type, $node->flags ?? 0, $property_fqsen);
            // Add the property to the class
            $class->addProperty($this->code_base, $property, new None());
            $property->setSuppressIssueList($comment->getSuppressIssueList());
            // Look for any @var declarations
            if ($variable = $comment->getVariableList()[$i] ?? null) {
                if ((string) $union_type != 'null' && !$union_type->canCastToUnionType($variable->getUnionType())) {
                    $this->emitIssue(Issue::TypeMismatchProperty, $child_node->lineno ?? 0, (string) $union_type, (string) $property->getFQSEN(), (string) $variable->getUnionType());
                }
                // Set the declared type to the doc-comment type and add
                // |null if the default value is null
                $property->getUnionType()->addUnionType($variable->getUnionType());
            }
            $property->setIsDeprecated($comment->isDeprecated());
            // Wait until after we've added the (at)var type
            // before setting the future so that calling
            // $property->getUnionType() doesn't force the
            // future to be reified.
            if ($future_union_type instanceof FutureUnionType) {
                $property->setFutureUnionType($future_union_type);
            }
        }
        return $this->context;
    }