Example #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));
        }
Example #2
0
        public override void VisitAssign(BoundAssignEx x)
        {
            // Template: <x> = <x>
            if (x.Target is BoundVariableRef lvar && lvar.Variable is BoundLocal lloc &&
                x.Value is BoundVariableRef rvar && rvar.Variable is BoundLocal rloc &&
                lloc.Name == rloc.Name && !string.IsNullOrEmpty(lloc.Name) && x.PhpSyntax != null)
            {
                // Assignment made to same variable
                _diagnostics.Add(_routine, x.PhpSyntax, ErrorCode.WRN_AssigningSameVariable);
            }

            //

            base.VisitAssign(x);
        }
Example #3
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);
            }

            //

            return(base.VisitAssign(x));
        }
        public override object VisitAssign(BoundAssignEx x)
        {
            // A = A <binOp> <right>
            if (x.Target is BoundVariableRef trg &&
                MatchExprSkipCopy(x.Value, out BoundBinaryEx binOp, isCopied: out _) &&
                binOp.Left is BoundVariableRef valLeft &&
                trg.Variable == valLeft.Variable)
            {
                var newTrg =
                    new BoundVariableRef(trg.Name)
                    .WithAccess(trg.Access.WithRead())
                    .WithSyntax(trg.PhpSyntax);

                // A = A +/- 1; => ++A; / --A;
                if ((binOp.Operation == Ast.Operations.Add || binOp.Operation == Ast.Operations.Sub) &&
                    binOp.Right.ConstantValue.IsInteger(out long rightVal) && rightVal == 1)
                {
                    TransformationCount++;
                    return(new BoundIncDecEx(newTrg, binOp.Operation == Ast.Operations.Add, false).WithAccess(x));
                }

                // A = A & B => A &= B; // &, |, ^, <<, >>, +, -, *, /, %, **, .
                switch (binOp.Operation)
                {
                case Ast.Operations.BitAnd:
                case Ast.Operations.BitOr:
                case Ast.Operations.BitXor:
                case Ast.Operations.ShiftLeft:
                case Ast.Operations.ShiftRight:
                case Ast.Operations.Add:
                case Ast.Operations.Sub:
                case Ast.Operations.Mul:
                case Ast.Operations.Div:
                case Ast.Operations.Mod:
                case Ast.Operations.Pow:
                case Ast.Operations.Concat:
                    TransformationCount++;
                    var compoundOp = AstUtils.BinaryToCompoundOp(binOp.Operation);
                    return(new BoundCompoundAssignEx(newTrg, binOp.Right, compoundOp).WithAccess(x));
                }
            }

            return(base.VisitAssign(x));
        }
Example #5
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);
            }

            // Following is commented since it does not have any effect on the compiler and the type check also needs to be improved.
            // Currently it is very inaccurate:

            //// 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);
        }
 public override VoidStruct VisitAssign(BoundAssignEx assign)
 {
     ProcessAssignment(assign);
     return(default);
Example #7
0
 public override object VisitAssign(BoundAssignEx x)
 {
     return(x.Update(
                (BoundReferenceExpression)Accept(x.Target),
                (BoundExpression)Accept(x.Value)));
 }