Example #1
0
        internal GeneratorBase(
            SourceTypeInfo sourceTypeInfo)
        {
            if (sourceTypeInfo is null)
            {
                throw new ArgumentNullException(nameof(sourceTypeInfo));
            }

            this.SourceTypeInfo = sourceTypeInfo;
        }
        public void Execute(
            GeneratorExecutionContext context)
        {
            LaunchDebugger(context);

            if (context.SyntaxReceiver is not SyntaxReceiver receiver)
            {
                return;
            }

            var knownTypes     = new KnownTypes(context.Compilation);
            var candidateTypes = new List <SourceTypeInfo>();

            foreach (var candidateSyntax in receiver.CandidateSyntaxes)
            {
                var sourceTypeInfo = SourceTypeInfo.TryCreate(
                    context,
                    candidateSyntax,
                    knownTypes,
                    this._options,
                    out var diagnostics);

                context.ReportDiagnostics(diagnostics);

                if (sourceTypeInfo is null)
                {
                    continue;
                }

                candidateTypes.Add(sourceTypeInfo);
            }

            var typeMap = candidateTypes.ToDictionary(
                x => x.TypeSymbol,
                (IEqualityComparer <ITypeSymbol>)SymbolEqualityComparer.Default);

            foreach (var candidateType in candidateTypes.ToArray())
            {
                if (!candidateType.HasComparableAttribute)
                {
                    continue;
                }

                var options = candidateType.GenerateOptions;

                foreach (var member in candidateType.Members)
                {
                    if (options.GenerateGenericComparable ||
                        options.GenerateNonGenericComparable ||
                        options.GenerateOperators ||
                        options.GenerateStructuralComparable)
                    {
                        var memberType = member.Type;

                        if (knownTypes.IsGenericComparable(memberType))
                        {
                            continue;
                        }

                        if (knownTypes.IsNonGenericComparable(memberType))
                        {
                            continue;
                        }

                        if (knownTypes.IsStructuralComparable(memberType))
                        {
                            continue;
                        }

                        if (typeMap.TryGetValue(memberType, out var targetType) &&
                            targetType.HasComparableAttribute)
                        {
                            continue;
                        }

                        if (!knownTypes.TryGetNullableUnderlyingType(memberType, out var underlyingType))
                        {
                            continue;
                        }

                        if (typeMap.TryGetValue(underlyingType, out var targetType2) &&
                            targetType2.HasComparableAttribute)
                        {
                            continue;
                        }

                        var memberLocation = member.Symbol.DeclaringSyntaxReferences
                                             .Select(x => Location.Create(x.SyntaxTree, x.Span))
                                             .ToArray();

                        context.ReportDiagnostic(
                            DiagnosticFactory.MemberIsNotComparable(
                                candidateType.FullName,
                                member.Name,
                                member.TypeName,
                                memberLocation[0],
                                memberLocation.Skip(1)));
                    }
                }
            }

            foreach (var sourceType in candidateTypes)
            {
                var    options  = sourceType.GenerateOptions;
                string fullName = sourceType.FullName;

                GenerateCode(
                    context,
                    new CommonGenerator(sourceType),
                    $"{fullName}_Common.cs");

                if (options.GenerateEqualityContract &&
                    !sourceType.HasEqualityContract &&
                    !sourceType.IsValueType)
                {
                    GenerateCode(
                        context,
                        new EqualityContractGenerator(sourceType),
                        $"{fullName}_EqualityContract.cs");
                }

                if (options.GenerateEquatable &&
                    !sourceType.IsEquatable)
                {
                    GenerateCode(
                        context,
                        new EquatableGenerator(sourceType),
                        $"{fullName}_Equatable.cs");
                }

                if (options.GenerateGenericComparable &&
                    !sourceType.IsGenericComparable)
                {
                    GenerateCode(
                        context,
                        new GenericComparableGenerator(sourceType),
                        $"{fullName}_GenericComparable.cs");
                }

                if (options.GenerateNonGenericComparable &&
                    !sourceType.IsNonGenericComparable)
                {
                    GenerateCode(
                        context,
                        new NonGenericComparableGenerator(sourceType),
                        $"{fullName}_NonGenericComparable.cs");
                }

                if (options.OverrideObjectMethods)
                {
                    if (!sourceType.OverridesObjectEquals)
                    {
                        GenerateCode(
                            context,
                            new ObjectEqualsGenerator(sourceType),
                            $"{fullName}_ObjectEquals.cs");
                    }

                    if (!sourceType.OverridesObjectGetHashCode)
                    {
                        GenerateCode(
                            context,
                            new ObjectGetHashCodeGenerator(sourceType),
                            $"{fullName}_ObjectGetHashCode.cs");
                    }
                }

                if (options.GenerateOperators &&
                    !sourceType.DefinedNullableParameterOperator)
                {
                    GenerateCode(
                        context,
                        new EqualityOperatorsGenerator(sourceType),
                        $"{fullName}_EqualityOperators.cs");

                    if (sourceType.HasComparableAttribute)
                    {
                        GenerateCode(
                            context,
                            new ComparisonOperatorsGenerator(sourceType),
                            $"{fullName}_ComparisonOperators.cs");
                    }
                }
            }
        }