Exemple #1
0
        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));
        }
Exemple #3
0
        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
                );
        }
Exemple #4
0
        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
                }))