예제 #1
0
        internal static bool TryGet(ExpressionSyntax expression, SyntaxNodeAnalysisContext context, out MethodInfo methodInfo)
        {
            switch (expression)
            {
            case InvocationExpressionSyntax invocation when GetX.TryMatchGetMethod(invocation, context, out var member, out _, out _, out _) && member.Symbol is IMethodSymbol method:
                methodInfo = new MethodInfo(member.ReflectedType, method);

                return(true);

            case InvocationExpressionSyntax invocation when invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
                context.SemanticModel.TryGetSymbol(invocation, KnownSymbol.PropertyInfo.GetGetMethod, context.CancellationToken, out _) &&
                PropertyInfo.TryGet(memberAccess.Expression, context, out var propertyInfo) &&
                propertyInfo.Property.GetMethod is IMethodSymbol getMethod:
                methodInfo = new MethodInfo(propertyInfo.ReflectedType, getMethod);
                return(true);

            case InvocationExpressionSyntax invocation when invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
                context.SemanticModel.TryGetSymbol(invocation, KnownSymbol.PropertyInfo.GetSetMethod, context.CancellationToken, out _) &&
                PropertyInfo.TryGet(memberAccess.Expression, context, out var propertyInfo) &&
                propertyInfo.Property.SetMethod is IMethodSymbol setMethod:
                methodInfo = new MethodInfo(propertyInfo.ReflectedType, setMethod);
                return(true);

            case MemberAccessExpressionSyntax memberAccess when context.SemanticModel.TryGetSymbol(memberAccess, context.CancellationToken, out ISymbol symbol):
                if (symbol == KnownSymbol.PropertyInfo.GetMethod &&
                    PropertyInfo.TryGet(memberAccess.Expression, context, out var property))
                {
                    methodInfo = new MethodInfo(property.ReflectedType, property.Property.GetMethod);
                    return(true);
                }

                if (symbol == KnownSymbol.PropertyInfo.SetMethod &&
                    PropertyInfo.TryGet(memberAccess.Expression, context, out property))
                {
                    methodInfo = new MethodInfo(property.ReflectedType, property.Property.SetMethod);
                    return(true);
                }

                break;
            }

            if (expression.IsEither(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression) &&
                context.SemanticModel.TryGetSymbol(expression, context.CancellationToken, out ISymbol local))
            {
                methodInfo = default(MethodInfo);
                return(AssignedValue.TryGetSingle(local, context.SemanticModel, context.CancellationToken, out var assignedValue) &&
                       TryGet(assignedValue, context, out methodInfo));
            }

            methodInfo = default(MethodInfo);
            return(false);
        }
예제 #2
0
        private static bool TryFindInvocation(MemberAccessExpressionSyntax memberAccess, QualifiedMethod expected, SyntaxNodeAnalysisContext context, out InvocationExpressionSyntax invocation)
        {
            switch (memberAccess.Expression)
            {
            case InvocationExpressionSyntax candidate when candidate.TryGetTarget(expected, context.SemanticModel, context.CancellationToken, out _):
                invocation = candidate;

                return(true);

            case IdentifierNameSyntax identifierName when context.SemanticModel.TryGetSymbol(identifierName, context.CancellationToken, out ILocalSymbol local) &&
                AssignedValue.TryGetSingle(local, context.SemanticModel, context.CancellationToken, out var expression) &&
                expression is InvocationExpressionSyntax candidate &&
                candidate.TryGetTarget(expected, context.SemanticModel, context.CancellationToken, out _):
                invocation = candidate;

                return(true);
            }

            invocation = null;
            return(false);
        }
예제 #3
0
        internal static bool TryGet(ExpressionSyntax expression, SyntaxNodeAnalysisContext context, out EventInfo eventInfo)
        {
            switch (expression)
            {
            case InvocationExpressionSyntax invocation when GetX.TryMatchGetEvent(invocation, context, out var member, out _, out _) &&
                member.Symbol is IEventSymbol @event:
                eventInfo = new EventInfo(member.ReflectedType, @event);

                return(true);
            }

            if (expression.IsEither(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression) &&
                context.SemanticModel.TryGetSymbol(expression, context.CancellationToken, out ISymbol local))
            {
                eventInfo = default(EventInfo);
                return(AssignedValue.TryGetSingle(local, context.SemanticModel, context.CancellationToken, out var assignedValue) &&
                       TryGet(assignedValue, context, out eventInfo));
            }

            eventInfo = default(EventInfo);
            return(false);
        }
