private AttributeListSyntax BuildUnmanagedFunctionPointerAttribute(DllImportData dllImportData)
        {
            var charset = string.Format("CharSet = CharSet.{0}", dllImportData.CharacterSet);
            var charsetArgument = Syntax.AttributeArgument(Syntax.ParseExpression(charset));

            var setLastError = string.Format("SetLastError = {0}", dllImportData.SetLastError.ToProperString());
            var setLastErrorArgument = Syntax.AttributeArgument(Syntax.ParseExpression(setLastError));

            var callingConvention = string.Format("CallingConvention.{0}", dllImportData.CallingConvention);
            var callingConventionArgument = Syntax.AttributeArgument(Syntax.ParseExpression(callingConvention));

            var arguments = Syntax.SeparatedList(callingConventionArgument).Add(setLastErrorArgument, charsetArgument);

            if (dllImportData.BestFitMapping.HasValue)
            {
                var bestFitMapping = string.Format("BestFitMapping = {0}", dllImportData.BestFitMapping.ToProperString());
                var bestFitMappingArgument = Syntax.AttributeArgument(Syntax.ParseExpression(bestFitMapping));

                arguments = arguments.Add(bestFitMappingArgument);
            }

            if (dllImportData.ThrowOnUnmappableCharacter.HasValue)
            {
                var throwOnUnmappableCharacter = string.Format("ThrowOnUnmappableChar = {0}", dllImportData.ThrowOnUnmappableCharacter.ToProperString());
                var throwOnUnmappableCharacterArgument = Syntax.AttributeArgument(Syntax.ParseExpression(throwOnUnmappableCharacter));

                arguments = arguments.Add(throwOnUnmappableCharacterArgument);
            }

            var unmanagedFunctionPointerAttribute = Syntax.Attribute(Syntax.ParseName("UnmanagedFunctionPointer"))
                                                          .WithArgumentList(Syntax.AttributeArgumentList(arguments));

            return Syntax.AttributeList(Syntax.SeparatedList(unmanagedFunctionPointerAttribute));
        }
            public void AnalyzeSymbol(SymbolAnalysisContext context)
            {
                var methodSymbol = (IMethodSymbol)context.Symbol;

                if (methodSymbol == null)
                {
                    return;
                }

                DllImportData dllImportData = methodSymbol.GetDllImportData();

                if (dllImportData == null)
                {
                    return;
                }

                AttributeData dllAttribute    = methodSymbol.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Equals(_dllImportType));
                Location      defaultLocation = dllAttribute == null?methodSymbol.Locations.FirstOrDefault() : GetAttributeLocation(dllAttribute);

                // CA1401 - PInvoke methods should not be visible
                if (methodSymbol.GetResultantVisibility() == SymbolVisibility.Public)
                {
                    context.ReportDiagnostic(context.Symbol.CreateDiagnostic(RuleCA1401, methodSymbol.Name));
                }

                // CA2101 - Specify marshalling for PInvoke string arguments
                if (dllImportData.BestFitMapping != false)
                {
                    bool appliedCA2101ToMethod = false;
                    foreach (IParameterSymbol parameter in methodSymbol.Parameters)
                    {
                        if (parameter.Type.SpecialType == SpecialType.System_String || parameter.Type.Equals(_stringBuilderType))
                        {
                            AttributeData marshalAsAttribute = parameter.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Equals(_marshalAsType));
                            CharSet?      charSet            = marshalAsAttribute == null
                                ? dllImportData.CharacterSet
                                : MarshalingToCharSet(GetParameterMarshaling(marshalAsAttribute));

                            // only unicode marshaling is considered safe
                            if (charSet != CharSet.Unicode)
                            {
                                if (marshalAsAttribute != null)
                                {
                                    // track the diagnostic on the [MarshalAs] attribute
                                    Location marshalAsLocation = GetAttributeLocation(marshalAsAttribute);
                                    context.ReportDiagnostic(Diagnostic.Create(RuleCA2101, marshalAsLocation));
                                }
                                else if (!appliedCA2101ToMethod)
                                {
                                    // track the diagnostic on the [DllImport] attribute
                                    appliedCA2101ToMethod = true;
                                    context.ReportDiagnostic(Diagnostic.Create(RuleCA2101, defaultLocation));
                                }
                            }
                        }
                    }

                    // only unicode marshaling is considered safe, but only check this if we haven't already flagged the attribute
                    if (!appliedCA2101ToMethod && dllImportData.CharacterSet != CharSet.Unicode &&
                        (methodSymbol.ReturnType.SpecialType == SpecialType.System_String || methodSymbol.ReturnType.Equals(_stringBuilderType)))
                    {
                        context.ReportDiagnostic(Diagnostic.Create(RuleCA2101, defaultLocation));
                    }
                }
            }