protected virtual void ResolveMultipleInheritanceMembers(CodeTypeDeclaration generatedType, HashSet <CodeTypeMember> shadows, CodeConstructor constructor) { Func <CodeTypeDeclaration, IEnumerable <CodeTypeDeclaration> > getBaseTypes = type => { var interfaceType = CodeDomHelper.GetOrCreateUserItem <CodeTypeDeclaration>(type, CodeDomHelper.InterfaceKey); if (interfaceType == null) { interfaceType = type; } return(interfaceType.BaseTypes.Cast <CodeTypeReference>().Select(r => r.GetTypeForReference()).Where(c => c != null)); }; var layering = Layering <CodeTypeDeclaration> .CreateLayers(generatedType, getBaseTypes); CodeTypeDeclaration implBaseType = FindBaseClassAndCreateShadows(generatedType, shadows, layering); IEnumerable <CodeTypeDeclaration> inheritedBaseClasses; if (implBaseType != null) { inheritedBaseClasses = implBaseType.Closure(getBaseTypes); var implementationRef = new CodeTypeReference(); implementationRef.BaseType = implBaseType.Name; var n = implBaseType.GetReferenceForType().Namespace(); if (n != null && n.EndsWith(implBaseType.Name)) { implementationRef.BaseType = n + "." + implBaseType.Name; } else { implementationRef.SetNamespace(n); } generatedType.BaseTypes.Insert(0, implementationRef); } else { inheritedBaseClasses = Enumerable.Empty <CodeTypeDeclaration>(); AddImplementationBaseClass(generatedType); } for (int i = layering.Count - 1; i >= 0; i--) { foreach (var baseType in layering[i]) { if (!inheritedBaseClasses.Contains(baseType) && baseType != generatedType && ShouldContainMembers(generatedType, baseType.GetReferenceForType())) { var dependent = baseType.DependentMembers(false); if (dependent != null) { foreach (var inheritedMember in dependent) { RecursivelyAddDependentMembers(generatedType.Members, constructor.Statements, inheritedMember, shadows); } } } } } }
private static IEnumerable <CodeTypeDeclaration> Edges(CodeTypeDeclaration typeDeclaration, IEnumerable <CodeTypeDeclaration> candidates) { var ancestors = typeDeclaration.Closure(GetBaseClasses); var refinements = Refinements(typeDeclaration); var conflicting = from cand in candidates where !cand.Closure(GetBaseClasses).Contains(typeDeclaration) && refinements.IntersectsWith(AllFeatures(cand)) select cand; return(ancestors.Union(conflicting)); }
private static IEnumerable <CodeTypeMember> AllDeclaredFeatures(CodeTypeDeclaration typeDeclaration) { return(typeDeclaration.Closure <CodeTypeMember>(t => { var dependents = t.DependentMembers(false); if (dependents == null) { return Enumerable.Empty <CodeTypeMember>(); } else { return dependents; } })); }
/// <summary> /// Initializes the generated type declaration /// </summary> /// <param name="input">The input model element</param> /// <param name="generatedType">The generated class declaration</param> /// <param name="context">The transformation context</param> /// <remarks>Can be overridden to refine code generation</remarks> public override void Transform(T input, CodeTypeDeclaration generatedType, ITransformationContext context) { HashSet <CodeTypeMember> shadows; var ownShadows = generatedType.Shadows(false); if (ownShadows != null) { shadows = new HashSet <CodeTypeMember>(ownShadows); } else { shadows = new HashSet <CodeTypeMember>(); } var constructor = CodeDomHelper.GetOrCreateDefaultConstructor(generatedType, () => new CodeConstructor() { Attributes = MemberAttributes.Public }); var dependends = generatedType.DependentMembers(false); if (dependends != null) { foreach (var member in dependends) { RecursivelyAddDependentMembers(generatedType.Members, constructor.Statements, member, shadows); } } var interfaceDecl = CreateSeparatePublicInterface(input, generatedType); if (interfaceDecl != null) { CodeDomHelper.SetUserItem(generatedType, CodeDomHelper.InterfaceKey, interfaceDecl); var dependentTypes = CodeDomHelper.DependentTypes(generatedType, true); dependentTypes.Add(interfaceDecl); var typeReference = generatedType.GetReferenceForType(); typeReference.BaseType = interfaceDecl.Name; CreateInterfaceMembers(generatedType, interfaceDecl); for (int i = generatedType.BaseTypes.Count - 1; i >= 0; i--) { var baseTypeRef = generatedType.BaseTypes[i]; var baseType = CodeDomHelper.GetOrCreateUserItem <CodeTypeDeclaration>(baseTypeRef, CodeDomHelper.ClassKey); if (baseType == null) { continue; } interfaceDecl.BaseTypes.Add(baseTypeRef); generatedType.BaseTypes.RemoveAt(i); } generatedType.BaseTypes.Add(typeReference); ResolveMultipleInheritanceMembers(generatedType, shadows, constructor); } else { CodeDomHelper.SetUserItem(generatedType, CodeDomHelper.BaseClassesKey, generatedType.Closure(GetBaseClasses).Except(generatedType)); } if (constructor.Statements.Count > 0) { CodeDomHelper.SetUserItem(generatedType, CodeDomHelper.ConstructorKey, constructor); generatedType.Members.Add(constructor); } }
protected virtual void ResolveMultipleInheritanceMembers(CodeTypeDeclaration generatedType, HashSet <CodeTypeMember> shadows, CodeConstructor constructor) { var allClasses = generatedType.Closure(GetBaseClasses); var layering = Layering <CodeTypeDeclaration> .CreateLayers(generatedType, c => Edges(c, allClasses)); CodeTypeDeclaration implBaseType = null; int layerIndex; for (layerIndex = layering.Count - 1; layerIndex >= 0; layerIndex--) { var layer = layering[layerIndex]; if (layer.Count == 1 && layer.First() != generatedType && !shadows.IntersectsWith(AllFeatures(layer.First()))) { implBaseType = layer.First(); break; } foreach (var cl in layer) { shadows.UnionWith(Refinements(cl)); } } IEnumerable <CodeTypeDeclaration> inheritedBaseClasses; if (implBaseType != null) { inheritedBaseClasses = layering.Take(layerIndex + 1).SelectMany(s => s); var implementationRef = new CodeTypeReference(); implementationRef.BaseType = implBaseType.Name; var n = implBaseType.GetReferenceForType().Namespace(); if (n != null && n.EndsWith(implBaseType.Name)) { implementationRef.BaseType = n + "." + implBaseType.Name; } else { implementationRef.SetNamespace(n); } generatedType.BaseTypes.Insert(0, implementationRef); } else { inheritedBaseClasses = Enumerable.Empty <CodeTypeDeclaration>(); AddImplementationBaseClass(generatedType); } CodeDomHelper.SetUserItem(generatedType, CodeDomHelper.BaseClassesKey, inheritedBaseClasses); for (int i = layerIndex + 1; i < layering.Count; i++) { foreach (var baseType in layering[i]) { if (baseType != generatedType) { var dependent = baseType.DependentMembers(false); if (dependent != null) { foreach (var inheritedMember in dependent) { RecursivelyAddDependentMembers(generatedType.Members, constructor.Statements, inheritedMember, shadows); } } } } } }
private static IEnumerable <CodeTypeMember> AllFeatures(CodeTypeDeclaration typeDeclaration) { return(typeDeclaration.Closure(GetBaseClasses).SelectMany(AllDeclaredFeatures)); }