예제 #4
0
        private static bool TryGet(ExpressionSyntax expression, SyntaxNodeAnalysisContext context, PooledSet <ExpressionSyntax> visited, out ITypeSymbol result, out ExpressionSyntax source)
        {
            switch (expression)
            {
            case MemberAccessExpressionSyntax memberAccess when memberAccess.Name.Identifier.ValueText == "ReturnType" &&
                memberAccess.Expression is InvocationExpressionSyntax invocation &&
                GetX.TryMatchGetMethod(invocation, context, out var reflectedMember, out _, out _, out _) &&
                reflectedMember.Match == FilterMatch.Single &&
                reflectedMember.Symbol is IMethodSymbol method:
                source = memberAccess;
                result = method.ReturnType;
                return(true);

            case MemberAccessExpressionSyntax memberAccess when memberAccess.Name.Identifier.ValueText == "FieldType" &&
                memberAccess.Expression is InvocationExpressionSyntax invocation &&
                GetX.TryMatchGetField(invocation, context, out var reflectedMember, out _, out _) &&
                reflectedMember.Match == FilterMatch.Single &&
                reflectedMember.Symbol is IFieldSymbol field:
                source = memberAccess;
                result = field.Type;
                return(true);

            case MemberAccessExpressionSyntax memberAccess when memberAccess.Name.Identifier.ValueText == "PropertyType" &&
                memberAccess.Expression is InvocationExpressionSyntax invocation &&
                GetX.TryMatchGetProperty(invocation, context, out var reflectedMember, out _, out _, out _) &&
                reflectedMember.Match == FilterMatch.Single &&
                reflectedMember.Symbol is IPropertySymbol field:
                source = memberAccess;
                result = field.Type;
                return(true);

            case TypeOfExpressionSyntax typeOf:
                source = typeOf;
                return(context.SemanticModel.TryGetType(typeOf.Type, context.CancellationToken, out result));

            case InvocationExpressionSyntax invocation when invocation.ArgumentList is ArgumentListSyntax args &&
                args.Arguments.Count == 0 &&
                invocation.TryGetMethodName(out var name) &&
                name == "GetType":
                switch (invocation.Expression)
                {
                case MemberAccessExpressionSyntax typeAccess:
                    source = invocation;
                    if (context.SemanticModel.TryGetType(typeAccess.Expression, context.CancellationToken, out result))
                    {
                        if (result is INamedTypeSymbol namedType &&
                            namedType.ConstructedFrom?.SpecialType == SpecialType.System_Nullable_T)
                        {
                            result = namedType.TypeArguments[0];
                        }

                        return(true);
                    }

                    return(false);

                case IdentifierNameSyntax _ when expression.TryFirstAncestor(out TypeDeclarationSyntax containingType):
                    source = invocation;

                    return(context.SemanticModel.TryGetSymbol(containingType, context.CancellationToken, out result));

                case MemberBindingExpressionSyntax memberBinding when memberBinding.Parent?.Parent is ConditionalAccessExpressionSyntax conditionalAccess:
                    source = invocation;
                    return(context.SemanticModel.TryGetType(conditionalAccess.Expression, context.CancellationToken, out result));
                }

                break;

            case InvocationExpressionSyntax candidate when TryMatchTypeGetType(candidate, context, out var typeName, out var ignoreCase):
                source = candidate;

                result = context.Compilation.GetTypeByMetadataName(typeName, ignoreCase.Value);
                return(result != null);

            case InvocationExpressionSyntax candidate when TryMatchAssemblyGetType(candidate, context, out var typeName, out var ignoreCase):
                source = candidate;

                result = Assembly.TryGet(candidate.Expression, context, out var assembly)
                        ? assembly.GetTypeByMetadataName(typeName, ignoreCase.Value)
                        : null;
                return(result != null);

            case InvocationExpressionSyntax invocation when invocation.TryGetTarget(KnownSymbol.Type.GetGenericTypeDefinition, context.SemanticModel, context.CancellationToken, out _) &&
                invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
                TryGet(memberAccess.Expression, context, visited, out var definingType, out _) &&
                definingType is INamedTypeSymbol namedType:
                source = invocation;

                result = namedType.ConstructedFrom;
                return(true);

            case InvocationExpressionSyntax invocation when GetX.TryMatchGetNestedType(invocation, context, out var reflectedMember, out _, out _):
                source = invocation;

                result = reflectedMember.Symbol as ITypeSymbol;
                return(result != null && reflectedMember.Match == FilterMatch.Single);

            case InvocationExpressionSyntax invocation when invocation.TryGetTarget(KnownSymbol.Type.MakeGenericType, context.SemanticModel, context.CancellationToken, out _) &&
                invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
                TypeArguments.TryCreate(invocation, context, out var typeArguments) &&
                typeArguments.TryGetArgumentsTypes(context, out var types):
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                {
                    if (visited.Add(invocation) &&
                        TryGet(memberAccess.Expression, context, visited, out var definition, out _) &&
                        definition is INamedTypeSymbol namedType)
                    {
                        source = invocation;
                        result = namedType.Construct(types);
                        return(result != null);
                    }
                }

                break;

            case ConditionalAccessExpressionSyntax conditionalAccess:
                source = conditionalAccess;
                return(TryGet(conditionalAccess.WhenNotNull, context, out result, out _));
            }

            if (expression.IsEither(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression) &&
                context.SemanticModel.TryGetSymbol(expression, context.CancellationToken, out ISymbol local))
            {
#pragma warning disable IDISP003 // Dispose previous before re-assigning.
                using (visited = visited.IncrementUsage())
#pragma warning restore IDISP003 // Dispose previous before re-assigning.
                {
                    source = null;
                    result = null;
                    return(AssignedValue.TryGetSingle(local, context.SemanticModel, context.CancellationToken, out var assignedValue) &&
                           visited.Add(assignedValue) &&
                           TryGet(assignedValue, context, visited, out result, out source));
                }
            }

            source = null;
            result = null;
            return(false);
        }