private void AnalyzeType(SourceTypeSymbol type) { // resolves base types in here var btype = type.BaseType; // ... }
/// <summary> /// Creates type context for a method within given type, determines naming, type context. /// </summary> public static TypeRefContext /*!*/ CreateTypeRefContext(SourceTypeSymbol /*!*/ containingType) { Contract.ThrowIfNull(containingType); var typeDecl = containingType.Syntax; return(new TypeRefContext(typeDecl.ContainingSourceUnit, containingType)); }
/// <summary> /// Creates type context for a method within given type, determines naming, type context. /// </summary> public static TypeRefContext /*!*/ CreateTypeRefContext(SourceTypeSymbol /*!*/ containingType) { Contract.ThrowIfNull(containingType); return(new TypeRefContext( containingType, // scope thisType: containingType.IsTrait?null: containingType)); }
void WriteType(SourceTypeSymbol type) { _writer.WriteLine($"<member name=\"{CommentIdResolver.GetId(type)}\">"); var phpdoc = type.Syntax?.PHPDoc; if (phpdoc != null) { WriteSummary(phpdoc.Summary); } _writer.WriteLine("</member>"); // // fields // foreach (var field in type.GetMembers().OfType <SourceFieldSymbol>()) { if ((phpdoc = field.PhpDocBlock) != null) { var summary = phpdoc.Summary; var value = string.Empty; if (string.IsNullOrEmpty(summary)) { // try @var or @staticvar: var vartag = field.FindPhpDocVarTag(); if (vartag != null) { summary = vartag.Description; if (!string.IsNullOrEmpty(vartag.TypeNames)) { value = string.Format("<value>{0}</value>", XmlEncode(vartag.TypeNames)); } } } if (!string.IsNullOrWhiteSpace(summary)) { _writer.WriteLine($"<member name=\"{CommentIdResolver.GetId(field)}\">"); WriteSummary(summary); _writer.WriteLine(value); _writer.WriteLine("</member>"); } } } // // .ctor // foreach (var ctor in type.InstanceConstructors) { if (ctor is SynthesizedPhpCtorSymbol synctor && synctor.PhpConstructor is SourceRoutineSymbol phpctor) { WriteRoutine(CommentIdResolver.GetId(synctor), phpctor); } } }
public BoundClassTypeRef(QualifiedName qname, SourceRoutineSymbol routine, SourceTypeSymbol self) { if (qname.IsReservedClassName) { throw new ArgumentException(); } _qname = qname; _routine = routine; _self = self; }
void WriteType(SourceTypeSymbol type) { _writer.WriteLine($"<member name=\"{CommentIdResolver.GetId(type)}\">"); var phpdoc = type.Syntax?.PHPDoc; if (phpdoc != null) { WriteSummary(phpdoc.Summary); } _writer.WriteLine("</member>"); }
internal BoundTypeDeclStatement Update(SourceTypeSymbol type) { if (type == _type) { return(this); } else { return(new BoundTypeDeclStatement(type)); } }
/// <summary> /// Enqueues initializers of a class fields and constants. /// </summary> void EnqueueFieldsInitializer(SourceTypeSymbol type) { type.GetDeclaredMembers().OfType <SourceFieldSymbol>().ForEach(f => { if (f.Initializer != null) { EnqueueExpression( f.Initializer, f.EnsureTypeRefContext()); } }); }
/// <summary> /// Enqueues initializers of a class fields and constants. /// </summary> void EnqueueFieldsInitializer(SourceTypeSymbol type) { type.GetMembers().OfType <SourceFieldSymbol>().Foreach(f => { if (f.Initializer != null) { EnqueueExpression( f.Initializer, TypeRefFactory.CreateTypeRefContext(type), //the context will be lost, analysis resolves constant values only and types are temporary NameUtils.GetNamingContext(type.Syntax)); } }); }
/// <summary> /// Enqueues initializers of a class fields and constants, and type custom attributes. /// </summary> void EnqueueType(SourceTypeSymbol type) { type.GetDeclaredMembers().OfType <SourceFieldSymbol>().ForEach(f => { if (f.Initializer != null) { EnqueueExpression( f.Initializer, f.EnsureTypeRefContext()); } EnqueueAttributes(f.SourceAttributes); }); EnqueueAttributes(type.SourceAttributes.OfType <SourceCustomAttribute>()); }
void WalkTypes(Action <SourceTypeSymbol> action) { SourceTypeSymbol current = null; try { foreach (SourceTypeSymbol s in _compilation.SourceSymbolCollection.GetTypes()) { current = s; action.Invoke(s); } } catch (Exception e) { L.Error(e, "Exception thrown analyzing source type {0} in file {1}.", current.Name, current.ContainingFile.SyntaxTree.FilePath); } _compilation.SourceSymbolCollection.GetTypes().Foreach(action); }
/// <summary> /// Binds <see cref="AST.TypeRef"/> to a type symbol. /// </summary> /// <param name="tref">Type reference.</param> /// <param name="selfHint">Optional. /// Current type scope for better <paramref name="tref"/> resolution since <paramref name="tref"/> might be ambiguous</param> /// <param name="nullable">Whether the resulting type must be able to contain NULL. Default is <c>false</c>.</param> /// <returns>Resolved symbol.</returns> internal TypeSymbol GetTypeFromTypeRef(AST.TypeRef tref, SourceTypeSymbol selfHint = null, bool nullable = false) { if (tref == null) { return(null); } var t = this.TypeRefFactory.CreateFromTypeRef(tref, null, selfHint); var symbol = t.ResolveRuntimeType(this); if (t.IsNullable || nullable) { // TODO: for value types -> Nullable<T> symbol = MergeNull(symbol); } return(symbol); }
/// <summary> /// Binds <see cref="AST.TypeRef"/> to a type symbol. /// </summary> /// <param name="tref">Type reference.</param> /// <param name="selfHint">Optional. /// Current type scope for better <paramref name="tref"/> resolution since <paramref name="tref"/> might be ambiguous</param> /// <param name="nullable">Whether the resulting type must be able to contain NULL. Default is <c>false</c>.</param> /// <param name="phpLang">PHP semantic - specifies how to treat <c>int</c> and <c>string</c> special types.</param> /// <returns>Resolved symbol.</returns> internal TypeSymbol GetTypeFromTypeRef(AST.TypeRef tref, SourceTypeSymbol selfHint = null, bool nullable = false, bool phpLang = false) { if (tref == null) { return(null); } var t = this.TypeRefFactory.CreateFromTypeRef(tref, self: selfHint, phpLang: phpLang); var symbol = t.ResolveRuntimeType(this); if (t.IsNullable || nullable) { // TODO: asSystemNullable: true // to generate strongly typed function signatures symbol = MergeNull(symbol, asSystemNullable: false); } return(symbol); }
void WriteType(SourceTypeSymbol type) { _writer.WriteLine($"<member name=\"{CommentIdResolver.GetId(type)}\">"); var phpdoc = type.Syntax?.PHPDoc; if (phpdoc != null) { WriteSummary(_writer, phpdoc.Summary); } _writer.WriteLine("</member>"); // // fields // foreach (var field in type.GetMembers().OfType <SourceFieldSymbol>()) { if ((phpdoc = field.PHPDocBlock) != null) { var summary = phpdoc.Summary; var value = string.Empty; if (string.IsNullOrEmpty(summary)) { // try @var or @staticvar: var vartag = field.FindPhpDocVarTag(); if (vartag != null) { summary = vartag.Description; if (!string.IsNullOrEmpty(vartag.TypeNames)) { value = string.Format("<value>{0}</value>", XmlEncode(vartag.TypeNames)); } } } if (!string.IsNullOrWhiteSpace(summary)) { _writer.WriteLine($"<member name=\"{CommentIdResolver.GetId(field)}\">"); WriteSummary(_writer, summary); _writer.WriteLine(value); _writer.WriteLine("</member>"); } } } // // .ctor // var ctors = type.InstanceConstructors; for (int i = 0; i < ctors.Length; i++) { // find __construct() if (ctors[i] is SynthesizedPhpCtorSymbol synctor && synctor.PhpConstructor is SourceRoutineSymbol php_construct) { // annotate all generated .ctor() methods: for (int j = 0; j < ctors.Length; j++) { var ctor_id = CommentIdResolver.GetId(ctors[j]); if (ctors[j].IsFieldsOnlyConstructor()) { // annotate special .ctor that initializes only fields _writer.WriteLine($"<member name=\"{ctor_id}\">"); WriteSummary(_writer, Peachpie.CodeAnalysis.PhpResources.XmlDoc_FieldsOnlyCtor); _writer.WriteLine("</member>"); } else { WriteRoutine(ctor_id, php_construct); } } break; } } }
internal TypeRefContext(SourceTypeSymbol selfType) : this(selfType, thisType : selfType) { }
internal TypeRefContext(PhpCompilation compilation, SourceTypeSymbol selfType) : this(compilation, selfType, thisType : selfType) { }
protected private virtual void OnUnreachableTypeFound(SourceTypeSymbol type) { }
public static IBoundTypeRef Create(QualifiedName qname, SourceTypeSymbol self) => new BoundClassTypeRef(qname, null, self);
internal TypeRefContext(PhpCompilation compilation, SourceTypeSymbol selfType, SourceTypeSymbol thisType) { _compilation = compilation ?? throw ExceptionUtilities.ArgumentNull(nameof(compilation)); _selfType = selfType; _thisType = thisType; }
ImmutableArray <BoundTypeRef> Create(IList <Ast.TypeRef> trefs, SemanticsBinder binder, SourceTypeSymbol self) { return(trefs .Select(t => CreateFromTypeRef(t, binder, self, objectTypeInfoSemantic: false).WithSyntax(t)) .AsImmutable()); }
/// <summary> /// Binds <see cref="AST.TypeRef"/> to a type symbol. /// </summary> /// <param name="tref">Type reference.</param> /// <param name="selfHint">Optional. /// Current type scope for better <paramref name="tref"/> resolution since <paramref name="tref"/> might be ambiguous</param> /// <param name="nullable">Whether the resulting type must be able to contain NULL. Default is <c>false</c>.</param> /// <returns>Resolved symbol.</returns> internal TypeSymbol GetTypeFromTypeRef(AST.TypeRef tref, SourceTypeSymbol selfHint = null, bool nullable = false) { if (tref == null) { return(null); } if (nullable) { return(MergeNull(GetTypeFromTypeRef(tref, selfHint, nullable: false))); // TODO: Nullable<T> } if (tref is AST.PrimitiveTypeRef) { switch (((AST.PrimitiveTypeRef)tref).PrimitiveTypeName) { case AST.PrimitiveTypeRef.PrimitiveType.@int: return(CoreTypes.Long); case AST.PrimitiveTypeRef.PrimitiveType.@float: return(CoreTypes.Double); case AST.PrimitiveTypeRef.PrimitiveType.@string: return(CoreTypes.String); // TODO: PhpString ? case AST.PrimitiveTypeRef.PrimitiveType.@bool: return(CoreTypes.Boolean); case AST.PrimitiveTypeRef.PrimitiveType.array: return(CoreTypes.PhpArray); case AST.PrimitiveTypeRef.PrimitiveType.callable: return(CoreTypes.PhpValue); // array|string|object case AST.PrimitiveTypeRef.PrimitiveType.@void: return(CoreTypes.Void); case AST.PrimitiveTypeRef.PrimitiveType.iterable: return(CoreTypes.PhpValue); // array|Traversable case AST.PrimitiveTypeRef.PrimitiveType.@object: return(CoreTypes.Object); // Object default: throw new ArgumentException(); } } else if (tref is AST.INamedTypeRef namedtref) { if (selfHint != null) { if (namedtref.ClassName == selfHint.FullName) { return(selfHint); } if (selfHint.BaseType is IPhpTypeSymbol phpt && namedtref.ClassName == phpt.FullName) { return(selfHint.BaseType); } } var t = (NamedTypeSymbol)GlobalSemantics.ResolveType(namedtref.ClassName); return(t.IsErrorTypeOrNull() ? CoreTypes.Object.Symbol // TODO: merge candidates if any : t); } else if (tref is AST.ReservedTypeRef) { throw new ArgumentException(); // NOTE: should be translated by parser to AliasedTypeRef } else if (tref is AST.AnonymousTypeRef) { return((NamedTypeSymbol)GlobalSemantics.ResolveType(((AST.AnonymousTypeRef)tref).TypeDeclaration.GetAnonymousTypeQualifiedName())); } else if (tref is AST.MultipleTypeRef) { TypeSymbol result = null; foreach (var x in ((AST.MultipleTypeRef)tref).MultipleTypes) { var resolved = GetTypeFromTypeRef(x, selfHint); result = (result != null) ? Merge(result, resolved) : resolved; } return(result); } else if (tref is AST.NullableTypeRef nullableref) { return(GetTypeFromTypeRef(nullableref.TargetType, selfHint, nullable: true)); } else if (tref is AST.GenericTypeRef) { throw new NotImplementedException(); //((AST.GenericTypeRef)tref).TargetType } else if (tref is AST.IndirectTypeRef) { throw new NotImplementedException(); } throw ExceptionUtilities.UnexpectedValue(tref); }
private protected override void OnUnreachableTypeFound(SourceTypeSymbol type) { _delayedTransformations.UnreachableTypes.Add(type); }
internal TypeRefContext(SourceTypeSymbol selfType, SourceTypeSymbol thisType) { _typeRefs = new List <ITypeRef>(); _selfType = selfType; _thisType = thisType; }
internal TypeRefContext(SourceUnit sourceUnit, SourceTypeSymbol containingType) { _sourceUnit = sourceUnit; _typeRefs = new List <ITypeRef>(); _containingType = containingType; }
ImmutableArray <BoundTypeRef> Create(IList <Ast.TypeRef> trefs, SemanticsBinder binder, SourceTypeSymbol self, bool nullClassSemantic = false, bool phpLang = false) { return(trefs.SelectAsArray(t => { if (nullClassSemantic && t.IsNullClass()) { return NullTypeRef; } return CreateFromTypeRef(t, binder, self, objectTypeInfoSemantic: false, phpLang: phpLang).WithSyntax(t); })); }
public BoundTypeRef CreateFromTypeRef(Ast.TypeRef tref, SemanticsBinder binder = null, SourceTypeSymbol self = null, bool objectTypeInfoSemantic = false) { if (tref is Ast.PrimitiveTypeRef pt) { switch (pt.PrimitiveTypeName) { case Ast.PrimitiveTypeRef.PrimitiveType.@int: return(LongTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.@float: return(DoubleTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.@string: return(StringTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.@bool: return(BoolTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.array: return(ArrayTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.callable: return(CallableTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.@void: return(VoidTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.iterable: return(IterableTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.@object: return(ObjectTypeRef); default: throw ExceptionUtilities.UnexpectedValue(pt.PrimitiveTypeName); } } else if (tref is Ast.INamedTypeRef named) { if (named.ClassName == NameUtils.SpecialNames.System_Object) { return(ObjectTypeRef); } //if (named.ClassName == NameUtils.SpecialNames.stdClass) return StdClassTypeRef; if (named is Ast.TranslatedTypeRef tt && self != null && tt.OriginalType is Ast.ReservedTypeRef reserved) { // keep self,parent,static not translated - better in cases where the type is ambiguous return(CreateFromTypeRef(reserved, binder, self, objectTypeInfoSemantic)); } return(new BoundClassTypeRef(named.ClassName, binder?.Routine, self ?? binder?.Self)); } else if (tref is Ast.ReservedTypeRef reserved) { return(new BoundReservedTypeRef(reserved.Type, self)); } else if (tref is Ast.AnonymousTypeRef at) { return(new BoundTypeRefFromSymbol(at.TypeDeclaration.GetProperty <SourceTypeSymbol>())); } else if (tref is Ast.MultipleTypeRef mt) { return(new BoundMultipleTypeRef(Create(mt.MultipleTypes, binder, self))); } else if (tref is Ast.NullableTypeRef nullable) { var t = CreateFromTypeRef(nullable.TargetType, binder, self, objectTypeInfoSemantic); t.IsNullable = true; return(t); } else if (tref is Ast.GenericTypeRef gt) { return(new BoundGenericClassTypeRef( CreateFromTypeRef(gt.TargetType, binder, self, objectTypeInfoSemantic), Create(gt.GenericParams, binder, self))); } else if (tref is Ast.IndirectTypeRef it) { return(new BoundIndirectTypeRef( binder.BindWholeExpression(it.ClassNameVar, BoundAccess.Read).SingleBoundElement(), objectTypeInfoSemantic)); } else { throw ExceptionUtilities.UnexpectedValue(tref); } }
private void DiagnoseType(SourceTypeSymbol type) { type.GetDiagnostics(_diagnostics); }
internal TypeRefContext(SourceTypeSymbol selfType, SourceTypeSymbol thisType) { _selfType = selfType; _thisType = thisType; }
public BoundReservedTypeRef(ReservedType type, SourceTypeSymbol self = null) { _type = type; _self = self; }
public BoundTypeRef CreateFromTypeRef(Ast.TypeRef tref, SemanticsBinder binder = null, SourceTypeSymbol self = null, bool objectTypeInfoSemantic = false, int arity = -1, bool phpLang = false) { if (tref is Ast.PrimitiveTypeRef pt) { switch (pt.PrimitiveTypeName) { case Ast.PrimitiveTypeRef.PrimitiveType.@int: return(LongTypeRef); // CONSIDER: phpLang ? LongTypeRef : Create(Int32); case Ast.PrimitiveTypeRef.PrimitiveType.@float: return(DoubleTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.@string: return(phpLang ? WritableStringRef : StringTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.@bool: return(BoolTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.array: return(ArrayTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.callable: return(CallableTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.@void: return(VoidTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.iterable: return(IterableTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.@object: return(ObjectTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.mixed: return(MixedTypeRef); case Ast.PrimitiveTypeRef.PrimitiveType.never: return(VoidTypeRef); default: throw ExceptionUtilities.UnexpectedValue(pt.PrimitiveTypeName); } } else if (tref is Ast.INamedTypeRef named) { if (named.ClassName == NameUtils.SpecialNames.System_Object) { return(ObjectTypeRef); } //if (named.ClassName == NameUtils.SpecialNames.stdClass) return StdClassTypeRef; if (named is Ast.TranslatedTypeRef tt && self != null && tt.OriginalType is Ast.ReservedTypeRef reserved) { // keep self,parent,static not translated - better in cases where the type is ambiguous return(CreateFromTypeRef(reserved, binder, self, objectTypeInfoSemantic, phpLang: phpLang)); } return(new BoundClassTypeRef(named.ClassName, binder?.Routine, self ?? binder?.Self, arity)); } else if (tref is Ast.ReservedTypeRef reserved) { return(new BoundReservedTypeRef(reserved.Type, self)); } else if (tref is Ast.AnonymousTypeRef at) { return(new BoundTypeRefFromSymbol(at.TypeDeclaration.GetProperty <SourceTypeSymbol>())); } else if (tref is Ast.MultipleTypeRef mt) { return(new BoundMultipleTypeRef(Create(mt.MultipleTypes, binder, self, nullClassSemantic: true, phpLang: phpLang))); } else if (tref is Ast.NullableTypeRef nullable) { var t = CreateFromTypeRef(nullable.TargetType, binder, self, objectTypeInfoSemantic, phpLang: phpLang); if (t.IsNullable != true) { if (t is BoundPrimitiveTypeRef bpt) { // do not change the cached singleton // https://github.com/peachpiecompiler/peachpie/issues/455 t = new BoundPrimitiveTypeRef(bpt.TypeCode); } t.IsNullable = true; } return(t); } else if (tref is Ast.GenericTypeRef gt) { return(new BoundGenericClassTypeRef( CreateFromTypeRef(gt.TargetType, binder, self, objectTypeInfoSemantic, arity: gt.GenericParams.Count, phpLang: phpLang), Create(gt.GenericParams, binder, self, phpLang: false))); } else if (tref is Ast.IndirectTypeRef it) { return(new BoundIndirectTypeRef( binder.BindWholeExpression(it.ClassNameVar, BoundAccess.Read).SingleBoundElement(), objectTypeInfoSemantic)); } else { throw ExceptionUtilities.UnexpectedValue(tref); } }