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); }
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); }
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; } } } }