本文整理汇总了PHP中Phan\Language\Context::getClassInScope方法的典型用法代码示例。如果您正苦于以下问题:PHP Context::getClassInScope方法的具体用法?PHP Context::getClassInScope怎么用?PHP Context::getClassInScope使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Phan\Language\Context
的用法示例。
在下文中一共展示了Context::getClassInScope方法的8个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的PHP代码示例。
示例1: visitProp
/**
* @param Node $node
* A node of the type indicated by the method name that we'd
* like to figure out the type that it produces.
*
* @return string
* The class name represented by the given call
*/
public function visitProp(Node $node) : string
{
if (!($node->children['expr']->kind == \ast\AST_VAR && !$node->children['expr']->children['name'] instanceof Node)) {
return '';
}
// $var->prop->method()
$var = $node->children['expr'];
$class = null;
if ($var->children['name'] == 'this') {
// If we're not in a class scope, 'this' won't work
if (!$this->context->isInClassScope()) {
Log::err(Log::ESTATIC, 'Using $this when not in object context', $this->context->getFile(), $node->lineno);
return '';
}
// $this->$node->method()
if ($node->children['prop'] instanceof Node) {
// Too hard. Giving up.
return '';
}
$class = $this->context->getClassInScope($this->code_base);
} else {
// Get the list of viable class types for the
// variable
$union_type = AST::varUnionType($this->context, $var)->nonNativeTypes()->nonGenericArrayTypes();
if ($union_type->isEmpty()) {
return '';
}
$class_fqsen = $union_type->head()->asFQSEN();
if (!$this->code_base->hasClassWithFQSEN($class_fqsen)) {
return '';
}
$class = $this->code_base->getClassByFQSEN($class_fqsen);
}
$property_name = $node->children['prop'];
if (!$class->hasPropertyWithName($this->code_base, $property_name)) {
// If we can't find the property, there's
// no type. Thie issue should be caught
// elsewhere.
return '';
}
try {
$property = $class->getPropertyByNameInContext($this->code_base, $property_name, $this->context);
} catch (AccessException $exception) {
Log::err(Log::EACCESS, $exception->getMessage(), $this->context->getFile(), $node->lineno);
return '';
}
$union_type = $property->getUnionType()->nonNativeTypes();
if ($union_type->isEmpty()) {
// If we don't have a type on the property we
// can't figure out the class type.
return '';
} else {
// Return the first type on the property
// that could be a reference to a class
return (string) $union_type->head()->asFQSEN();
}
// No such property was found, or none were classes
// that could be found
return '';
}
示例2: visitReturn
/**
* @param Node $node
* A node to parse
*
* @return Context
* A new or an unchanged context resulting from
* parsing the node
*/
public function visitReturn(Node $node) : Context
{
// Don't check return types in traits
if ($this->context->isInClassScope()) {
$clazz = $this->context->getClassInScope($this->code_base);
if ($clazz->isTrait()) {
return $this->context;
}
}
// Make sure we're actually returning from a method.
if (!$this->context->isMethodScope() && !$this->context->isClosureScope()) {
return $this->context;
}
// Get the method/function/closure we're in
$method = null;
if ($this->context->isClosureScope()) {
$method = $this->context->getClosureInScope($this->code_base);
} else {
if ($this->context->isMethodScope()) {
$method = $this->context->getMethodInScope($this->code_base);
}
}
assert(!empty($method), "We're supposed to be in either method or closure scope.");
// Figure out what we intend to return
$method_return_type = $method->getUnionType();
// Figure out what is actually being returned
$expression_type = UnionType::fromNode($this->context, $this->code_base, $node->children['expr']);
// If there is no declared type, see if we can deduce
// what it should be based on the return type
if ($method_return_type->isEmpty() || $method->isReturnTypeUndefined()) {
$method->setIsReturnTypeUndefined(true);
// Set the inferred type of the method based
// on what we're returning
$method->getUnionType()->addUnionType($expression_type);
// No point in comparing this type to the
// type we just set
return $this->context;
}
if (!$method->isReturnTypeUndefined() && !$expression_type->canCastToExpandedUnionType($method_return_type, $this->code_base)) {
Issue::emit(Issue::TypeMismatchReturn, $this->context->getFile(), $node->lineno ?? 0, (string) $expression_type, $method->getName(), (string) $method_return_type);
}
if ($method->isReturnTypeUndefined()) {
// Add the new type to the set of values returned by the
// method
$method->getUnionType()->addUnionType($expression_type);
}
return $this->context;
}
示例3: visitClassNode
private function visitClassNode(Node $node) : UnionType
{
// Things of the form `new $class_name();`
if ($node->kind == \ast\AST_VAR) {
return new UnionType();
}
// Anonymous class of form `new class { ... }`
if ($node->kind == \ast\AST_CLASS && $node->flags & \ast\flags\CLASS_ANONYMOUS) {
// Generate a stable name for the anonymous class
$anonymous_class_name = (new ContextNode($this->code_base, $this->context, $node))->getUnqualifiedNameForAnonymousClass();
// Turn that into a fully qualified name
$fqsen = FullyQualifiedClassName::fromStringInContext($anonymous_class_name, $this->context);
// Turn that into a union type
return Type::fromFullyQualifiedString((string) $fqsen)->asUnionType();
}
// Things of the form `new $method->name()`
if ($node->kind !== \ast\AST_NAME) {
return new UnionType();
}
// Get the name of the class
$class_name = $node->children['name'];
// If this is a straight-forward class name, recurse into the
// class node and get its type
if (!Type::isSelfTypeString($class_name)) {
// TODO: does anyone else call this method?
return self::unionTypeFromClassNode($this->code_base, $this->context, $node);
}
// This is a self-referential node
if (!$this->context->isInClassScope()) {
Log::err(Log::ESTATIC, "Cannot access {$class_name} when not in a class scope", $this->context->getFile(), $node->lineno);
return new UnionType();
}
// Reference to a parent class
if ($class_name === 'parent') {
$class = $this->context->getClassInScope($this->code_base);
if (!$class->hasParentClassFQSEN()) {
Log::err(Log::ESTATIC, "Reference to parent of parentless class {$class->getFQSEN()}", $this->context->getFile(), $node->lineno);
return new UnionType();
}
return Type::fromFullyQualifiedString((string) $class->getParentClassFQSEN())->asUnionType();
}
return Type::fromFullyQualifiedString((string) $this->context->getClassFQSEN())->asUnionType();
}
示例4: visitReturn
/**
* @param Node $node
* A node to parse
*
* @return Context
* A new or an unchanged context resulting from
* parsing the node
*/
public function visitReturn(Node $node) : Context
{
// Don't check return types in traits
if ($this->context->isInClassScope()) {
$clazz = $this->context->getClassInScope($this->code_base);
if ($clazz->isTrait()) {
return $this->context;
}
}
// Make sure we're actually returning from a method.
if (!$this->context->isMethodScope() && !$this->context->isClosureScope()) {
return $this->context;
}
// Get the method/function/closure we're in
$method = null;
if ($this->context->isClosureScope()) {
$method = $this->context->getClosureInScope($this->code_base);
} else {
if ($this->context->isMethodScope()) {
$method = $this->context->getMethodInScope($this->code_base);
} else {
assert(false, "We're supposed to be in either method or closure scope.");
}
}
// Figure out what we intend to return
$method_return_type = $method->getUnionType();
// Figure out what is actually being returned
$expression_type = UnionType::fromNode($this->context, $this->code_base, $node->children['expr']);
// If there is no declared type, see if we can deduce
// what it should be based on the return type
if ($method_return_type->isEmpty()) {
// Set the inferred type of the method based
// on what we're returning
$method->getUnionType()->addUnionType($expression_type);
// No point in comparing this type to the
// type we just set
return $this->context;
}
if (!$expression_type->canCastToExpandedUnionType($method_return_type, $this->code_base)) {
Log::err(Log::ETYPE, "return {$expression_type} but {$method->getName()}() is declared to return {$method_return_type}", $this->context->getFile(), $node->lineno);
}
return $this->context;
}
示例5: visitNew
/**
* @param Node $node
* A node of the type indicated by the method name that we'd
* like to figure out the type that it produces.
*
* @return string
* The class name represented by the given call
*/
public function visitNew(Node $node) : string
{
// Things of the form `new $class_name();`
if ($node->children['class']->kind == \ast\AST_VAR) {
return '';
}
// Anonymous class
// $v = new class { ... }
if ($node->children['class']->kind == \ast\AST_CLASS && $node->children['class']->flags & \ast\flags\CLASS_ANONYMOUS) {
return AST::unqualifiedNameForAnonymousClassNode($node->children['class'], $this->context);
}
// Things of the form `new $method->name()`
if ($node->children['class']->kind !== \ast\AST_NAME) {
return '';
}
$class_name = $node->children['class']->children['name'];
if (!in_array($class_name, ['self', 'static', 'parent'])) {
return (string) UnionTypeVisitor::unionTypeFromClassNode($this->code_base, $this->context, $node->children['class']);
}
if (!$this->context->isInClassScope()) {
Log::err(Log::ESTATIC, "Cannot access {$class_name}:: when no class scope is active", $this->context->getFile(), $node->lineno);
return '';
}
if ($class_name == 'static') {
return (string) $this->context->getClassFQSEN();
}
if ($class_name == 'self') {
if ($this->context->isGlobalScope()) {
assert(false, "Unimplemented branch is required for {$this->context}");
} else {
return (string) $this->context->getClassFQSEN();
}
}
if ($class_name == 'parent') {
$clazz = $this->context->getClassInScope($this->code_base);
if (!$clazz->hasParentClassFQSEN()) {
return '';
}
return (string) $clazz->getParentClassFQSEN();
}
return '';
}
示例6: getPropertyByNameInContext
/**
* @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}}"]));
}
示例7: asClassList
/**
* @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));
}
}
}
示例8: visitMethodCall
/**
* @param Node $node
* A node of the type indicated by the method name that we'd
* like to figure out the type that it produces.
*
* @return string
* The class name represented by the given call
*/
public function visitMethodCall(Node $node) : string
{
if ($node->children['expr']->kind == \ast\AST_VAR) {
if ($node->children['expr']->children['name'] instanceof Node) {
return '';
}
// $var->method()
if ($node->children['expr']->children['name'] == 'this') {
if (!$this->context->isInClassScope()) {
Log::err(Log::ESTATIC, 'Using $this when not in object context', $this->context->getFile(), $node->lineno);
return '';
}
return (string) $this->context->getClassFQSEN();
}
$variable_name = $node->children['expr']->children['name'];
if (!$this->context->getScope()->hasVariableWithName($variable_name)) {
// Got lost, couldn't find the variable in the current scope
// If it really isn't defined, it will be caught by the
// undefined var error
return '';
}
$variable = $this->context->getScope()->getVariableWithName($variable_name);
// Hack - loop through the possible types of the var and assume
// first found class is correct
foreach ($variable->getUnionType()->nonGenericArrayTypes()->getTypeList() as $type) {
$child_class_fqsen = FullyQualifiedClassName::fromStringInContext((string) $type, $this->context);
if ($this->code_base->hasClassWithFQSEN($child_class_fqsen)) {
return (string) FullyQualifiedClassName::fromStringInContext((string) $type, $this->context);
}
}
// Could not find name
return '';
}
if ($node->children['expr']->kind == \ast\AST_PROP) {
$prop = $node->children['expr'];
if (!($prop->children['expr']->kind == \ast\AST_VAR && !$prop->children['expr']->children['name'] instanceof Node)) {
return '';
}
// $var->prop->method()
$var = $prop->children['expr'];
if ($var->children['name'] == 'this') {
// If we're not in a class scope, 'this' won't work
if (!$this->context->isInClassScope()) {
Log::err(Log::ESTATIC, 'Using $this when not in object context', $this->context->getFile(), $node->lineno);
return '';
}
// $this->$prop->method()
if ($prop->children['prop'] instanceof Node) {
// Too hard. Giving up.
return '';
}
$class = $this->context->getClassInScope($this->code_base);
$property_name = $prop->children['prop'];
if (!$class->hasPropertyWithName($this->code_base, $property_name)) {
// If we can't find the property, there's
// no type. Thie issue should be caught
// elsewhere.
return '';
}
try {
$property = $class->getPropertyByNameInContext($this->code_base, $property_name, $this->context);
} catch (AccessException $exception) {
Log::err(Log::EACCESS, $exception->getMessage(), $this->context->getFile(), $node->lineno);
return '';
}
$union_type = $property->getUnionType()->nonNativeTypes();
if ($union_type->isEmpty()) {
// If we don't have a type on the property we
// can't figure out the class type.
return '';
} else {
// Return the first type on the property
// that could be a reference to a class
return (string) $union_type->head()->asFQSEN();
}
// No such property was found, or none were classes
// that could be found
return '';
}
return '';
}
if ($node->children['expr']->kind == \ast\AST_METHOD_CALL) {
// Get the type returned by the first method
// call.
$union_type = UnionType::fromNode($this->context, $this->code_base, $node->children['expr']);
// Find the subset of types that are viable
// classes
$viable_class_types = $union_type->nonNativeTypes()->nonGenericArrayTypes();
// If there are no non-native types, give up
if ($viable_class_types->isEmpty()) {
return '';
}
//.........这里部分代码省略.........