public ConflictDetectionResult Process(ContributedConflictGroup group) { group.ResolvedMember = null; group.HasConflict = false; var result = new ConflictDetectionResult(); if (group.IsSuperceded) { return result; // TODO: process warnings? views here are superfluous since the member is overriden! } // to solve the conflict, EXACTLY one non-abstract member must remain in the list // only consider foreign members var resolvedMembers = group.Members.Where(roleMember => roleMember.IsForeign).ToList(); // process excluded members resolvedMembers = resolvedMembers.Where(roleMember => !roleMember.IsExcluded).ToList(); if (resolvedMembers.Count == 0) { result.AddMessage(Error.AllMembersExcluded(group.TargetType, group.ResolveRepresentation())); return result; } // process aliased members resolvedMembers = resolvedMembers.Where(roleMember => !roleMember.IsAliased).ToList(); if (resolvedMembers.Count == 0) { // all members are aliased group.ResolvedMember = null; return result; } // process base methods if (resolvedMembers.All(roleMember => roleMember.Definition.IsBaseMethod())) { // all members are virtual base members, they'll be provided by the composing class group.IsBaseMethod = true; group.ResolvedMember = null; return result; } Tracer.Assert(!resolvedMembers.Any(roleMember => roleMember.Definition.IsBaseMethod()), "Base methods cannot be provided by roles"); if (resolvedMembers.All(roleMember => roleMember.IsAbstract)) { if (!group.TargetType.IsRole()) { result.AddMessage(Error.DoesNotImplementAbstractRoleMember(group.TargetType, group.ResolveRepresentation())); } return result; } // process abstract members resolvedMembers = resolvedMembers.Where(roleMember => !roleMember.IsAbstract).ToList(); if (resolvedMembers.Count > 1) { group.HasConflict = true; result.AddMessage(Error.Conflict(group.TargetType, group.ResolveRepresentation(), resolvedMembers)); return result; } group.ResolvedMember = resolvedMembers.Single(); return result; }
public IMemberDefinition Compose(ContributedConflictGroup group, MethodAttributes accessSpecifier) { Group = group; if (group.ImplementedMember != null) { return group.ImplementedMember; } if (group.DontImplement) { return null; } if (group.IsSuperceded) { // the superceding member in the class is the implementing member for the role member return group.ImplementedMember = AdjustSupercedingMember(group.Supercede, group.ResolveOverridingMembers()); } if (group.IsBaseMethod) { ImplementBaseMethod(group.Members[0], group.ResolveOverridingMembers()); // any member will do, they all point to the same base method // TODO: use the ImplementedMember here? return null; } // the resolved member implements all the other members in the group by calling its implementing member var resolvedMember = group.ResolvedMember; if (resolvedMember == null) { // this member does not get composed (it will be aliased by another member) return null; } var implementedMember = ImplementMember( resolvedMember.Definition.Name, resolvedMember.ResolveImplementingMember(), group.ResolveOverridingMembers(), accessSpecifier); if (implementedMember == null) { // this member was not implemented (it was provided by a base class) return null; } if (group.ReuseSlot) { ((MethodDefinition)implementedMember).IsNewSlot = false; } return group.ImplementedMember = implementedMember; }
public IMemberDefinition Compose(ContributedConflictGroup group) { return Compose(group, MethodAttributes.Public); }