示例#1
0
        private void RegisterAttribute(AttributeBuilderDetails variableDetails, AttributeData attribute)
        {
            switch (variableDetails.Target)
            {
            case AttributeTarget.ReturnValue:
                Attributes.RegisterReturnValueAttribute(variableDetails.Symbol, attribute);
                break;

            default:
                Attributes.RegisterAttribute(variableDetails.Symbol, attribute);
                break;
            }
        }
示例#2
0
        private void RegisterAttribute(AttributeBuilderDetails variableDetails, AttributeData attribute)
        {
            Log.Info($"Registering attribute '{attribute.AttributeClass}' on element '{variableDetails.Symbol}'");
            switch (variableDetails.Target)
            {
            case AttributeTarget.ReturnValue:
                Attributes.RegisterReturnValueAttribute(variableDetails.Symbol, attribute);
                break;

            default:
                Attributes.RegisterAttribute(variableDetails.Symbol, attribute);
                break;
            }
        }
示例#3
0
        private void HandleAttributeBuilderInvocation(InvocationExpressionSyntax node, IMethodSymbol method)
        {
            // add attribute
            if (method.Name == "Add" && node.Expression.Kind() == SyntaxKind.SimpleMemberAccessExpression)
            {
                var memberAccess = (MemberAccessExpressionSyntax)node.Expression;

                AttributeBuilderDetails variableDetails = null;
                if (memberAccess.Expression.Kind() == SyntaxKind.InvocationExpression)
                {
                    // chained method calls
                    variableDetails = this.GetAttributesBuilderVariable(memberAccess.Expression);
                }
                else
                {
                    var symbol = _semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol;
                    if (symbol != null && symbol.Kind == SymbolKind.Local)
                    {
                        // variable access
                        _variables.TryGetValue(symbol.Name, out variableDetails);
                    }
                }

                if (variableDetails == null)
                {
                    throw ReportError(Diagnostic.Create(PhaseErrors.PH012, node.Expression.GetLocation()));
                }

                foreach (var argument in node.ArgumentList.Arguments)
                {
                    if (argument.Expression.Kind() != SyntaxKind.ObjectCreationExpression)
                    {
                        throw ReportError(Diagnostic.Create(PhaseErrors.PH013, argument.GetLocation()));
                    }

                    var newAttribute = (ObjectCreationExpressionSyntax)argument.Expression;
                    var constructor  = (IMethodSymbol)_semanticModel.GetSymbolInfo(newAttribute).Symbol;

                    var constructorArguments = new List <TypedConstant>();
                    var namedArguments       = new Dictionary <string, TypedConstant>();

                    for (var i = 0; i < newAttribute.ArgumentList.Arguments.Count; i++)
                    {
                        var ctorArgument = newAttribute.ArgumentList.Arguments[i];
                        var typeInfo     = _semanticModel.GetTypeInfo(ctorArgument.Expression);
                        var value        = _semanticModel.GetConstantValue(ctorArgument.Expression);
                        if (!value.HasValue)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                ctorArgument.GetLocation(), constructor.Parameters[i].Name));
                        }
                        constructorArguments.Add(CreateTypedConstant(typeInfo.Type, value.Value));
                    }

                    if (newAttribute.Initializer != null)
                    {
                        foreach (var initializerStatement in newAttribute.Initializer.Expressions)
                        {
                            if (initializerStatement.Kind() != SyntaxKind.SimpleAssignmentExpression)
                            {
                                throw ReportError(Diagnostic.Create(PhaseErrors.PH014, initializerStatement.GetLocation()));
                            }

                            var assignment = (AssignmentExpressionSyntax)initializerStatement;
                            var symbol     = _semanticModel.GetSymbolInfo(assignment.Left).Symbol;
                            var typeInfo   = _semanticModel.GetTypeInfo(assignment.Right);
                            var value      = _semanticModel.GetConstantValue(assignment.Right);

                            if (!value.HasValue)
                            {
                                throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                    assignment.Right.GetLocation(), symbol.Name));
                            }

                            namedArguments[symbol.Name] = CreateTypedConstant(typeInfo.Type, value.Value);
                        }
                    }

                    this.RegisterAttribute(variableDetails, new CustomAttributeData(constructor, constructorArguments, namedArguments));;
                }
            }
            else
            {
                Debug.Fail("Missing handling of method");
            }
        }
