public ReturnStatementCollector([NotNull] SequenceTypeInfo sequenceTypeInfo, OperationBlockAnalysisContext context)
            {
                Guard.NotNull(sequenceTypeInfo, nameof(sequenceTypeInfo));

                this.sequenceTypeInfo = sequenceTypeInfo;
                this.context          = context;
            }
        private static void AnalyzeCodeBlock(OperationBlockAnalysisContext context, [NotNull] SequenceTypeInfo sequenceTypeInfo)
        {
            if (!IsInMethodThatReturnsEnumerable(context.OwningSymbol, sequenceTypeInfo))
            {
                return;
            }

            var collector = new ReturnStatementCollector(sequenceTypeInfo, context);

            collector.VisitBlocks(context.OperationBlocks);

            AnalyzeReturnStatements(collector.ReturnStatements, context);
        }
        private static void RegisterCompilationStart([NotNull] CompilationStartAnalysisContext startContext)
        {
            var sequenceTypeInfo = new SequenceTypeInfo(startContext.Compilation);

            startContext.RegisterOperationBlockAction(context => AnalyzeCodeBlockAction(context, sequenceTypeInfo));
        }
 private static bool IsInMethodThatReturnsEnumerable([NotNull] ISymbol owningSymbol,
                                                     [NotNull] SequenceTypeInfo sequenceTypeInfo)
 {
     return(owningSymbol is IMethodSymbol method && !method.ReturnsVoid &&
            sequenceTypeInfo.IsEnumerable(method.ReturnType));
 }
