private TypeBindingInformationState NewTypeBindingInformation( CompositeValidationResultMutable vResult, CollectionsFactory collectionsFactory, CompositeModel compositeModel, AbstractInjectableModel injModel, Type nInfo, Type type, Type declaringType, IDictionary <Type, TypeBindingInformationState> privateComposites ) { TypeBindingInformationState state = new TypeBindingInformationState(collectionsFactory); state.NativeInfo = nInfo.GetGenericDefinitionIfContainsGenericParameters(); ListProxy <ListProxy <AbstractGenericTypeBinding> > bindings = collectionsFactory.NewListProxy <ListProxy <AbstractGenericTypeBinding> >(); Boolean allBindingsOK = this.NewGenericTypeBinding(collectionsFactory, compositeModel, type, declaringType, bindings, privateComposites); if (allBindingsOK) { state.Bindings.AddRange(bindings.CQ); } else if (vResult != null) { vResult.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Failed to deduce generic bindings for " + (injModel == null ? (Object)type : injModel) + ".", compositeModel, injModel as AbstractMemberInfoModel <Object>)); } return(allBindingsOK ? state : null); }
protected virtual CompositeValidationResultMutable PerformValidationWithoutTypeGeneration(CompositeModel compositeModel) { var state = new CompositeValidationResultState(compositeModel); var result = new CompositeValidationResultMutable(state, new CompositeValidationResultImmutable(state)); this.CreateValidator().ValidateComposite(result, compositeModel); this.PostValidateModel(compositeModel, result); return(result); }
private IDictionary <Type, TypeBindingInformationState> CreateInvocationInfos <AttributeType>( CompositeValidationResultMutable vResult, CollectionsFactory collectionsFactory, CompositeModel compositeModel, IDictionary <Type, TypeBindingInformationState> privateComposites ) where AttributeType : Attribute { var injModels = compositeModel.GetAllInjectableModelsWithInjectionScope <AttributeType>(); var invocationTypes = injModels.GetBottomTypes(model => model.TargetType); var invocationInfos = new Dictionary <Type, TypeBindingInformationState>(); foreach (var model in invocationTypes) { var actualType = model.TargetType; this.ModifyTypeBindingInfoDictionary(invocationInfos, this.NewTypeBindingInformation(vResult, collectionsFactory, compositeModel, model, actualType, actualType, GetBottommostDeclaringType(model), privateComposites)); } return(invocationInfos); }
public virtual void ValidateComposite(CompositeValidationResultMutable result, CompositeModel compositeModel) { // TODO check that all keys of the type model CompositeTypeInformations and FragmentTypeInformations are assignable from all methods of the composite model. this.ValidateCompositeTypeModel(result, compositeModel); if (compositeModel.MainCodeGenerationType == null) { result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Composite model main code generation type was null", compositeModel)); } else if (!compositeModel.PublicTypes.Contains(compositeModel.MainCodeGenerationType)) { result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Composite model main code generation type " + compositeModel.MainCodeGenerationType + " was not contained in its public types (" + String.Join(", ", compositeModel.PublicTypes) + ").", compositeModel)); } else { CompositeMethodModel[] unimplementedMethods = compositeModel.Methods .Where(methodModel => methodModel.Mixin == null) .ToArray(); if (unimplementedMethods.Any()) { foreach (CompositeMethodModel unimplementedMethod in unimplementedMethods) { result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("No implementation found for " + unimplementedMethod.NativeInfo + ".", compositeModel, unimplementedMethod)); } } else { foreach (FieldModel fieldModel in compositeModel.Fields) { this.ValidateField(result, compositeModel, fieldModel); } foreach (ConstructorModel constructorModel in compositeModel.Constructors) { foreach (ParameterModel parameterModel in constructorModel.Parameters) { this.ValidateParameter(result, compositeModel, parameterModel); } } foreach (CompositeMethodModel compositeMethod in compositeModel.Methods) { if (compositeMethod == null) { result.InternalValidationErrors.Add(ValidationErrorFactory.NewInternalError("Composite method model may not be null.", compositeModel)); } else { this.ValidateParameter(result, compositeModel, compositeMethod.Result); foreach (ParameterModel parameterModel in compositeMethod.Parameters) { this.ValidateParameter(result, compositeModel, parameterModel); } foreach (AbstractFragmentMethodModel fragmentMethod in compositeMethod.GetAllMethodModels().OfType <AbstractFragmentMethodModel>()) { this.ValidateFragmentMethod(result, compositeModel, compositeMethod, fragmentMethod); } foreach (ConstraintModel constraintModel in compositeMethod.Parameters.SelectMany(param => param.Constraints).Concat(compositeMethod.Result.Constraints)) { if (constraintModel.ConstraintType == null) { result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Could not bind parameter constraint " + constraintModel.ConstraintAttribute + ".", compositeModel, compositeMethod)); } else if (constraintModel.ConstraintType.GetConstructor(Empty <Type> .Array) == null) { result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Constraints must have constructor without parameters, but constraint of type " + constraintModel.ConstraintType + " does not.", compositeModel, compositeMethod)); } else if (constraintModel.ConstraintType.ContainsGenericParameters() && !constraintModel.ConstraintType.IsGenericTypeDefinition()) { result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Constraint type " + constraintModel.ConstraintType + " contains non-closed generic parameters but is not generic type definition.", compositeModel, compositeMethod)); } } } } foreach (var pModel in compositeModel.GetAllPropertyModels()) { this.ValidatePropertyModel(result, compositeModel, pModel); } foreach (SpecialMethodModel specialMethod in compositeModel.SpecialMethods) { this.ValidateSpecialMethodModel(result, compositeModel, specialMethod); } foreach (var constraintModel in compositeModel.GetAllConstraints()) { this.ValidateConstraintModel(result, compositeModel, constraintModel); } if (!result.IQ.HasAnyErrors()) { result.TypeModel = new CompositeTypeModelImpl(compositeModel, result); } } } }
public CompositeTypeModelImpl(CompositeModel compositeModel, CompositeValidationResultMutable vResult) { var collectionsFactory = compositeModel.ApplicationModel.CollectionsFactory; this._publicCompositeGenericArguments = collectionsFactory.NewListProxy(GetCompositeModelPublicTypeGenericArguments(compositeModel).ToList()).CQ; var injThisTypes = compositeModel.GetAllInjectableModelsWithInjectionScope <ThisAttribute>() .Select(inj => new ThisTypeInfo(inj)) .ToArray(); var thisTypesInModel = compositeModel.Methods .Select(m => m.NativeInfo.DeclaringType) .Concat(compositeModel.PublicTypes) .Concat(injThisTypes.Select(inj => inj.resolvedTargetType)) .Concat(compositeModel.GetAllFragmentTypes().SelectMany(ft => ft.GetAllParentTypes(false))) .GetBottomTypes(); foreach (var injThisType in injThisTypes) { injThisType.resolvedTargetTypeFromModel = thisTypesInModel.First(tType => injThisType.resolvedTargetType.GetGenericDefinitionIfContainsGenericParameters().IsAssignableFrom_IgnoreGenericArgumentsForGenericTypes(tType)); } var thisTypesToProcess = new HashSet <ThisTypeInfo>(injThisTypes.GetBottomTypes(model => model.resolvedTargetType).Distinct(INJECTABLE_MODEL_EQ_COMPARER)); thisTypesToProcess.ExceptWith(thisTypesToProcess.Where(type => compositeModel.PublicTypes.Any(role => type.resolvedTargetType.GetGenericDefinitionIfGenericType().IsAssignableFrom_IgnoreGenericArgumentsForGenericTypes(role))).ToArray()); // TODO check that if type binding has more than one list with indirect bindings -> throw or add error. var privateComposites = new Dictionary <Type, TypeBindingInformationState>(); while (thisTypesToProcess.Any()) { var processedTypes = new HashSet <ThisTypeInfo>(GDEF_EQ_COMPARER); foreach (var thisType in thisTypesToProcess) { if (this.ModifyTypeBindingInfoDictionary(privateComposites, this.NewTypeBindingInformation(null, collectionsFactory, compositeModel, null, thisType.resolvedTargetTypeFromModel, thisType.resolvedTargetType, GetBottommostDeclaringType(thisType.model), privateComposites))) { processedTypes.Add(thisType); } } thisTypesToProcess.ExceptWith(thisTypesToProcess.Where(t => processedTypes.Any(p => t.resolvedTargetType.GetGenericDefinitionIfContainsGenericParameters().Equals(p.resolvedTargetType.GetGenericDefinitionIfContainsGenericParameters()))).ToArray()); if (processedTypes.Count == 0) { // We are stuck vResult.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Could not deduce generic bindings for types " + String.Join(", ", thisTypesToProcess.Select(ttp => ttp.resolvedDeclaringType)), compositeModel)); break; } else { processedTypes.Clear(); } } var fragmentTypeInfos = new Dictionary <Type, TypeBindingInformationState>(); foreach (var fragmentType in compositeModel.GetAllFragmentTypes()) { // TODO check - if any parent is public or private composite type (genericdefifgenerictype), error if (fragmentType.IsGenericType()) { var it = FindImplementingTypeFrom(fragmentType, compositeModel.PublicTypes); if (it != null || !fragmentType.ContainsGenericParameters()) { this.ModifyTypeBindingInfoDictionary(fragmentTypeInfos, this.NewTypeBindingInformation(vResult, collectionsFactory, compositeModel, null, fragmentType, fragmentType, fragmentType, privateComposites)); } else { // Private composite fragment // Process all base types + injectable models of this fragment, and all their generic arguments as DFS var dependentStates = Enumerable.Repeat <Tuple <Int32, TypeBindingInformationState> >(null, fragmentType.GetGenericArguments().Length).ToList(); foreach (var typeToProcess in fragmentType.GetAllParentTypes(false) .Concat( compositeModel.GetAllInjectableModels() .Where(inj => fragmentType.GetClassHierarchy().Contains(inj.DeclaringType)) .Select(inj => inj.TargetType) )) { if (dependentStates.Any(item => item == null)) { var gArgs = typeToProcess.GetGenericArguments(); for (var i = 0; i < gArgs.Length; ++i) { foreach (var typeOrGArg in gArgs[i].AsDepthFirstEnumerable(t => t.GetGenericArgumentsSafe())) { if (typeOrGArg.IsGenericParameter && dependentStates[typeOrGArg.GenericParameterPosition] == null) { TypeBindingInformationState other; if (!privateComposites.TryGetValue(typeToProcess.GetGenericDefinitionIfContainsGenericParameters(), out other) && compositeModel.PublicTypes.Contains(typeToProcess) ) { other = new TypeBindingInformationState(collectionsFactory); other.NativeInfo = typeToProcess; } if (other != null) { dependentStates[typeOrGArg.GenericParameterPosition] = Tuple.Create(i, other); } } } } } else { break; } } if (!dependentStates.Any(item => item == null)) { var state = new TypeBindingInformationState(collectionsFactory); state.NativeInfo = fragmentType; var max = Math.Max(1, dependentStates.Max(dState => dState.Item2.Bindings.CQ.Count)); if (dependentStates.Select(dState => dState.Item2.Bindings.CQ.Count).Where(c => c > 1).Distinct().Count() > 1) { throw new NotImplementedException("Very complex private type binding is not yet supported."); } else { for (var i = 0; i < max; ++i) { state.Bindings.Add(collectionsFactory.NewListProxy(dependentStates.Select(dState => { AbstractGenericTypeBinding gtb; if (dState.Item2.Bindings.CQ.Any()) { // Private composite binding gtb = dState.Item2.Bindings.CQ[i].CQ[dState.Item1]; } else { var iState = new IndirectGenericTypeBindingState(); iState.GenericDefinition = dState.Item2.NativeInfo.GetGenericDefinitionIfGenericType(); iState.GenericIndex = dState.Item1; gtb = new IndirectGenericTypeBindingImpl(iState); } return(gtb); }).ToList())); } this.ModifyTypeBindingInfoDictionary(fragmentTypeInfos, state); } } } } else { var state = new TypeBindingInformationState(collectionsFactory); state.NativeInfo = fragmentType; this.ModifyTypeBindingInfoDictionary(fragmentTypeInfos, state); } } this._fragmentTypeInfos = collectionsFactory.NewDictionaryProxy(fragmentTypeInfos.ToDictionary(kvp => kvp.Key, kvp => (TypeBindingInformation) new TypeBindingInformationImpl(kvp.Value))).CQ; this._concernInvocationTypeInfos = collectionsFactory.NewDictionaryProxy(this.CreateInvocationInfos <ConcernForAttribute>(vResult, collectionsFactory, compositeModel, privateComposites).ToDictionary(kvp => kvp.Key, kvp => (TypeBindingInformation) new TypeBindingInformationImpl(kvp.Value))).CQ; this._sideEffectInvocationTypeInfos = collectionsFactory.NewDictionaryProxy(this.CreateInvocationInfos <SideEffectForAttribute>(vResult, collectionsFactory, compositeModel, privateComposites).ToDictionary(kvp => kvp.Key, kvp => (TypeBindingInformation) new TypeBindingInformationImpl(kvp.Value))).CQ; this._privateCompositeTypeInfos = collectionsFactory.NewDictionaryProxy(privateComposites.ToDictionary(kvp => kvp.Key, kvp => (TypeBindingInformation) new TypeBindingInformationImpl(kvp.Value))).CQ; }