/// <summary> /// Creates type reference from a given qualified name. /// The given name will be translated using current naming context. /// </summary> public TypeRef CreateTypeRef(QualifiedNameRef tname, bool allowPrimitiveTypes = false) { var qname = tname.QualifiedName; var span = tname.Span; // primitive type name ? if (qname.IsSimpleName) { if (ReservedTypeRef.ReservedTypes.TryGetValue(qname.Name, out ReservedTypeRef.ReservedType reserved)) { var reservedRef = _astFactory.ReservedTypeReference(span, reserved); if (IsInClassContext) { var context = ClassContexts.Peek(); switch (reserved) { case ReservedTypeRef.ReservedType.parent: if (context.Base != null) { reservedRef = _astFactory.AliasedTypeReference(span, context.Base.QualifiedName.Value, reservedRef); } else if (context.Attributes.IsTrait()) { // keep unbound // {parent} refers to actual class where the trait is used } else { this.ErrorSink.Error(span, FatalErrors.ParentAccessedInParentlessClass); } break; case ReservedTypeRef.ReservedType.self: if (context.Attributes.IsTrait()) { // keep unbound // {self} refers to actual class where the trait is used } else if (context.Name.Name == Name.AnonymousClassName) { // we don't translate {self} in the context of an anonymous type name // since the translated name is platform specific and may differ from how it is handled by caller } else { reservedRef = _astFactory.AliasedTypeReference(span, context.Name, reservedRef); } break; case ReservedTypeRef.ReservedType.@static: // keep unbound break; default: throw new ArgumentException(); } } else { // TODO: Error: self|parent|static used outside a class context // NOTE: allowed in global code } return(reservedRef); } if (allowPrimitiveTypes && PrimitiveTypes.TryGetValue(qname, out PrimitiveTypeRef.PrimitiveType primitive)) { return(_astFactory.PrimitiveTypeReference(span, primitive)); } } // direct type reference return(CreateNamedTypeRef(span, tname)); }
TypeRef CreateTypeRef(Span span, QualifiedNameRef tname) { var qname = tname.QualifiedName; // primitive type name ? if (qname.IsSimpleName) { ReservedTypeRef.ReservedType reserved; PrimitiveTypeRef.PrimitiveType primitive; if ((_languageFeatures.HasFeature(LanguageFeatures.Php71Set)) && PHP71PrimitiveTypes.TryGetValue(qname, out primitive)) { return(_astFactory.PrimitiveTypeReference(span, primitive)); } if ((_languageFeatures.HasFeature(LanguageFeatures.Php70Set)) && PHP70PrimitiveTypes.TryGetValue(qname, out primitive)) { return(_astFactory.PrimitiveTypeReference(span, primitive)); } if ((_languageFeatures.HasFeature(LanguageFeatures.Php56Set)) && PHP56PrimitiveTypes.TryGetValue(qname, out primitive)) { return(_astFactory.PrimitiveTypeReference(span, primitive)); } if (ReservedTypeRef.ReservedTypes.TryGetValue(qname.Name, out reserved)) { var reservedRef = _astFactory.ReservedTypeReference(span, reserved); if (IsInClassContext) { var context = ClassContexts.Peek(); switch (reserved) { case ReservedTypeRef.ReservedType.parent: if (context.Base != null) { reservedRef = _astFactory.AliasedTypeReference(span, context.Base.QualifiedName.Value, reservedRef); } else { this.ErrorSink.Error(span, FatalErrors.ParentAccessedInParentlessClass); } break; case ReservedTypeRef.ReservedType.self: // we don't translate {self} in the context of an anonymous type name // since the translated name is platform specific and may differ from how it is handled by caller if (context.Name.Name != Name.AnonymousClassName) { reservedRef = _astFactory.AliasedTypeReference(span, context.Name, reservedRef); } break; case ReservedTypeRef.ReservedType.@static: // keep unbound break; default: throw new ArgumentException(); } } else { // TODO: Error: self|parent|static used outside a class context } return(reservedRef); } } // direct type reference return(CreateNamedTypeRef(span, tname)); }