public static ICollection <IReference> Decompose(this IClass scope, IReference reference) { var layering = Layering <IClass> .CreateLayers(scope, cl => cl.BaseTypes); var references = new HashSet <IReference>(); references.Add(reference); foreach (var layer in layering) { if (layer.Count > 1) { throw new InvalidOperationException("There is a cycle in the inheritance hierarchy."); } foreach (var cl in layer) { foreach (var r in cl.References) { if (r.Refines != null && references.Contains(r.Refines)) { references.Add(r); } } } } return(references); }
private string QueryResult() { return(string.Join('|', (from comment in SocialNetwork.Descendants().OfType <Comment>() let layering = Layering <IUser> .CreateLayers(comment.LikedBy, u => u.Friends.Where(f => f.Likes.Contains(comment))) orderby layering.Sum(l => Square(l.Count)) select comment.Id).Take(3))); }
private string QueryResult() { return(string.Join('|', (from comment in SocialNetwork.Descendants().OfType <Comment>() let layering = Layering <IUser> .CreateLayers(comment.LikedBy, u => u.Friends.Intersect(comment.LikedBy)) let score = layering.Sum(l => Square(l.Count)) orderby(score, comment.Timestamp) descending select comment.Id).Take(3))); }
public IEnumerator <IEnumerable <T> > GetEnumerator() { if (components == null) { components = Layering <T> .CreateLayers(nodes, edges); } return(components.GetEnumerator()); }
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 void Recompute() { components.Clear(); var layers = Layering <T> .CreateLayers(nodes, GetEdges); foreach (var layer in layers) { foreach (var item in layer) { components.Add(item, layer); } } OnCleared(); }
private static IEClass FindBaseClass(IEClass eClass, out IEnumerable <IEStructuralFeature> shadows) { shadows = Enumerable.Empty <IEStructuralFeature>(); var ancestors = eClass.Closure(c => c.ESuperTypes); foreach (var layer in Layering <IEClass> .CreateLayers(eClass, c => Edges(c, ancestors)).Reverse()) { if (layer.Count == 1 && layer.First() != eClass && !shadows.IntersectsWith(AllFeatures(layer.First()))) { return(layer.First()); } foreach (var cl in layer) { shadows = shadows.Union(Refinements(cl)); } } return(null); }
public override void Transform(IClass scope, IReference reference, CodeMemberProperty property, Transformations.Core.ITransformationContext context) { var baseTypes = Layering <IClass> .CreateLayers(scope, c => c.BaseTypes).Select(c => c.Single()).ToList(); if (!baseTypes.Contains((IClass)reference.DeclaringType)) { throw new InvalidOperationException(string.Format("The reference {0} cannot be refined in the scope of class {1} because {1} does not inherit from its declaring class.", reference.Name, scope.Name)); } var classDeclaration = context.Trace.ResolveIn(Rule <Type2Type>(), scope); var originalReference = context.Trace.ResolveIn(Rule <Reference2Property>(), reference); property.Attributes = MemberAttributes.Private; property.Name = originalReference.Name; property.PrivateImplementationType = CreateReference(reference.DeclaringType, false, context); property.Type = originalReference.Type; lock (classDeclaration) { classDeclaration.Shadows(true).Add(originalReference); classDeclaration.DependentMembers(true).Add(property); } var implementations = baseTypes.SelectMany(s => s.References).Where(r => r.Refines == reference).ToList(); var constraints = baseTypes.SelectMany(s => s.ReferenceConstraints).Where(rc => rc.Constrains == reference); foreach (var declClass in implementations.Select(a => a.DeclaringType).OfType <IClass>().Concat(constraints.Select(c => c.DeclaringType)).Distinct()) { if (declClass != scope) { var refinedReference = context.Trace.ResolveIn(this, declClass, reference); if (refinedReference != null) { property.Shadows(true).Add(refinedReference); } } } if (implementations.Count == 0 && !constraints.Any()) { throw new InvalidOperationException( string.Format("The reference {0} can not be refined in the scope of class {1} because no reference refines it. ", reference, scope) ); } var referenceType = CreateReference(reference.Type, true, context); if (reference.UpperBound == 1) { var nullRef = new CodePrimitiveExpression(null); if (!constraints.Any()) { var castedThisVariable = new CodeVariableDeclarationStatement(classDeclaration.GetReferenceForType(), "_this", new CodeThisReferenceExpression()); var castedThisVariableRef = new CodeVariableReferenceExpression("_this"); property.GetStatements.Add(castedThisVariable); property.SetStatements.Add(castedThisVariable); var setRef = new CodePropertySetValueReferenceExpression(); var ifNull = new CodeConditionStatement(); ifNull.Condition = new CodeBinaryOperatorExpression(setRef, CodeBinaryOperatorType.IdentityInequality, nullRef); var foundMatch = false; foreach (var implementation in implementations) { var implementationRef = new CodePropertyReferenceExpression(castedThisVariableRef, context.Trace.ResolveIn(Rule <Reference2Property>(), implementation).Name); if (implementation.Type == reference.Type) { property.GetStatements.Add(new CodeMethodReturnStatement(implementationRef)); property.SetStatements.Add(new CodeAssignStatement(implementationRef, setRef)); foundMatch = true; break; } else { var getIfStmt = new CodeConditionStatement(); getIfStmt.Condition = new CodeBinaryOperatorExpression(implementationRef, CodeBinaryOperatorType.IdentityInequality, nullRef); getIfStmt.TrueStatements.Add(new CodeMethodReturnStatement(implementationRef)); property.GetStatements.Add(getIfStmt); var implementationType = CreateReference(implementation.Type, true, context); var asRef = new CodeMethodReferenceExpression(setRef, "As", implementationType); var localVar = new CodeVariableDeclarationStatement(implementationType, "__" + implementation.Name, new CodeMethodInvokeExpression(asRef)); var localVarRef = new CodeVariableReferenceExpression(localVar.Name); var setIfStmt = new CodeConditionStatement(); setIfStmt.Condition = new CodeBinaryOperatorExpression(localVarRef, CodeBinaryOperatorType.IdentityInequality, nullRef); setIfStmt.TrueStatements.Add(new CodeAssignStatement(implementationRef, localVarRef)); setIfStmt.TrueStatements.Add(new CodeMethodReturnStatement()); ifNull.TrueStatements.Add(localVar); ifNull.TrueStatements.Add(setIfStmt); ifNull.FalseStatements.Add(new CodeAssignStatement(implementationRef, nullRef)); } } ifNull.FalseStatements.Add(new CodeMethodReturnStatement()); if (ifNull.TrueStatements.Count > 0) { property.SetStatements.Add(ifNull); } if (!foundMatch) { property.GetStatements.Add(new CodeMethodReturnStatement(nullRef)); property.SetStatements.Add(new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(System.ArgumentException), new CodePrimitiveExpression("There was no suitable refining reference found for this object")))); } } else { var constraint = constraints.Last(); var ifNotDefault = new CodeConditionStatement(); ifNotDefault.TrueStatements.Add(new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(System.NotSupportedException)))); CodeExpression value; if (constraint.References.Count == 0) { value = nullRef; } else { var refEl = constraint.References[0]; var uri = refEl.AbsoluteUri; if (uri == null) { throw new System.InvalidOperationException(); } var metaRepositoryInstance = new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(MetaRepository)), "Instance"); var refElExpression = new CodeMethodInvokeExpression(metaRepositoryInstance, "Resolve", new CodePrimitiveExpression(uri.AbsoluteUri)); refElExpression = new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(refElExpression, "As", property.Type)); var retrieveValueMethod = new CodeMemberMethod { Name = "Retrieve" + reference.Name.ToPascalCase(), Attributes = MemberAttributes.Private | MemberAttributes.Static, ReturnType = property.Type }; retrieveValueMethod.Statements.Add(new CodeMethodReturnStatement(refElExpression)); property.DependentMembers(true).Add(retrieveValueMethod); var staticField = new CodeMemberField(new CodeTypeReference("Lazy", property.Type), "_" + reference.Name.ToPascalCase()); staticField.Attributes = MemberAttributes.Private | MemberAttributes.Static; staticField.InitExpression = new CodeObjectCreateExpression(staticField.Type, new CodeMethodReferenceExpression(null, retrieveValueMethod.Name)); property.DependentMembers(true).Add(staticField); value = new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(null, staticField.Name), "Value"); } property.GetStatements.Add(new CodeMethodReturnStatement(value)); ifNotDefault.Condition = new CodeBinaryOperatorExpression(new CodePropertySetValueReferenceExpression(), CodeBinaryOperatorType.IdentityInequality, value); property.SetStatements.Add(ifNotDefault); } CreateChangeEvent(property, implementations, context, "Changed"); CreateChangeEvent(property, implementations, context, "Changing"); } else { if (reference.IsUnique) { throw new System.InvalidOperationException("Unique references must not be refined!"); } if (implementations.Count > 0 || constraints.Any(c => c.References.Any())) { var collectionType = context.Trace.ResolveIn(Rule <RefinedReferenceCollectionClassGenerator>(), scope, reference); property.GetStatements.Add(new CodeMethodReturnStatement(new CodeObjectCreateExpression(collectionType.GetReferenceForType(), new CodeThisReferenceExpression()))); property.DependentTypes(true).Add(collectionType); } else { property.GetStatements.Add(new CodeMethodReturnStatement(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(new CodeTypeReference(typeof(EmptyList <>).Name, referenceType)), "Instance"))); } } }
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); } } } } } }
/// <summary> /// Initializes the generated code property for the refined attribute /// </summary> /// <param name="scope">The scope in which the attribute is refined</param> /// <param name="attribute">The NMeta attribute that is refined</param> /// <param name="property">The generated code property</param> /// <param name="context">The transformation context</param> public override void Transform(IClass scope, IAttribute attribute, CodeMemberProperty property, ITransformationContext context) { var baseTypes = Layering <IClass> .CreateLayers(scope, c => c.BaseTypes).Select(c => c.Single()).ToList(); if (!baseTypes.Contains((IClass)attribute.DeclaringType)) { throw new InvalidOperationException(string.Format("The attribute {0} cannot be refined in the scope of class {1} because {1} does not inherit from its declaring class.", attribute.Name, scope.Name)); } var classDeclaration = context.Trace.ResolveIn(Rule <Type2Type>(), scope); var originalAttribute = context.Trace.ResolveIn(Rule <Attribute2Property>(), attribute); property.Attributes = MemberAttributes.Private; property.Name = originalAttribute.Name; property.PrivateImplementationType = CreateReference(attribute.DeclaringType, false, context); lock (classDeclaration) { classDeclaration.Shadows(true).Add(originalAttribute); classDeclaration.DependentMembers(true).Add(property); } var implementations = baseTypes.SelectMany(s => s.Attributes).Where(att => att.Refines == attribute).ToList(); var constraints = baseTypes.SelectMany(s => s.AttributeConstraints).Where(rc => rc.Constrains == attribute); foreach (var declClass in implementations.Select(a => a.DeclaringType).OfType <IClass>().Concat(constraints.Select(c => c.DeclaringType)).Distinct()) { if (declClass != scope) { var refinedAttribute = context.Trace.ResolveIn(this, declClass, attribute); if (refinedAttribute != null) { property.Shadows(true).Add(refinedAttribute); } } } if (implementations.Count == 0 && !constraints.Any()) { throw new InvalidOperationException( string.Format("The attribute {0} can not be refined in the scope of class {1} because no reference refines it. ", attribute, scope) ); } var attributeType = CreateReference(attribute.Type, false, context); if (attribute.UpperBound == 1) { property.Type = attributeType; if (implementations.Count > 1) { throw new System.InvalidOperationException("A single value typed attribute may only be refined once!"); } else if (implementations.Count == 1) { if (constraints.Any()) { throw new System.InvalidOperationException("A single values attribute must not be constrained and implemented at the same time!"); } if (implementations[0].Type != attribute.Type) { throw new System.InvalidOperationException("The refining attribute has a different type than the original attribute. Covariance is not supported for attributes!"); } var castedThisVariable = new CodeVariableDeclarationStatement(classDeclaration.GetReferenceForType(), "_this", new CodeThisReferenceExpression()); var castedThisVariableRef = new CodeVariableReferenceExpression("_this"); property.GetStatements.Add(castedThisVariable); property.SetStatements.Add(castedThisVariable); var implProperty = context.Trace.ResolveIn(Rule <Attribute2Property>(), implementations[0]); CodeExpression implementationRef = new CodePropertyReferenceExpression(castedThisVariableRef, implProperty.Name); property.GetStatements.Add(new CodeMethodReturnStatement(implementationRef)); property.SetStatements.Add(new CodeAssignStatement(implementationRef, new CodePropertySetValueReferenceExpression())); } else { var constraint = constraints.Last(); var ifNotDefault = new CodeConditionStatement(); ifNotDefault.TrueStatements.Add(new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(System.NotSupportedException)))); CodeExpression value; if (constraints.Sum(c => c.Values.Count) == 0) { value = new CodeDefaultValueExpression(attributeType); } else { value = CodeDomHelper.CreatePrimitiveExpression(constraint.Values[0], attributeType, attribute.Type is IEnumeration); if (value == null) { throw new InvalidOperationException(string.Format("The value {0} could not be serialized as a value for {1}", constraint.Values[0], attribute)); } } property.GetStatements.Add(new CodeMethodReturnStatement(value)); ifNotDefault.Condition = new CodeBinaryOperatorExpression(new CodePropertySetValueReferenceExpression(), CodeBinaryOperatorType.IdentityInequality, value); property.SetStatements.Add(ifNotDefault); } CreateChangeEvent(property, implementations, context, "Changed"); CreateChangeEvent(property, implementations, context, "Changing"); } else { if (attribute.IsUnique) { throw new System.InvalidOperationException("Unique attributes must not be refined."); } if (implementations.Count > 0 || constraints.Any(c => c.Values.Any())) { var collectionType = context.Trace.ResolveIn(Rule <RefinedAttributeCollectionClassGenerator>(), scope, attribute); property.GetStatements.Add(new CodeMethodReturnStatement(new CodeObjectCreateExpression(collectionType.GetReferenceForType(), new CodeThisReferenceExpression()))); property.DependentTypes(true).Add(collectionType); } else { property.GetStatements.Add(new CodeMethodReturnStatement(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(new CodeTypeReference(typeof(EmptyList <>).Name, attributeType)), "Instance"))); } } }