示例#1
0
        public override T VisitAssign(BoundAssignEx x)
        {
            // Template: <x> = <x>
            if (x.Target is BoundVariableRef lvar && lvar.Variable is LocalVariableReference lloc &&
                x.Value is BoundVariableRef rvar && rvar.Variable is LocalVariableReference rloc &&
                lloc.BoundName == rloc.BoundName && x.PhpSyntax != null)
            {
                // Assignment made to same variable
                _diagnostics.Add(_routine, x.PhpSyntax, ErrorCode.WRN_AssigningSameVariable);
            }

            // Check the type of the value assigned to a field against its PHPDoc
            var valMask = x.Value.TypeRefMask;

            if (!valMask.IsAnyType && !valMask.IsRef &&
                x.Target is BoundFieldRef fr && fr.BoundReference.Symbol is SourceFieldSymbol fieldSymbol &&
                fieldSymbol.FindPhpDocVarTag() is PHPDocBlock.TypeVarDescTag fieldDoc &&
                fieldDoc.TypeNamesArray.Length != 0)
            {
                var namingCtx = NameUtils.GetNamingContext(fieldSymbol.PhpDocBlock.ContainingType);
                var fieldMask = PHPDoc.GetTypeMask(TypeCtx, fieldDoc.TypeNamesArray, namingCtx);

                if (!TypeCtx.CanBeSameType(fieldMask, valMask))
                {
                    // The value can't be of the type specified in PHPDoc
                    _diagnostics.Add(_routine, x.PhpSyntax, ErrorCode.WRN_FieldPhpDocAssignIncompatible,
                                     TypeCtx.ToString(valMask), fieldSymbol, fieldDoc.TypeNames);
                }
            }

            //

            return(base.VisitAssign(x));
        }
示例#2
0
 /// <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));
         }
     });
 }
示例#3
0
        internal override TypeSymbol GetFieldType(ConsList <FieldSymbol> fieldsBeingBound)
        {
            // TODO: HHVM TypeHint

            //
            if ((IsConst || IsReadOnly) && Initializer != null)
            {
                // resolved type symbol if possible
                if (Initializer.ResultType != null)
                {
                    return(Initializer.ResultType);
                }

                // resolved value type if possible
                var cvalue = Initializer.ConstantValue;
                if (cvalue.HasValue)
                {
                    var specialType = (cvalue.Value != null)
                        ? cvalue.ToConstantValueOrNull()?.SpecialType
                        : SpecialType.System_Object;    // NULL

                    if (specialType.HasValue && specialType != SpecialType.None)
                    {
                        return(DeclaringCompilation.GetSpecialType(specialType.Value));
                    }
                }

                //
                //return DeclaringCompilation.GetTypeFromTypeRef(typectx, Initializer.TypeRefMask);
            }

            // PHPDoc @var type
            var vartag = _phpDoc?.GetElement <PHPDocBlock.VarTag>();

            if (vartag != null && vartag.TypeNamesArray.Length != 0)
            {
                var dummyctx = TypeRefFactory.CreateTypeRefContext(_containingType);
                var tmask    = PHPDoc.GetTypeMask(dummyctx, vartag.TypeNamesArray, NameUtils.GetNamingContext(_containingType.Syntax));
                return(DeclaringCompilation.GetTypeFromTypeRef(dummyctx, tmask));
            }

            // default
            return(DeclaringCompilation.CoreTypes.PhpValue);
        }
示例#4
0
        internal override TypeSymbol GetFieldType(ConsList <FieldSymbol> fieldsBeingBound)
        {
            // TODO: PHP 7.4 typed properties // https://github.com/peachpiecompiler/peachpie/issues/766

            //
            if ((IsConst || IsReadOnly) && Initializer != null)
            {
                // resolved type symbol if possible
                if (Initializer.ResultType != null)
                {
                    return(Initializer.ResultType);
                }

                // resolved value type if possible
                var cvalue = Initializer.ConstantValue;
                if (cvalue.HasValue)
                {
                    var specialType = (cvalue.Value != null)
                        ? cvalue.ToConstantValueOrNull()?.SpecialType
                        : SpecialType.System_Object;    // NULL

                    if (specialType.HasValue && specialType != SpecialType.None)
                    {
                        return(DeclaringCompilation.GetSpecialType(specialType.Value));
                    }
                }

                //
                //return DeclaringCompilation.GetTypeFromTypeRef(typectx, Initializer.TypeRefMask);
            }

            // PHPDoc @var type
            if ((DeclaringCompilation.Options.PhpDocTypes & PhpDocTypes.FieldTypes) != 0)
            {
                var vartag = FindPhpDocVarTag();
                if (vartag != null && vartag.TypeNamesArray.Length != 0)
                {
                    var dummyctx = TypeRefFactory.CreateTypeRefContext(_containingType);
                    var tmask    = PHPDoc.GetTypeMask(dummyctx, vartag.TypeNamesArray, NameUtils.GetNamingContext(_containingType.Syntax));
                    return(DeclaringCompilation.GetTypeFromTypeRef(dummyctx, tmask));
                }
            }

            // default
            return(DeclaringCompilation.CoreTypes.PhpValue);
        }
示例#5
0
 protected override TypeRefContext CreateTypeRefContext()
 => new TypeRefContext(NameUtils.GetNamingContext(_syntax.Namespace, _syntax.SourceUnit.Ast), _syntax.SourceUnit, null);