Пример #5
0
        public ParseStatus ParseTypeSymbol(
            ITypeSymbol typeSymbol,
            bool isReadonly,
            out ITypeInfo typeInfo)
        {
            this.ParseNullable_(ref typeSymbol, out var isNullable);

            var primitiveType =
                SchemaPrimitiveTypesUtil.GetPrimitiveTypeFromTypeSymbol(
                    typeSymbol);

            if (primitiveType != SchemaPrimitiveType.UNDEFINED)
            {
                switch (primitiveType)
                {
                case SchemaPrimitiveType.BOOLEAN: {
                    typeInfo = new BoolTypeInfo(
                        typeSymbol,
                        isReadonly,
                        isNullable);
                    return(ParseStatus.SUCCESS);
                }

                case SchemaPrimitiveType.BYTE:
                case SchemaPrimitiveType.SBYTE:
                case SchemaPrimitiveType.INT16:
                case SchemaPrimitiveType.UINT16:
                case SchemaPrimitiveType.INT32:
                case SchemaPrimitiveType.UINT32:
                case SchemaPrimitiveType.INT64:
                case SchemaPrimitiveType.UINT64: {
                    typeInfo = new IntegerTypeInfo(
                        typeSymbol,
                        SchemaTypeKind.INTEGER,
                        SchemaPrimitiveTypesUtil.ConvertNumberToInt(
                            SchemaPrimitiveTypesUtil
                            .ConvertPrimitiveToNumber(primitiveType)),
                        isReadonly,
                        isNullable);
                    return(ParseStatus.SUCCESS);
                }

                case SchemaPrimitiveType.SN8:
                case SchemaPrimitiveType.UN8:
                case SchemaPrimitiveType.SN16:
                case SchemaPrimitiveType.UN16:
                case SchemaPrimitiveType.SINGLE:
                case SchemaPrimitiveType.DOUBLE: {
                    typeInfo = new FloatTypeInfo(
                        typeSymbol,
                        SchemaTypeKind.FLOAT,
                        SchemaPrimitiveTypesUtil
                        .ConvertPrimitiveToNumber(primitiveType),
                        isReadonly,
                        isNullable);
                    return(ParseStatus.SUCCESS);
                }

                case SchemaPrimitiveType.CHAR: {
                    typeInfo = new CharTypeInfo(
                        typeSymbol,
                        isReadonly,
                        isNullable);
                    return(ParseStatus.SUCCESS);
                }

                case SchemaPrimitiveType.ENUM: {
                    typeInfo = new EnumTypeInfo(
                        typeSymbol,
                        isReadonly,
                        isNullable);
                    return(ParseStatus.SUCCESS);
                }

                default: throw new ArgumentOutOfRangeException();
                }
            }

            if (typeSymbol.SpecialType == SpecialType.System_String)
            {
                typeInfo = new StringTypeInfo(
                    typeSymbol,
                    isReadonly,
                    isNullable);
                return(ParseStatus.SUCCESS);
            }

            if (typeSymbol.SpecialType is SpecialType
                .System_Collections_Generic_IReadOnlyList_T)
            {
                var listTypeSymbol = typeSymbol as INamedTypeSymbol;

                var containedTypeSymbol  = listTypeSymbol.TypeArguments[0];
                var containedParseStatus = this.ParseTypeSymbol(
                    containedTypeSymbol,
                    true,
                    out var containedTypeInfo);
                if (containedParseStatus != ParseStatus.SUCCESS)
                {
                    typeInfo = default;
                    return(containedParseStatus);
                }

                typeInfo = new SequenceTypeInfo(
                    typeSymbol,
                    isReadonly,
                    isNullable,
                    false,
                    isReadonly,
                    containedTypeInfo);
                return(ParseStatus.SUCCESS);
            }

            if (typeSymbol.TypeKind is TypeKind.Array)
            {
                var arrayTypeSymbol = typeSymbol as IArrayTypeSymbol;

                var containedTypeSymbol  = arrayTypeSymbol.ElementType;
                var containedParseStatus = this.ParseTypeSymbol(
                    containedTypeSymbol,
                    false,
                    out var containedTypeInfo);
                if (containedParseStatus != ParseStatus.SUCCESS)
                {
                    typeInfo = default;
                    return(containedParseStatus);
                }

                typeInfo = new SequenceTypeInfo(
                    typeSymbol,
                    isReadonly,
                    isNullable,
                    true,
                    isReadonly,
                    containedTypeInfo);
                return(ParseStatus.SUCCESS);
            }

            if (typeSymbol.SpecialType is SpecialType
                .System_Collections_Generic_IList_T)
            {
                var listTypeSymbol = typeSymbol as INamedTypeSymbol;

                var containedTypeSymbol  = listTypeSymbol.TypeArguments[0];
                var containedParseStatus = this.ParseTypeSymbol(
                    containedTypeSymbol,
                    false,
                    out var containedTypeInfo);
                if (containedParseStatus != ParseStatus.SUCCESS)
                {
                    typeInfo = default;
                    return(containedParseStatus);
                }

                typeInfo = new SequenceTypeInfo(
                    typeSymbol,
                    isReadonly,
                    isNullable,
                    false,
                    false,
                    containedTypeInfo);
                return(ParseStatus.SUCCESS);
            }

            if (typeSymbol is INamedTypeSymbol namedTypeSymbol)
            {
                typeInfo = new StructureTypeInfo(
                    namedTypeSymbol,
                    isReadonly,
                    isNullable);
                return(ParseStatus.SUCCESS);
            }

            if (typeSymbol is ITypeParameterSymbol typeParameterSymbol)
            {
                var constraintTypeInfos =
                    typeParameterSymbol
                    .ConstraintTypes
                    .Select(constraintType => {
                    var parseStatus = this.ParseTypeSymbol(
                        constraintType, isReadonly, out var constraintTypeInfo);
                    Asserts.Equal(ParseStatus.SUCCESS, parseStatus);
                    return(constraintTypeInfo);
                })
                    .ToArray();

                typeInfo = new GenericTypeInfo(
                    constraintTypeInfos,
                    typeParameterSymbol,
                    isReadonly,
                    isNullable);
                return(ParseStatus.SUCCESS);
            }

            typeInfo = default;
            return(ParseStatus.NOT_IMPLEMENTED);
        }