private static bool IsAssignDestination(IReferenceExpression expr)
        {
            var fullReference = ReferenceExpressionNavigator.GetTopByQualifierExpression(expr);
            var assignment    = AssignmentExpressionNavigator.GetByDest(fullReference.GetContainingParenthesizedExpression());

            return(ExpressionStatementNavigator.GetByExpression(assignment) != null);
        }
        private bool IsUsageSetTransformParent([NotNull] IReferenceExpression referenceExpression, out bool stayInWorldCoords, [CanBeNull] out ICSharpExpression expression)
        {
            stayInWorldCoords = true;
            expression        = null;
            var declaredElement = referenceExpression.Reference.Resolve().DeclaredElement as IClrDeclaredElement;

            if (declaredElement == null)
            {
                return(false);
            }

            if (declaredElement is IProperty property)
            {
                expression = AssignmentExpressionNavigator.GetByDest(referenceExpression)?.Source;
                if (!property.ShortName.Equals("parent"))
                {
                    return(false);
                }
            }

            if (declaredElement is IMethod setParentMethod)
            {
                if (!setParentMethod.ShortName.Equals("SetParent"))
                {
                    return(false);
                }

                var invocation = InvocationExpressionNavigator.GetByInvokedExpression(referenceExpression);
                if (invocation == null)
                {
                    return(false);
                }
                expression = invocation.Arguments[0].Value;
                if (setParentMethod.Parameters.Count == 2)
                {
                    var argument = invocation.Arguments[1].Value;
                    if (argument?.ConstantValue.Value is bool constantValue)
                    {
                        stayInWorldCoords = constantValue;
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            var containingType = declaredElement.GetContainingType();

            if (containingType != null && containingType.GetClrName().Equals(KnownTypes.Transform))
            {
                return(true);
            }

            return(false);
        }
Beispiel #3
0
        protected override bool IsAppropriateNode(ITreeNode element)
        {
            var csharpExpression = element as ICSharpExpression;

            if (csharpExpression == null)
            {
                return(false);
            }
            return(AssignmentExpressionNavigator.GetBySource(csharpExpression) != null ||
                   CSharpArgumentNavigator.GetByValue(csharpExpression) != null);
        }
        protected override Action <ITextControl> ExecutePsiTransaction(ISolution solution, IProgressIndicator progress)
        {
            var factory  = CSharpElementFactory.GetInstance(myHighlightedReference);
            var property = (myHighlightedReference.Reference.Resolve().DeclaredElement as IProperty).NotNull();

            // save declaration (in case of expression lambda)
            var declaration = myHighlightedReference.GetContainingFunctionLikeDeclarationOrClosure();
            var type        = property.Type;

            var name = GetUniqueName(myHighlightedReference, property.ShortName);

            IReferenceExpression originValue = myHighlightedReference.Copy();

            for (var i = 0; i < myReferences.Count; i++)
            {
                var reference = myReferences[i];
                myReferences[i] = reference.ReplaceBy(factory.CreateReferenceExpression("$0", name));
            }

            var firstReference = myReferences[0];

            if (declaration is IExpressionBodyOwnerDeclaration expressionBodyOwnerDeclaration &&
                expressionBodyOwnerDeclaration.GetCodeBody().ExpressionBody != null)
            {
                using (var marker = new DisposableMarker <IReferenceExpression>(firstReference))
                {
                    var body = expressionBodyOwnerDeclaration.EnsureStatementMemberBody();
                    HandleExpressionBody(body, factory, type, name, marker, originValue);
                }

                return(null);
            }

            if (declaration is ILambdaExpression lambdaExpression &&
                lambdaExpression.GetCodeBody().ExpressionBody != null)
            {
                using (var marker = new DisposableMarker <IReferenceExpression>(firstReference))
                {
                    var body = lambdaExpression.EnsureStatementLambda();
                    HandleExpressionBody(body, factory, type, name, marker, originValue);
                }
                return(null);
            }

            Assertion.Assert(myCacheAnchor is ICSharpStatement, "myInlineCache is IStatement");
            var statementCacheAnchor = (ICSharpStatement)myCacheAnchor;

            if (myInlineCache) // replace first read with assignment expression
            {
                foreach (var reference in myReferences)
                {
                    if (reference.GetContainingStatement() != myCacheAnchor)
                    {
                        continue;
                    }

                    // is write first???
                    // example: var x = (transform.position = Vector3.Up) + transform.position + transform.position ...
                    // if yes, we have already save our variable in cycle above, if no use inline to cache.
                    if (AssignmentExpressionNavigator.GetByDest(reference.GetContainingParenthesizedExpression()) == null)
                    {
                        reference.ReplaceBy(factory.CreateExpression("($0 = $1)", name, originValue.Copy()));
                    }
                    break;
                }

                var cacheStatement = factory.CreateStatement("$0 $1;", type, name);
                StatementUtil.InsertStatement(cacheStatement, ref statementCacheAnchor, true);
            }
            else
            {
                var cacheStatement = factory.CreateStatement("var $0 = $1;", name, originValue.Copy());
                StatementUtil.InsertStatement(cacheStatement, ref statementCacheAnchor, true);
            }

            if (myRestoreAnchor != null)
            {
                Assertion.Assert(myRestoreAnchor is ICSharpStatement, "myRestoreAnchor is IStatement");
                var statementRestoreAnchor = (ICSharpStatement)myRestoreAnchor;
                if (myInlineRestore)
                {
                    var size = myReferences.Count;
                    for (int i = size - 1; i >= 0; i--)
                    {
                        var reference = myReferences[i];
                        if (reference.GetContainingStatement() == myRestoreAnchor)
                        {
                            reference.ReplaceBy(factory.CreateReferenceExpression("$0", originValue));
                            break;
                        }
                    }
                }
                else
                {
                    var restoreStatement = factory.CreateStatement("$0 = $1;", originValue, name);
                    StatementUtil.InsertStatement(restoreStatement, ref statementRestoreAnchor, false);
                }
            }

            return(null);
        }
Beispiel #5
0
 protected override IAssignmentExpression Navigate(ICSharpExpression expression)
 {
     return(AssignmentExpressionNavigator.GetBySource(expression));
 }
        protected override void Analyze(IInvocationExpression expression, ElementProblemAnalyzerData data, IHighlightingConsumer consumer)
        {
            var reference = (expression.InvokedExpression as IReferenceExpression)?.Reference;

            if (reference == null)
            {
                return;
            }

            var info = reference.Resolve();

            if (info.ResolveErrorType != ResolveErrorType.OK)
            {
                return;
            }

            var method = info.DeclaredElement as IMethod;

            if (method == null)
            {
                return;
            }

            if (!method.ShortName.Equals(ourKnownMethod))
            {
                return;
            }

            if (method.GetContainingType()?.GetClrName().Equals(KnownTypes.Object) != true)
            {
                return;
            }


            var parameters = method.Parameters;

            if (parameters.Count != 1)
            {
                return;
            }

            var scope = expression.GetContainingFunctionLikeDeclarationOrClosure().GetCodeBody().GetAnyTreeNode();

            if (scope == null)
            {
                return;
            }

            IEnumerable <ITreeNode> usages = null;
            ITreeNode storage = null;
            var       containingParenthesizedExpression = expression.GetContainingParenthesizedExpression();
            var       castExpression = CastExpressionNavigator.GetByOp(containingParenthesizedExpression);
            var       asExpression   = AsExpressionNavigator.GetByOperand(containingParenthesizedExpression);
            var       initializer    = ExpressionInitializerNavigator.GetByValue(castExpression ?? asExpression ?? containingParenthesizedExpression);
            var       declaration    = LocalVariableDeclarationNavigator.GetByInitial(initializer);


            var usageProvider = data.GetUsagesProvider();

            if (declaration != null)
            {
                usages  = usageProvider.GetUsages(declaration.DeclaredElement, scope).Where(t => t is IReferenceExpression);
                storage = declaration;
            }
            else
            {
                var assignment = AssignmentExpressionNavigator.GetBySource(castExpression ?? asExpression ?? containingParenthesizedExpression);
                var dest       = assignment?.Dest as IReferenceExpression;
                var destInfo   = dest?.Reference.Resolve();
                if (destInfo != null && destInfo.ResolveErrorType == ResolveErrorType.OK)
                {
                    usages  = usageProvider.GetUsages(destInfo.DeclaredElement.NotNull(), scope).Where(t => IsSameReferenceUsed(t, dest));
                    storage = dest;
                }
                else
                {
                    return;
                }
            }

            foreach (var usage in usages)
            {
                if (usage is IReferenceExpression referenceExpression)
                {
                    var fullReferenceExpression = ReferenceExpressionNavigator.GetTopByQualifierExpression(referenceExpression);
                    if (IsUsageSetTransformParent(fullReferenceExpression, out var stayInWorldCoords, out var transform))
                    {
                        if (!InSameBlock(fullReferenceExpression, storage))
                        {
                            return;
                        }
                        var finder             = new TransformParentRelatedReferenceFinder(referenceExpression);
                        var relatedExpressions = finder.GetRelatedExpressions(scope, expression).FirstOrDefault();
                        if (relatedExpressions == null || relatedExpressions.GetTreeStartOffset() >= fullReferenceExpression.GetTreeStartOffset())
                        {
                            consumer.AddHighlighting(new InstantiateWithoutParentWarning(fullReferenceExpression, expression, transform, stayInWorldCoords));
                        }
                        return;
                    }
                }
            }
        }