private static bool IsPreferGetMemberThenAccessor(ReflectedMember member, Name name, Flags flags, Types types, SyntaxNodeAnalysisContext context, out string callText) { if (member.Invocation?.Expression is MemberAccessExpressionSyntax memberAccess) { if (member.Symbol is IMethodSymbol method) { if (method.AssociatedSymbol is IPropertySymbol property && Flags.TryGetExpectedBindingFlags(property.ContainingType, property, out var bindingFlags)) { return TryGetPropertyAccessor(MemberName(property), bindingFlags, property.Type, out callText); } if (method.AssociatedSymbol is IEventSymbol eventSymbol && Flags.TryGetExpectedBindingFlags(eventSymbol.ContainingType, eventSymbol, out bindingFlags)) { return TryGetEventAccessor(MemberName(eventSymbol), bindingFlags, out callText); } } //// For symbols not in source and not visible in metadata. else if (member.Symbol is null && types.Argument == null && flags.Explicit.HasFlagFast(BindingFlags.NonPublic)) { if (TryGetInvisibleMemberName("get_", out var memberName) || TryGetInvisibleMemberName("set_", out memberName)) { return TryGetPropertyAccessor(memberName, flags.Explicit, null, out callText); } if (TryGetInvisibleMemberName("add_", out memberName) || TryGetInvisibleMemberName("remove_", out memberName) || TryGetInvisibleMemberName("raise_", out memberName)) { return TryGetEventAccessor(memberName, flags.Explicit, out callText); } } } callText = null; return false; bool TryGetPropertyAccessor(string propertyName, BindingFlags bindingFlags, ITypeSymbol type, out string result) { if (name.MetadataName.StartsWith("get_", StringComparison.OrdinalIgnoreCase)) { result = types.Argument == null ? $"{memberAccess.Expression}.GetProperty({propertyName}, {bindingFlags.ToDisplayString(memberAccess)}).GetMethod" : $"{memberAccess.Expression}.GetProperty({propertyName}, {bindingFlags.ToDisplayString(memberAccess)}, null, typeof({type.ToString(context)}), {types.Argument}, null).GetMethod"; return true; } if (name.MetadataName.StartsWith("set_", StringComparison.OrdinalIgnoreCase)) { result = types.Argument == null ? $"{memberAccess.Expression}.GetProperty({propertyName}, {bindingFlags.ToDisplayString(memberAccess)}).SetMethod" : $"{memberAccess.Expression}.GetProperty({propertyName}, {bindingFlags.ToDisplayString(memberAccess)}, null, typeof({type.ToString(context)}), {types.Argument}, null).SetMethod"; return true; } result = null; return false; } bool TryGetEventAccessor(string eventName, BindingFlags bindingFlags, out string result) { if (name.MetadataName.StartsWith("add_", StringComparison.OrdinalIgnoreCase)) { result = $"{memberAccess.Expression}.GetEvent({eventName}, {bindingFlags.ToDisplayString(memberAccess)}).AddMethod"; return true; } if (name.MetadataName.StartsWith("remove_", StringComparison.OrdinalIgnoreCase)) { result = $"{memberAccess.Expression}.GetEvent({eventName}, {bindingFlags.ToDisplayString(memberAccess)}).RemoveMethod"; return true; } if (name.MetadataName.StartsWith("raise_", StringComparison.OrdinalIgnoreCase)) { result = $"{memberAccess.Expression}.GetEvent({eventName}, {bindingFlags.ToDisplayString(memberAccess)}).RaiseMethod"; return true; } result = null; return false; } bool TryGetInvisibleMemberName(string prefix, out string memberName) { if (name.MetadataName is string metadataName && metadataName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { memberName = $"\"{metadataName.Substring(prefix.Length)}\""; return true; } memberName = null; return false; } string MemberName(ISymbol associatedSymbol) { if (associatedSymbol is IPropertySymbol property && property.IsIndexer) { return $"\"{associatedSymbol.MetadataName}\""; } if (context.ContainingSymbol.ContainingType == associatedSymbol.ContainingType) { if (member.Symbol.IsStatic) { return $"nameof({associatedSymbol.Name})"; } return context.SemanticModel.UnderscoreFields() ? associatedSymbol.Name : $"nameof(this.{associatedSymbol.Name})"; } return context.SemanticModel.IsAccessible(context.Node.SpanStart, associatedSymbol) ? $"nameof({associatedSymbol.ContainingType.ToString(context)}.{associatedSymbol.Name})" : $"\"{associatedSymbol.Name}\""; } }
private static bool TryGetX(SyntaxNodeAnalysisContext context, out ReflectedMember member, out Name name, out Flags flags, out Types types) { name = default(Name); if (context.Node is InvocationExpressionSyntax candidate) { return GetX.TryMatchGetConstructor(candidate, context, out member, out flags, out types) || GetX.TryMatchGetEvent(candidate, context, out member, out name, out flags) || GetX.TryMatchGetField(candidate, context, out member, out name, out flags) || GetX.TryMatchGetMethod(candidate, context, out member, out name, out flags, out types) || GetX.TryMatchGetNestedType(candidate, context, out member, out name, out flags) || GetX.TryMatchGetProperty(candidate, context, out member, out name, out flags, out types); } member = default(ReflectedMember); flags = default(Flags); types = default(Types); return false; }
private static FilterMatch TryGetMember(IMethodSymbol getX, ITypeSymbol type, Name name, BindingFlags flags, Types types, Compilation compilation, out ISymbol?member) { if (type is INamedTypeSymbol { IsUnboundGenericType : true })
private static bool IsPreferGetMemberThenAccessor(ReflectedMember member, Name name, Flags flags, Types types, SyntaxNodeAnalysisContext context, out string callText) { if (member.Invocation?.Expression is MemberAccessExpressionSyntax memberAccess) { if (member.Symbol is IMethodSymbol method && member.Match == FilterMatch.Single) { if (method.AssociatedSymbol is IPropertySymbol property && Flags.TryGetExpectedBindingFlags(property.ContainingType, property, out var bindingFlags)) { return(TryGetPropertyAccessor(MemberName(property), bindingFlags, property.Type, out callText)); } if (method.AssociatedSymbol is IEventSymbol eventSymbol && Flags.TryGetExpectedBindingFlags(eventSymbol.ContainingType, eventSymbol, out bindingFlags)) { return(TryGetEventAccessor(MemberName(eventSymbol), bindingFlags, out callText)); } } else if (member.Match == FilterMatch.PotentiallyInvisible && types.Argument == null && flags.Explicit.HasFlagFast(BindingFlags.NonPublic)) { if (TryGetInvisibleMemberName("get_", out var memberName) || TryGetInvisibleMemberName("set_", out memberName)) { return(TryGetPropertyAccessor(memberName, flags.Explicit, null, out callText)); } if (TryGetInvisibleMemberName("add_", out memberName) || TryGetInvisibleMemberName("remove_", out memberName) || TryGetInvisibleMemberName("raise_", out memberName)) { return(TryGetEventAccessor(memberName, flags.Explicit, out callText)); } } }
internal static bool TryCreate(IMethodSymbol getX, InvocationExpressionSyntax invocation, INamedTypeSymbol type, ExpressionSyntax typeSource, Name name, BindingFlags flags, Types types, Compilation compilation, out ReflectedMember member) { var match = TryGetMember(getX, type, name, flags, types, compilation, out var memberSymbol); member = new ReflectedMember(type, typeSource, memberSymbol, getX, invocation, match); return(true); }