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)); } } }
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()); } }