public MemberComposerSource(MemberMetaInfo layoutMember, GeneratingTypeName typeName, IEnumerable <IConditionResolverProvider> conditions, IEnumerable <IMemberDataFormatterProvider> formatters, ITypeSymbolProvider symbolProvider) { if (_member.ReturnType is null) { throw new ArgumentException("Invalid layout member (No Return Type)"); } _member = layoutMember; _typeName = typeName; _symbols = symbolProvider; // Watch out for order(? _conditions = conditions.SelectMany(x => x.GetResolvers(layoutMember, _throwCollection)).ToList(); _format = GetFormatResolver(); IMemberDataFormatter GetFormatResolver() { foreach (var formatter in formatters) { if (!formatter.ShouldFormat(layoutMember)) { continue; } return(formatter.GetFormatter(layoutMember, _componentCollection, _throwCollection)); } throw new ArgumentException($"The target member {layoutMember.Name} cannot be resolved by any of the provided {nameof(IMemberDataFormatterProvider)}"); } }
public IgnoreIfResolver(MemberMetaInfo member, ConditionExpression condition, IConditionAnalyzer analyzer, bool isInverted) { _member = member; _expression = condition; _condition = analyzer; _isInverted = isInverted; }
public MemberComposer(ITypeComposer type, MemberMetaInfo targetMember, ITypeSymbol composerSymbol, IReadOnlyList <MethodSignature> methods) { ParentType = type; TargetMember = targetMember; ComposerSymbol = composerSymbol; Methods = methods; }
public IEnumerable <IConditionResolver> GetResolvers(MemberMetaInfo member, IThrowCollection throwCollection) { var ignoreIf = GetResolvers <IgnoreIfAttribute>(member, isInverted: false); var ignoreIfNot = GetResolvers <IgnoreIfNotAttribute>(member, isInverted: true); return(ignoreIf.Concat(ignoreIfNot)); }
public BinaryMemberCompositeStruct(TypeName name, MemberMetaInfo compositeMember, IReadOnlyList <MemberMetaInfo> relyingMembers, IReadOnlyList <MethodSignature> entryMethods, int?constantLength) { Name = name; CompositeMember = compositeMember; RelyingMembers = relyingMembers; EntryMethods = entryMethods; ConstantLength = constantLength; }
public ParsingMethodBuilder(MemberMetaInfo member, ComposerMethodNames methodNames, Accessibility accessibility) { if (member.ReturnType is null) { throw new ArgumentException("Member without return type cannot be configured for parser groups"); } TargetSymbol = member.ReturnType.Symbol; MethodNames = methodNames; _accessibility = accessibility; }
public MemberComposerSourceProto(MemberMetaInfo layoutMember, GeneratingTypeName typeName, IEnumerable <IMemberComposingFeature> features, ITypeSymbolProvider symbolProvider) { if (_member.ReturnType is null) { throw new ArgumentException("Invalid layout member (No Return Type)"); } _member = layoutMember; _typeName = typeName; _symbols = symbolProvider; _features = features.Where(x => x.ShouldFormat(layoutMember)).Select(x => x.GetComposingMethods(layoutMember, _componentCollection, _throwCollection)).ToList(); }
internal static Diagnostic ConflictingAttributes(MemberMetaInfo member, params AttributeData[] conflictingAttributes) { var conflicts = conflictingAttributes.ToList(); if (conflicts.Count < 2) { throw new ArgumentOutOfRangeException(nameof(conflictingAttributes)); } var primeLocation = member.GetLocation(conflicts[0]); var secondary = conflicts.Select(conflict => member.GetLocation(conflict)); var conflictNames = string.Join(",", conflictingAttributes.Select(x => x.AttributeClass?.Name)); return(CreateDiagnostic(primeLocation, secondary, new object[] { conflictNames, member })); }
public BinaryMemberCompositeBuilder(MemberMetaInfo member, GeneratingTypeName typeName, IMemberFormatNamespaceProvider namespaceProvider, IEnumerable <IBinaryMemberFeatureProvider> featureProviders, ISourceAddition sourceAddition) { _member = member; _typeName = typeName; _sourceAddition = sourceAddition; _features = featureProviders.Where(feature => feature.ShouldApply(member)) .Select(feature => feature.GetComposingMethods(member, _memberComponents, _throwCollection)) .ToList(); var namespaceInfo = namespaceProvider.GetUsingNamespaces(member); _normalNamespaces = namespaceInfo.WithNamespaces.ToList(); _prioritizedNamespaces = namespaceInfo.WithPrioritizedNamespaces.ToList(); Debug.Assert(_member.ReturnType != null); }
private static MethodSignature CreateMethod(TypeName memberName, MemberMetaInfo member, IEnumerable <MemberMetaInfo> relyingMembers, string methodName) { Debug.Assert(member.ReturnType is { });
public BinaryMemberCompositeStruct AddMemberCompositeStruct(MemberMetaInfo member, GeneratingTypeName typeName, IComponentResolver resolver) { return(new BinaryMemberCompositeBuilder(member, typeName, _namespaceProvider, _featureProviders, _sourceAddition).AddStructToSource(resolver)); }
private IEnumerable <IConditionResolver> GetResolvers <TAttribute>(MemberMetaInfo member, bool isInverted) where TAttribute : Attribute => member.GetAttributes <TAttribute>().Select(attr => new IgnoreIfResolver(member, GetAttributeCondition(attr), _analyzer, isInverted));
public bool ShouldFormat(MemberMetaInfo member) => member.ContainsAttribute <IgnoreIfAttribute>() || member.ContainsAttribute <IgnoreIfNotAttribute>();
private static MethodSignature CreateMethod(TypeName memberName, MemberMetaInfo member, string methodName) { Debug.Assert(member.ReturnType is { });
public ParsingMethodWithTypeBuilder(MemberMetaInfo member) : base(member, ComposerMethodNames.DefaultNames) { PrependArguments = new[] { $"in {member.ContainingFullType.Symbol} {parent}" }; }
internal static Diagnostic MeaninglessAttribute(Type attribute, MemberMetaInfo warningTarget) => CreateDiagnostic(
public static MethodSignature CreateMethodSignature(TypeName memberCompositeName, MemberMetaInfo member, string methodName) { Debug.Assert(member.ReturnType != null); return(MethodSignatureBuilder.CreateMethod(memberCompositeName, methodName) .AddGenerics(T_STATE, GenericConstrainKind.Struct, new TypeName("Decuplr.Serialization.Binary", "IBinaryWriteState<TState>")) .AddArgument((RefKind.In, member.ReturnType.Symbol, "member")) .AddArgument((RefKind.In, member.ContainingFullType.Symbol, "source")) .AddArgument((TypeName.FromGenericArgument(T_STATE), "state")) .AddArgument((TypeName.FromType(typeof(Span <byte>)), "data")) .WithReturn(TypeName.FromType <int>())); }
public GetBlockLengthSpanChainedMethods(TypeName memberCompositeName, MemberMetaInfo member, IEnumerable <MemberMetaInfo> relyingMembers, Func <int?, string> nextMethodName) : base(i => CreateMethod(memberCompositeName, member, relyingMembers, nextMethodName(i))) { }
internal static Diagnostic ExplicitDontNeedIgnore(MemberMetaInfo member) => CreateDiagnostic(member.Location, new object[] { member.Symbol });
internal static Diagnostic InvalidKeyword(string invalidKeyword, MemberMetaInfo member) => CreateDiagnostic(member.Location, new object?[] { invalidKeyword, member.Symbol });
public IMemberComposer Build(ITypeComposer typeComposer, MemberMetaInfo meta, GeneratingTypeName typeName, IComponentProvider provider) => new MemberComposerSource(meta, typeName, _conditions, _formatters, _symbolProvider) .CreateStruct(typeComposer, provider, (name, source) => { _sourceAddition.AddSource($"{typeName}.generated.cs", source); return(_symbolProvider.GetSymbol(name.ToString())); });
public ParsingMethodBuilder(MemberMetaInfo member, ComposerMethodNames methodNames) : this(member, methodNames, Accessibility.Private) { }
public static CodeNodeBuilder AddFormatterFinalMethods(this CodeNodeBuilder builder, IFormatterParsingMethod <TypeSourceArgs> resolver, MemberMetaInfo member, int index, Func <int, ComposerMethodNames> defaultNames) => builder.AddParsingMethods(new FormatterParsingMethodBuilder(resolver, index, member, defaultNames, false));
public static CodeNodeBuilder AddParsingBody(this CodeNodeBuilder builder, IComposerMethodBodyBuilder bodyBuilder, MemberMetaInfo member, ComposerMethodNames names) => builder.AddParsingMethods(new ParsingBodyWrapBuilder(member, names, bodyBuilder));
internal static Diagnostic UnsupportedTypeHint(MemberMetaInfo member) => CreateDiagnostic(member.Location, new object?[] { member.ReturnType?.Name, member.Symbol, member.ReturnType?.Symbol.TypeKind });
public ParsingBodyWrapBuilder(MemberMetaInfo member, ComposerMethodNames methodNames, IComposerMethodBodyBuilder bodyBuilder) : base(member, methodNames) { _body = bodyBuilder; }
internal static Diagnostic ExplicitSequentialShouldNotIndex(MemberMetaInfo member, Location attributeLocation) => CreateDiagnostic(attributeLocation, new object[] { member.Symbol.ToString() });
private static void EvaluateCondition(MemberMetaInfo targetMember, Location attributeLocation, ConditionExpression conditions, IDiagnosticReporter reporter) { switch (conditions.Condition) { // Since all objects contain Equals(object), this is the least we call back into // TODO : Note we might still want to warn user about that a returning type doesn't contain a correct signature // For example : If we try to evaluate the member equals to true, // even if the member returns a type that is obvious that wouldn't evaluate with true, then it would still evaluate, but just to false case Condition.Equal: case Condition.NotEqual: break; // In these cases we need to check if either the return type implements IComparable or IComparable<T> // We might also want to warn about boxing issue if the given compared type is a valuetype and returning type only has IComparable though case Condition.GreaterThan: case Condition.GreaterThanOrEqual: case Condition.LessThan: case Condition.LessThanOrEqual: { // Valid compare types // Value Types : bool, char, byte, sbyte, ushort, short, int, uint, ulong, long, float, double // Ref Types : Types (but why), string (but why) // We currently consider 'null' to be not comparable, so there's this if (conditions.ComparedValue is null) { reporter.ReportDiagnostic(DiagnosticHelper.CompareValueInvalid(conditions, attributeLocation)); break; } // Valid implicit conversion for IComparable is matched with C# specification : // https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/numeric-conversions // // [Possible Improvement] // TODO : We also don't support even if IComparation<T>'s T is implicit convertible from the compared type // We only support when it's primitive is implicitly convertible (supported by C# specification) to another primitive type // So types that only return IComparable<long> would work well with int numbers // // This can be done using a compilation extensions provided out of the box: // https://docs.microsoft.com/dotnet/api/microsoft.codeanalysis.csharp.csharpextensions.classifyconversion var returnType = targetMember.ReturnType !; var comparedType = conditions.ComparedValue.GetType(); if (!returnType.Implements(typeof(IComparable)) || !returnType.Implements(typeof(IComparable <>))) { reporter.ReportDiagnostic(DiagnosticHelper.ReturnTypeNotComparable(targetMember, conditions.Condition, attributeLocation)); break; } if (!returnType.Implements(typeof(IComparable <>).MakeGenericType(comparedType)) || !returnType.GetInterfaces(typeof(IComparable <>)).Any(x => x.IsImplicitConvertibleFrom(comparedType))) { reporter.ReportDiagnostic(DiagnosticHelper.ReturnTypeInvalidComparable(targetMember, comparedType, attributeLocation)); break; } break; } // Since all objects can be evaluated with is operator case Condition.IsTypeOf: case Condition.IsNotTypeOf: { if (!(conditions.ComparedValue is null) && conditions.ComparedValue.GetType() != typeof(Type)) { reporter.ReportDiagnostic(DiagnosticHelper.CompareValueInvalid(conditions, attributeLocation, ", it should be only a kind of Type and none other")); } break; } default: reporter.ReportDiagnostic(DiagnosticHelper.InvalidCondition(conditions.Condition, attributeLocation)); break; } }
internal static Diagnostic DuplicateIndexs(int index, MemberMetaInfo firstMember, MemberMetaInfo secondMember) => CreateDiagnostic(secondMember.Location, new object[] { index, firstMember.Symbol, secondMember.Symbol });
public SerializerSpanChainedMethods(TypeName memberCompositeName, MemberMetaInfo member, Func <int?, string> nextMethodName) : base(id => CreateMethodSignature(memberCompositeName, member, nextMethodName(id))) { }