private static void CalculateConnectionOfDisposableVariables(IInvocationExpression invocationExpression, ControlFlowElementData data, List<IRegularParameterDeclaration> thisConnections, Dictionary<IRegularParameterDeclaration, IVariableDeclaration> connections) { foreach (var argument in invocationExpression.InvocationExpressionReference.Invocation.Arguments) { var cSharpArgument = argument as ICSharpArgument; if (cSharpArgument == null) continue; var argumentExpression = cSharpArgument.Value; IRegularParameterDeclaration matchingVarDecl; if (argumentExpression is IThisExpression && data.ThisStatus != null) { if (GetMatchingParameterDeclaration(argument, out matchingVarDecl)) continue; thisConnections.Add(matchingVarDecl); continue; } var varDecl = TreeNodeHandlerUtil.GetVariableDeclarationForReferenceExpression(argumentExpression); if (data[varDecl] != null) // Если переменную не рассматриваем. { if (GetMatchingParameterDeclaration(argument, out matchingVarDecl)) continue; connections[matchingVarDecl] = varDecl; } } }
private static void SaveInvocationData(ControlFlowElementData data, IVariableDeclaration variable, byte position, string name, int offset, IPsiSourceFile sourceFile) { data[variable] = VariableDisposeStatus.DependsOnInvocation; var invokedExpression = new InvokedExpressionData(name, offset, position, sourceFile); data.InvokedExpressions.Add(variable, invokedExpression); }
public void ProcessTreeNode(ITreeNode treeNode, ControlFlowElementData data) { if (treeNode is IInvocationExpression) { ProcessInvocationExpression(treeNode as IInvocationExpression, data); } else if (treeNode is IUsingStatement) { TreeNodeHandlerUtil.ProcessUsingStatement(treeNode as IUsingStatement, data); } }
public IEnumerable<HighlightingInfo> Inspect() { _elementDataStorage = new ControlFlowElementDataStorage(); var initialData = new ControlFlowElementData(Graf.EntryElement.Id) { ThisStatus = VariableDisposeStatus.NotDisposed }; _elementDataStorage[Graf.EntryElement] = initialData; var nodeHandlerFactory = new TreeNodeHandlerFactory(_maxLevel, _disposableInterface); DoStep(null, Graf.EntryElement, true, nodeHandlerFactory, _elementDataStorage); AddHighlightings(); return _highlightings; }
private void ProcessInvocationExpression([NotNull] IInvocationExpression invocationExpression, ControlFlowElementData data) { var invokedExpression = invocationExpression.InvokedExpression as IReferenceExpression; if (invokedExpression == null) return; var isInvocationOnDisposableThis = TreeNodeHandlerUtil.IsInvocationOnDisposableThis(invokedExpression, _disposableInterface); var qualifierVariableDeclaration = TreeNodeHandlerUtil.GetQualifierVariableDeclaration(invokedExpression); var qualifierDisposableVariableDeclaration = data[qualifierVariableDeclaration] != null ? qualifierVariableDeclaration : null; if (TreeNodeHandlerUtil.CheckOnDisposeInvocation(invocationExpression, data, isInvocationOnDisposableThis, qualifierDisposableVariableDeclaration)) return; ProcessSimpleInvocation(invocationExpression, data, qualifierDisposableVariableDeclaration, isInvocationOnDisposableThis); }
private static void CalculatePositionOfDisposableVariables(IInvocationExpression invocationExpression, ControlFlowElementData data, List<byte> thisPositions, IDictionary<IVariableDeclaration, byte> positions) { byte i = 0; foreach (var argument in invocationExpression.InvocationExpressionReference.Invocation.Arguments) { i++; var cSharpArgument = argument as ICSharpArgument; if (cSharpArgument == null) continue; var argumentExpression = cSharpArgument.Value; if (argumentExpression is IThisExpression && data.ThisStatus != null) { thisPositions.Add(i); continue; } var varDecl = TreeNodeHandlerUtil.GetVariableDeclarationForReferenceExpression(argumentExpression); if (varDecl != null && data[varDecl] != null) // Т.е. если переменную не рассматриваем. positions[varDecl] = i; } }
private void ProcessSimpleInvocation([NotNull] IInvocationExpression invocationExpression, ControlFlowElementData data, [CanBeNull] IVariableDeclaration qualifierDisposableVariableDeclaration, bool isInvocationOnDisposableThis, int level) { var connections = new Dictionary<IRegularParameterDeclaration, IVariableDeclaration>(); var thisConnections = new List<IRegularParameterDeclaration>(); CalculateConnectionOfDisposableVariables(invocationExpression, data, thisConnections, connections); if (!connections.Any() && !thisConnections.Any() && qualifierDisposableVariableDeclaration == null && !isInvocationOnDisposableThis) return; var methodStatus = GetStatusForInvocationExpressionFromCache(invocationExpression); if (methodStatus == null) return; var parameterDeclarations = Enumerable.ToArray(connections.Keys); foreach (var parameterDeclaration in parameterDeclarations) { var argumentStatus = GetArgumentStatusForParameterDeclaration(parameterDeclaration, methodStatus); if (argumentStatus == null) continue; switch (argumentStatus.Status) { case VariableDisposeStatus.Disposed: data[connections[parameterDeclaration]] = VariableDisposeStatus.Disposed; break; case VariableDisposeStatus.DependsOnInvocation: if (AnyoneInvokedExpressionDispose(argumentStatus.InvokedExpressions, level)) data[connections[parameterDeclaration]] = VariableDisposeStatus.Disposed; break; } } //this в качестве аргумента var thisParameterDeclarations = Enumerable.ToArray(connections.Keys); foreach (var parameterDeclaration in thisParameterDeclarations) { var argumentStatus = GetArgumentStatusForParameterDeclaration(parameterDeclaration, methodStatus); if (argumentStatus == null) continue; switch (argumentStatus.Status) { case VariableDisposeStatus.Disposed: data.ThisStatus = VariableDisposeStatus.Disposed; break; case VariableDisposeStatus.DependsOnInvocation: if (AnyoneInvokedExpressionDispose(argumentStatus.InvokedExpressions, level)) data.ThisStatus = VariableDisposeStatus.Disposed; break; } } //обработка qualifierVariableDeclaration, в том числе this if (qualifierDisposableVariableDeclaration != null) { var argumentStatus = GetArgumentStatusByNumber(methodStatus, 0); if (argumentStatus != null) { switch (argumentStatus.Status) { case VariableDisposeStatus.Disposed: data[qualifierDisposableVariableDeclaration] = VariableDisposeStatus.Disposed; break; case VariableDisposeStatus.DependsOnInvocation: if (AnyoneInvokedExpressionDispose(argumentStatus.InvokedExpressions, level)) data[qualifierDisposableVariableDeclaration] = VariableDisposeStatus.Disposed; break; } } } else if (isInvocationOnDisposableThis) { var argumentStatus = GetArgumentStatusByNumber(methodStatus, 0); if (argumentStatus != null) { switch (argumentStatus.Status) { case VariableDisposeStatus.Disposed: data.ThisStatus = VariableDisposeStatus.Disposed; break; case VariableDisposeStatus.DependsOnInvocation: if (AnyoneInvokedExpressionDispose(argumentStatus.InvokedExpressions, level)) data.ThisStatus = VariableDisposeStatus.Disposed; break; } } } }
private void ProcessLocalVariableDeclaration([NotNull] ILocalVariableDeclaration variableDeclaration, ControlFlowElementData data) { if (!DisposeUtil.IsWrappedInUsing(variableDeclaration) && DisposeUtil.VariableTypeImplementsDisposable(variableDeclaration, _disposableInterface)) { data[variableDeclaration] = VariableDisposeStatus.NotDisposed; } }
private ControlFlowElementDataStorage InitElementDataStorage() { var elementDataStorage = new ControlFlowElementDataStorage(); var initialData = new ControlFlowElementData(Graf.EntryElement.Id); if (_disposableArguments != null) _disposableArguments.ForEach(kvp => initialData[kvp.Key] = VariableDisposeStatus.NotDisposed); if (_processThis) initialData.ThisStatus = VariableDisposeStatus.NotDisposed; elementDataStorage[Graf.EntryElement] = initialData; return elementDataStorage; }
private void ProcessSimpleInvocation([NotNull] IInvocationExpression invocationExpression, ControlFlowElementData data, [CanBeNull] IVariableDeclaration qualifierDisposableVariableDeclaration, bool isInvocationOnDisposableThis) { var positions = new Dictionary<IVariableDeclaration, byte>(); var thisPositions = new List<byte>(); CalculatePositionOfDisposableVariables(invocationExpression, data, thisPositions, positions); if (!positions.Any() && !thisPositions.Any() && qualifierDisposableVariableDeclaration == null && !isInvocationOnDisposableThis) return; var referenceExpression = invocationExpression.InvokedExpression as IReferenceExpression; if (referenceExpression == null) return; var nameIdentifier = referenceExpression.NameIdentifier; if (nameIdentifier == null) return; var name = nameIdentifier.Name; var offset = InvokedExpressionData.GetOffsetByNode(invocationExpression); var sourceFile = invocationExpression.GetSourceFile(); foreach (var position in positions) SaveInvocationData(data, position.Key, position.Value, name, offset, sourceFile); //this в качестве аргумента if (thisPositions.Any()) data.ThisStatus = VariableDisposeStatus.DependsOnInvocation; foreach (var position in thisPositions) { var invokedExpression = new InvokedExpressionData(name, offset, position, sourceFile); data.ThisInvokedExpressions.Add(invokedExpression); } //обработка qualifierVariableDeclaration, в том числе this if (qualifierDisposableVariableDeclaration != null) SaveInvocationData(data, qualifierDisposableVariableDeclaration, 0, name, offset, sourceFile); else if (isInvocationOnDisposableThis) { data.ThisStatus = VariableDisposeStatus.DependsOnInvocation; var invokedExpression = new InvokedExpressionData(name, offset, 0, sourceFile); data.ThisInvokedExpressions.Add(invokedExpression); } }