示例#4
0
        private AttributeBuilderDetails GetAttributesBuilderVariable(ExpressionSyntax variableInitializer)
        {
            if (variableInitializer.Kind() == SyntaxKind.InvocationExpression)
            {
                InvocationExpressionSyntax invocation = (InvocationExpressionSyntax)variableInitializer;

                var invokedSymbol = _semanticModel.GetSymbolInfo(invocation).Symbol;
                if (invokedSymbol?.ContainingType == null || !invokedSymbol.ContainingType.Equals(AttributesContextType))
                {
                    return(null);
                }
                switch (invokedSymbol.Name)
                {
                case "Assembly":
                {
                    IAssemblySymbol assembly;
                    if (invocation.ArgumentList.Arguments.Count == 0)
                    {
                        assembly = _semanticModel.Compilation.Assembly;
                    }
                    else
                    {
                        var firstArgument = _semanticModel.GetConstantValue(invocation.ArgumentList.Arguments[0]);
                        if (!firstArgument.HasValue)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.Arguments[0].GetLocation(), ((IMethodSymbol)invokedSymbol).Parameters[0].Name));
                        }

                        var assemblyName = firstArgument.ToString();
                        var assemblies   = _semanticModel.Compilation.References
                                           .Select(r => _semanticModel.Compilation.GetAssemblyOrModuleSymbol(r))
                                           .Where(r => r.Kind == SymbolKind.Assembly)
                                           .ToArray();

                        if (_semanticModel.Compilation.Assembly.Name == assemblyName)
                        {
                            assembly = _semanticModel.Compilation.Assembly;
                        }
                        else
                        {
                            assembly = (IAssemblySymbol)assemblies.FirstOrDefault(r => r.Name == assemblyName);
                        }


                        if (assembly == null)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH005,
                                                                invocation.ArgumentList.Arguments[0].GetLocation(),
                                                                assemblyName, string.Join(", ", assemblies.Select(a => a.Name))
                                                                ));
                        }
                    }

                    return(new AttributeBuilderDetails
                        {
                            Symbol = assembly,
                            Target = AttributeTarget.Default
                        });
                }

                case "Type":
                {
                    var         method = (IMethodSymbol)invokedSymbol;
                    ITypeSymbol type;
                    if (method.TypeArguments.Length == 1)
                    {
                        type = method.TypeArguments[0].OriginalDefinition ?? method.TypeArguments[0];
                    }
                    else
                    {
                        var typeofExpr = invocation.ArgumentList.Arguments[0];
                        if (typeofExpr.Expression.Kind() != SyntaxKind.TypeOfExpression)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH016,
                                                                invocation.ArgumentList.Arguments[0].GetLocation()
                                                                ));
                        }
                        type = _semanticModel.GetTypeInfo(((TypeOfExpressionSyntax)typeofExpr.Expression).Type).Type;
                    }

                    return(new AttributeBuilderDetails
                        {
                            Symbol = type,
                            Target = AttributeTarget.Default
                        });
                }

                case "Member":
                {
                    if (!(invocation.ArgumentList.Arguments[0].Expression is LambdaExpressionSyntax lambda) ||
                        lambda.Body == null || lambda.Body.Kind() == SyntaxKind.Block)
                    {
                        throw ReportError(Diagnostic.Create(PhaseErrors.PH006,
                                                            invocation.ArgumentList.Arguments[0].GetLocation()
                                                            ));
                    }

                    AttributeBuilderDetails details = new AttributeBuilderDetails();

                    var member = _semanticModel.GetSymbolInfo(lambda.Body).Symbol;
                    details.Symbol = member.OriginalDefinition ?? member;

                    string targetName = null;
                    for (int i = 1; i < invocation.ArgumentList.Arguments.Count; i++)
                    {
                        var argument = invocation.ArgumentList.Arguments[i];
                        var type     = _semanticModel.GetTypeInfo(argument.Expression).Type;

                        var value = _semanticModel.GetConstantValue(argument.Expression);
                        if (!value.HasValue)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.Arguments[0].GetLocation(), ((IMethodSymbol)invokedSymbol).Parameters[i].Name));
                        }

                        if (type.Equals(_attributeTargetType))
                        {
                            details.Target = (AttributeTarget)(int)value.Value;
                        }
                        else if (type.SpecialType == SpecialType.System_String)
                        {
                            targetName = value.Value.ToString();
                        }
                    }

                    if (targetName != null)
                    {
                        if (details.Target == AttributeTarget.Parameter)
                        {
                            if (details.Symbol.Kind == SymbolKind.Method)
                            {
                                details.Symbol =
                                    ((IMethodSymbol)details.Symbol).Parameters.FirstOrDefault(p => p.Name == targetName);
                            }
                        }
                    }

                    switch (details.Target)
                    {
                    case AttributeTarget.Default:
                        break;

                    case AttributeTarget.ReturnValue:
                        if (details.Symbol.Kind != SymbolKind.Method)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.GetLocation(), details.Target, SymbolKind.Property));
                        }
                        break;

                    case AttributeTarget.Parameter:
                        if (details.Symbol == null)
                        {
                            var parameterList = member.Kind == SymbolKind.Method
                                            ? ((IMethodSymbol)member).Parameters.Select(p => p.Name)
                                            : Enumerable.Empty <string>();

                            throw ReportError(Diagnostic.Create(PhaseErrors.PH008,
                                                                invocation.ArgumentList.GetLocation(),
                                                                member.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat),
                                                                targetName, string.Join(", ", parameterList)));
                        }
                        break;

                    case AttributeTarget.Getter:
                    {
                        if (details.Symbol.Kind != SymbolKind.Property)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.GetLocation(), details.Target, SymbolKind.Property));
                        }

                        details.Symbol = ((IPropertySymbol)details.Symbol).GetMethod;
                    }
                    break;

                    case AttributeTarget.Setter:
                    {
                        if (details.Symbol.Kind != SymbolKind.Property)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.GetLocation(), details.Target, SymbolKind.Property));
                        }

                        details.Symbol = ((IPropertySymbol)details.Symbol).SetMethod;
                    }
                    break;

                    case AttributeTarget.Adder:
                    {
                        if (details.Symbol.Kind != SymbolKind.Event)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.GetLocation(), details.Target, SymbolKind.Event));
                        }

                        details.Symbol = ((IEventSymbol)details.Symbol).AddMethod;
                    }
                    break;

                    case AttributeTarget.Remover:
                    {
                        if (details.Symbol.Kind != SymbolKind.Event)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.GetLocation(), details.Target, SymbolKind.Event));
                        }

                        details.Symbol = ((IEventSymbol)details.Symbol).RemoveMethod;
                    }
                    break;
                    }

                    return(details);
                }

                case "Constructor":
                {
                    if (!(invocation.ArgumentList.Arguments[0].Expression is LambdaExpressionSyntax lambda) ||
                        lambda.Body == null || lambda.Body.Kind() == SyntaxKind.Block)
                    {
                        throw ReportError(Diagnostic.Create(PhaseErrors.PH006,
                                                            invocation.ArgumentList.Arguments[0].GetLocation()
                                                            ));
                    }

                    var member = _semanticModel.GetSymbolInfo(lambda.Body).Symbol;
                    if (member.Kind != SymbolKind.Method ||
                        ((IMethodSymbol)member).MethodKind != MethodKind.Constructor)
                    {
                        throw ReportError(Diagnostic.Create(PhaseErrors.PH009,
                                                            invocation.ArgumentList.Arguments[0].GetLocation()));
                    }

                    AttributeBuilderDetails details = new AttributeBuilderDetails();
                    details.Symbol = member.OriginalDefinition ?? member;

                    return(details);
                }

                case "Event":
                {
                    var eventName = _semanticModel.GetConstantValue(invocation.ArgumentList.Arguments[0].Expression);
                    if (!eventName.HasValue)
                    {
                        throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                            invocation.ArgumentList.Arguments[0].GetLocation(), ((IMethodSymbol)invokedSymbol).Parameters[0].Name));
                    }

                    var type   = ((IMethodSymbol)invokedSymbol).TypeArguments[0];
                    var events = type.GetMembers()
                                 .Where(m => m.Kind == SymbolKind.Event);
                    var eventSymbol = events.FirstOrDefault(e => e.Name == eventName.Value.ToString());
                    if (!eventName.HasValue)
                    {
                        throw ReportError(Diagnostic.Create(PhaseErrors.PH010,
                                                            invocation.ArgumentList.Arguments[0].GetLocation(), eventName.Value,
                                                            type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat),
                                                            string.Join(", ", events.Select(e => e.Name))));
                    }


                    AttributeBuilderDetails details = new AttributeBuilderDetails();
                    details.Symbol = eventSymbol.OriginalDefinition ?? eventSymbol;

                    for (int i = 1; i < invocation.ArgumentList.Arguments.Count; i++)
                    {
                        var argument     = invocation.ArgumentList.Arguments[i];
                        var argumentType = _semanticModel.GetTypeInfo(argument).Type;

                        var value = _semanticModel.GetConstantValue(argument.Expression);
                        if (!value.HasValue)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.Arguments[0].GetLocation(), ((IMethodSymbol)invokedSymbol).Parameters[i].Name));
                        }

                        if (argumentType.Equals(_attributeTargetType))
                        {
                            details.Target = (AttributeTarget)(int)value.Value;
                        }
                    }

                    switch (details.Target)
                    {
                    case AttributeTarget.Default:
                        break;

                    case AttributeTarget.Adder:
                    {
                        if (details.Symbol.Kind != SymbolKind.Event)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.GetLocation(), details.Target, SymbolKind.Event));
                        }

                        details.Symbol = ((IEventSymbol)details.Symbol).AddMethod;
                    }
                    break;

                    case AttributeTarget.Remover:
                    {
                        if (details.Symbol.Kind != SymbolKind.Event)
                        {
                            throw ReportError(Diagnostic.Create(PhaseErrors.PH004,
                                                                invocation.ArgumentList.GetLocation(), details.Target, SymbolKind.Event));
                        }

                        details.Symbol = ((IEventSymbol)details.Symbol).RemoveMethod;
                    }
                    break;
                    }

                    return(details);
                }
                }
            }

            return(null);
        }