예제 #1
0
            public void AnalyzeAttribute(SyntaxNodeAnalysisContext context)
            {
                AttributeSyntax syntax           = (AttributeSyntax)context.Node;
                ISymbol         attributedSymbol = context.ContainingSymbol !;

                AttributeData?attr = syntax.FindAttributeData(attributedSymbol);

                if (attr?.AttributeClass?.ToDisplayString() == TypeNames.CustomMarshallerAttribute &&
                    attr.AttributeConstructor is not null)
                {
                    DiagnosticReporter managedTypeReporter = DiagnosticReporter.CreateForLocation(syntax.FindArgumentWithNameOrArity("managedType", 0).FindTypeExpressionOrNullLocation(), context.ReportDiagnostic);
                    INamedTypeSymbol   entryType           = (INamedTypeSymbol)attributedSymbol;

                    INamedTypeSymbol?managedTypeInAttribute = (INamedTypeSymbol?)attr.ConstructorArguments[0].Value;
                    if (managedTypeInAttribute is null)
                    {
                        managedTypeReporter.CreateAndReportDiagnostic(ManagedTypeMustBeNonNullRule, entryType.ToDisplayString());
                    }

                    if (!ManualTypeMarshallingHelper.TryResolveManagedType(
                            entryType,
                            managedTypeInAttribute,
                            ManualTypeMarshallingHelper.IsLinearCollectionEntryPoint(entryType),
                            (entryType, managedType) => managedTypeReporter.CreateAndReportDiagnostic(ManagedTypeMustBeClosedOrMatchArityRule, managedType, entryType), out ITypeSymbol managedType))
                    {
                        return;
                    }
                    DiagnosticReporter marshallerTypeReporter    = DiagnosticReporter.CreateForLocation(syntax.FindArgumentWithNameOrArity("marshallerType", 2).FindTypeExpressionOrNullLocation(), context.ReportDiagnostic);
                    ITypeSymbol?       marshallerTypeInAttribute = (ITypeSymbol?)attr.ConstructorArguments[2].Value;
                    if (marshallerTypeInAttribute is null)
                    {
                        marshallerTypeReporter.CreateAndReportDiagnostic(MarshallerTypeMustBeNonNullRule);
                    }
                    if (!ManualTypeMarshallingHelper.TryResolveMarshallerType(
                            entryType,
                            marshallerTypeInAttribute,
                            (entryType, marshallerType) => marshallerTypeReporter.CreateAndReportDiagnostic(MarshallerTypeMustBeClosedOrMatchArityRule, marshallerType, entryType),
                            out ITypeSymbol marshallerType))
                    {
                        return;
                    }

                    AnalyzeMarshallerType(
                        marshallerTypeReporter,
                        (INamedTypeSymbol)managedType,
                        (MarshalMode)attr.ConstructorArguments[1].Value,
                        (INamedTypeSymbol?)marshallerType,
                        ManualTypeMarshallingHelper.IsLinearCollectionEntryPoint(entryType));
                }
            }
        private static void SuppressMarkMethodsAsStaticDiagnosticIfNeeded(SuppressionAnalysisContext context, Diagnostic diagnostic)
        {
            SemanticModel model           = context.GetSemanticModel(diagnostic.Location.SourceTree);
            ISymbol       diagnosedSymbol = model.GetDeclaredSymbol(diagnostic.Location.SourceTree.GetRoot(context.CancellationToken).FindNode(diagnostic.Location.SourceSpan), context.CancellationToken);

            if (diagnosedSymbol.Kind != SymbolKind.Method)
            {
                return;
            }

            if (FindContainingEntryPointTypeAndManagedType(diagnosedSymbol.ContainingType) is (INamedTypeSymbol entryPointMarshallerType, INamedTypeSymbol managedType))
            {
                bool isLinearCollectionMarshaller = ManualTypeMarshallingHelper.IsLinearCollectionEntryPoint(entryPointMarshallerType);
                (MarshallerShape _, StatefulMarshallerShapeHelper.MarshallerMethods methods) = StatefulMarshallerShapeHelper.GetShapeForType(diagnosedSymbol.ContainingType, managedType, isLinearCollectionMarshaller, context.Compilation);
                if (methods.IsShapeMethod((IMethodSymbol)diagnosedSymbol))
                {
                    // If we are a method of the shape on the stateful marshaller shape, then we need to be our current shape.
                    // So, suppress the diagnostic to make this method static, as that would break the shape.
                    context.ReportSuppression(Suppression.Create(MarkMethodsAsStaticSuppression, diagnostic));
                }
            }
        }
