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