private void AnalyzeInvocation(SyntaxNodeAnalysisContext context, TypeSizeResolver resolver) { var semantics = context.SemanticModel; var @params = (context.Node as MethodDeclarationSyntax)?.ParameterList.Parameters ?? (context.Node as ConstructorDeclarationSyntax)?.ParameterList.Parameters ?? (context.Node as DelegateDeclarationSyntax)?.ParameterList.Parameters ?? (context.Node as LocalFunctionStatementSyntax)?.ParameterList.Parameters; foreach (var param in @params !) { var symbol = semantics.GetDeclaredSymbol(param); if (symbol is null) { throw new Exception("null param symbol. not sure what to do here to be honest. :("); } var advantageousToPassByRef = resolver.AdvantageousToPassByRef(symbol); var contextSymbol = semantics.GetDeclaredSymbol(context.Node) !; if (CanModifyMethod(contextSymbol) && advantageousToPassByRef) { context.ReportDiagnostic(Diagnostic.Create(Rule, param.GetLocation())); } }
// BUG: does not work with nested types protected override void GenerateFromSymbol(GeneratorExecutionContext context, INamedTypeSymbol symbol) { var equalsCandidates = symbol.GetMembers(nameof(Equals)) .Where(member => member is IMethodSymbol method && SymbolEqualityComparer.Default.Equals(method.ReturnType, context.Compilation.GetSpecialType(SpecialType.System_Boolean)) && method.Parameters.Length == 1 && SymbolEqualityComparer.Default.Equals(method.Parameters[0].Type, symbol)); var ghcCandidates = symbol.GetMembers(nameof(GetHashCode)) .Where(member => member is IMethodSymbol method && SymbolEqualityComparer.Default.Equals(method.ReturnType, context.Compilation.GetSpecialType(SpecialType.System_Int32)) && method.Parameters.Length == 0); var builder = new StringBuilder(); if (ghcCandidates.Count() == 0) { var ghcString = GenerateHashCodeOfAllFields(context, symbol); builder.AppendLine(string.Format(GetHashCodeTemplate, ghcString)); } string passByRefModifier = string.Empty; if (symbol.IsValueType) { var shouldPassByRef = new TypeSizeResolver(context.Compilation).AdvantageousToPassByRef(symbol); passByRefModifier = shouldPassByRef ? "in " : ""; builder.AppendLine(string.Format(ValueTypeEqualsTemplate, passByRefModifier, symbol.Name)); if (equalsCandidates.Count() == 0) { var compString = GenerateComparisonOfAllFields(context, symbol); builder.AppendLine(string.Format(ValueTypeStandardEqualsTemplate, symbol.Name, compString)); } } else { builder.AppendLine(string.Format(RefTypeEqualsTemplate, symbol.Name)); if (equalsCandidates.Count() == 0) { var compString = GenerateComparisonOfAllFields(context, symbol); builder.AppendLine(string.Format(RefTypeStandardEqualsTemplate, symbol.Name, compString)); } } builder.AppendLine(string.Format(EquatableTemplate, passByRefModifier, symbol.Name)); var source = string.Format(TypeTemplate, symbol.ContainingNamespace, symbol.IsValueType ? "struct" : "class", symbol.Name, builder.ToString()); context.AddSource($"{symbol.Name}.EqualityMembers.cs", SourceText.From(source, Encoding.UTF8)); }
private void InitializeCompilation(CompilationStartAnalysisContext context) { var compResolver = new TypeSizeResolver(context.Compilation); context.RegisterSyntaxNodeAction( invoc => AnalyzeInvocation(invoc, compResolver), SyntaxKind.LocalFunctionStatement, SyntaxKind.MethodDeclaration, SyntaxKind.ConstructorDeclaration, SyntaxKind.DelegateDeclaration ); }
protected override void GenerateFromSymbol(GeneratorExecutionContext context, INamedTypeSymbol symbol) { var builder = new StringBuilder(); var resolver = new TypeSizeResolver(context.Compilation); var explicitName = context.Compilation.GetTypeByMetadataName(FluentNameAttributeName) !; foreach (var member in symbol.GetMembers()) { if (member.IsStatic || member is not IPropertySymbol or IFieldSymbol || member.DeclaredAccessibility is not Accessibility.Public or Accessibility.Internal || (member is IPropertySymbol { IsIndexer: true }))