예제 #3
0
        private static async Task <Solution> AddMissingMembers(Document doc, SyntaxNode node, HashSet <string> missingMemberNames, CancellationToken ct)
        {
            var model = await doc.GetSemanticModelAsync(ct).ConfigureAwait(false);

            var entryPointTypeSymbol = (INamedTypeSymbol)model.GetEnclosingSymbol(node.SpanStart, ct);

            // TODO: Convert to use the IOperation tree once IAttributeOperation is available
            var managedTypeSymbolInAttribute = GetManagedTypeInAttributeSyntax(node.GetLocation(), entryPointTypeSymbol);

            bool isLinearCollectionMarshaller = ManualTypeMarshallingHelper.IsLinearCollectionEntryPoint(entryPointTypeSymbol);

            // Explicitly ignore the generic arity mismatch diagnostics as we will only reach here if there are no mismatches.
            // The analyzer will not for missing members if the managed type cannot be resolved.
            ManualTypeMarshallingHelper.TryResolveManagedType(entryPointTypeSymbol, ManualTypeMarshallingHelper.ReplaceGenericPlaceholderInType(managedTypeSymbolInAttribute, entryPointTypeSymbol, model.Compilation), isLinearCollectionMarshaller, IgnoreArityMismatch, out ITypeSymbol managedType);

            SymbolEditor editor = SymbolEditor.Create(doc.Project.Solution);

            INamedTypeSymbol marshallerType = (INamedTypeSymbol)model.GetSymbolInfo(node, ct).Symbol;

            await editor.EditOneDeclarationAsync(marshallerType, (editor, decl) => AddMissingMembers(editor, decl, marshallerType, managedType, missingMemberNames, isLinearCollectionMarshaller), ct).ConfigureAwait(false);

            return(editor.ChangedSolution);
        }
            private void AnalyzeManagedTypeMarshallingInfo(
                ITypeSymbol managedType,
                DiagnosticReporter diagnosticFactory,
                INamedTypeSymbol?entryType)
            {
                if (entryType is null)
                {
                    diagnosticFactory.CreateAndReportDiagnostic(
                        MarshallerEntryPointTypeMustBeNonNullRule,
                        managedType.ToDisplayString());
                    return;
                }

                if (!ManualTypeMarshallingHelper.HasEntryPointMarshallerAttribute(entryType))
                {
                    diagnosticFactory.CreateAndReportDiagnostic(
                        MarshallerEntryPointTypeMustHaveCustomMarshallerAttributeWithMatchingManagedTypeRule,
                        entryType.ToDisplayString(),
                        managedType.ToDisplayString());
                    return;
                }

                bool isLinearCollectionMarshaller = ManualTypeMarshallingHelper.IsLinearCollectionEntryPoint(entryType);

                if (entryType.IsUnboundGenericType)
                {
                    if (managedType is not INamedTypeSymbol namedManagedType)
                    {
                        diagnosticFactory.CreateAndReportDiagnostic(
                            GenericEntryPointMarshallerTypeMustBeClosedOrMatchArityRule,
                            entryType.ToDisplayString(),
                            managedType.ToDisplayString());
                        return;
                    }
                    if (!ManualTypeMarshallingHelper.TryResolveEntryPointType(
                            namedManagedType,
                            entryType,
                            isLinearCollectionMarshaller,
                            (managedType, entryType) => diagnosticFactory.CreateAndReportDiagnostic(
                                GenericEntryPointMarshallerTypeMustBeClosedOrMatchArityRule,
                                entryType.ToDisplayString(),
                                managedType.ToDisplayString()),
                            out ITypeSymbol resolvedEntryType))
                    {
                        return;
                    }
                    entryType = (INamedTypeSymbol)resolvedEntryType;
                }

                if (!ManualTypeMarshallingHelper.TryGetMarshallersFromEntryTypeIgnoringElements(
                        entryType,
                        managedType,
                        _compilation,
                        (entryType, managedType) =>
                        diagnosticFactory.CreateAndReportDiagnostic(
                            GenericEntryPointMarshallerTypeMustBeClosedOrMatchArityRule,
                            entryType.ToDisplayString(),
                            managedType.ToDisplayString()), out _))
                {
                    diagnosticFactory.CreateAndReportDiagnostic(
                        MarshallerEntryPointTypeMustHaveCustomMarshallerAttributeWithMatchingManagedTypeRule,
                        entryType.ToDisplayString(),
                        managedType.ToDisplayString());
                }
            }