private static InvokesPropertyChanged Invokes(IMethodSymbol method, IParameterSymbol parameter, SemanticModel semanticModel, CancellationToken cancellationToken) { if (method.DeclaringSyntaxReferences.Length == 0) { return(InvokesPropertyChanged.Maybe); } foreach (var reference in method.DeclaringSyntaxReferences) { var methodDeclaration = (MethodDeclarationSyntax)reference.GetSyntax(cancellationToken); using (var pooled = InvocationWalker.Create(methodDeclaration)) { foreach (var invocation in pooled.Item.Invocations) { var invokedMethod = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol; if (invokedMethod == null) { continue; } if (invokedMethod == KnownSymbol.PropertyChangedEventHandler.Invoke) { ArgumentSyntax argument; if (invocation.ArgumentList.Arguments.TryGetAtIndex(1, out argument)) { var identifier = argument.Expression as IdentifierNameSyntax; if (identifier?.Identifier.ValueText == parameter.Name) { return(InvokesPropertyChanged.Yes); } var objectCreation = argument.Expression as ObjectCreationExpressionSyntax; if (objectCreation != null) { var nameArgument = objectCreation.ArgumentList.Arguments[0]; if ((nameArgument.Expression as IdentifierNameSyntax)?.Identifier.ValueText == parameter.Name) { return(InvokesPropertyChanged.Yes); } } } } } } } return(InvokesPropertyChanged.No); }
internal static AnalysisResult InvokesPropertyChangedFor(this SyntaxNode assignment, IPropertySymbol property, SemanticModel semanticModel, CancellationToken cancellationToken) { var invokes = AnalysisResult.No; var block = assignment.FirstAncestorOrSelf <MethodDeclarationSyntax>()?.Body ?? assignment.FirstAncestorOrSelf <AccessorDeclarationSyntax>()?.Body ?? assignment.FirstAncestorOrSelf <AnonymousFunctionExpressionSyntax>()?.Body; if (block == null) { return(AnalysisResult.No); } using (var pooled = InvocationWalker.Create(block)) { foreach (var invocation in pooled.Item.Invocations) { if (invocation.SpanStart < assignment.SpanStart) { continue; } switch (TryGetInvokedPropertyChangedName(invocation, semanticModel, cancellationToken, out ArgumentSyntax _, out string propertyName)) {
internal static bool TryGetInvoker(ITypeSymbol type, SemanticModel semanticModel, CancellationToken cancellationToken, out IMethodSymbol invoker) { invoker = null; foreach (var member in type.GetMembers()) { var method = member as IMethodSymbol; if (method?.Parameters.Length != 1) { continue; } var parameter = method.Parameters[0]; if (method.DeclaringSyntaxReferences.Length == 0) { if (parameter.Type == KnownSymbol.String && method.Name.Contains("PropertyChnaged")) { // A bit speculative here // for handling the case when inheriting a ViewModelBase class from a binary reference. invoker = method; } continue; } foreach (var declaration in method.Declarations(cancellationToken)) { using (var pooled = InvocationWalker.Create(declaration)) { foreach (var invocation in pooled.Item.Invocations) { var invokedMethod = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol; if (invokedMethod == null) { continue; } if (invokedMethod == KnownSymbol.PropertyChangedEventHandler.Invoke) { ArgumentSyntax argument; if (invocation.ArgumentList.Arguments.TryGetAtIndex(1, out argument)) { var identifier = argument.Expression as IdentifierNameSyntax; if (identifier?.Identifier.ValueText == parameter.Name) { invoker = method; return(true); } var objectCreation = argument.Expression as ObjectCreationExpressionSyntax; if (objectCreation != null) { var nameArgument = objectCreation.ArgumentList.Arguments[0]; if ((nameArgument.Expression as IdentifierNameSyntax)?.Identifier.ValueText == parameter.Name) { invoker = method; return(true); } } } } } } } } return(invoker != null); }
internal static InvokesPropertyChanged InvokesPropertyChangedFor(this AssignmentExpressionSyntax assignment, IPropertySymbol property, SemanticModel semanticModel, CancellationToken cancellationToken) { var invokes = InvokesPropertyChanged.No; var block = assignment.FirstAncestorOrSelf <BlockSyntax>(); if (block == null) { return(InvokesPropertyChanged.No); } using (var pooled = InvocationWalker.Create(block)) { foreach (var invocation in pooled.Item.Invocations) { if (invocation.SpanStart < assignment.SpanStart) { continue; } var method = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol; if (method == null) { continue; } if (method == KnownSymbol.PropertyChangedEventHandler.Invoke) { ArgumentSyntax argument; if (invocation.ArgumentList.Arguments.TryGetAtIndex(1, out argument)) { if (argument.Expression.IsCreatePropertyChangedEventArgsFor(property, semanticModel, cancellationToken)) { return(InvokesPropertyChanged.Yes); } var cached = semanticModel.GetSymbolSafe(argument.Expression, cancellationToken); if (cached is IFieldSymbol) { foreach (var syntaxReference in cached.DeclaringSyntaxReferences) { var declarator = syntaxReference.GetSyntax(cancellationToken) as VariableDeclaratorSyntax; if (declarator?.Initializer?.Value?.IsCreatePropertyChangedEventArgsFor(property, semanticModel, cancellationToken) == true) { return(InvokesPropertyChanged.Yes); } } } continue; } } switch (method.InvokesPropertyChangedFor(property, invocation, semanticModel, cancellationToken)) { case InvokesPropertyChanged.No: break; case InvokesPropertyChanged.Yes: return(InvokesPropertyChanged.Yes); case InvokesPropertyChanged.Maybe: if (invokes == InvokesPropertyChanged.No) { invokes = InvokesPropertyChanged.Maybe; } break; default: throw new ArgumentOutOfRangeException(); } } } return(invokes); }