public static VisitorBuilder GetVisitorFrom(VisitorTargetDetail detail, IEnumerable <IType> types, ICSharpAssembly assembly) { var builder = new VisitorBuilder(detail, types.ToList()); builder.ScaffoldInterface(assembly); return(builder); }
public VisitorBuilder(VisitorTargetDetail detail, List <IType> relevantTypes) { this._detail = detail; if (this._detail.TypeParameterVariations.Length > 0) { var resultRelevantTypes = new List <IType>(); foreach (var type in relevantTypes) { foreach (var typeParamVariation in this._detail.TypeParameterVariations) { resultRelevantTypes.Add(((IGenericType)(type)).MakeGenericClosure(typeParamVariation)); } } this._relevantTypes = resultRelevantTypes; } else { this._relevantTypes = relevantTypes; } this._skippedTypes = new List <IType>(); }
internal static IEnumerable <VisitorBuilder> GetVisitorContexts(IAssembly assembly, VisitorModelCommonTypeContext attributeContext, ICSharpAssembly resultAssembly, IIntermediateCliManager identityManager) { var visitorRelevantTypes = assembly.GetTypes().Where(t => t.Metadata.Contains(attributeContext.TargetAttribute)).ToArray(); /* Using the metadata supplied on the relevant types, group them by their distinct visitor targets. * We'll use the distinct targets to generate concrete visitor interfaces. * The VisitorTargetAttribute allows multiple applications, so we may have multiple possible visitors for a single type. */ var visitorContextualDetail = (from type in visitorRelevantTypes from metadatum in type.Metadata.Where(k => k.Type == attributeContext.TargetAttribute) let currentDetail = VisitorTargetDetail.DeriveFromMetadata(metadatum) group type by currentDetail into distinctVisitorDetail orderby distinctVisitorDetail.Key.TargetContext, string.IsNullOrEmpty(distinctVisitorDetail.Key.DerivedThroughInheriting) ? string.Empty : distinctVisitorDetail.Key.DerivedThroughInheriting, distinctVisitorDetail.Key.ContextualVisitor, distinctVisitorDetail.Key.YieldingVisitor select distinctVisitorDetail).ToDictionary(k => k.Key, v => new HashSet <IType>(v)); /* Break the sets into two variations: * 1. Visitors which are derived from other visitors */ var inheritanceBasedDetail = visitorContextualDetail.Keys.Where(k => !string.IsNullOrEmpty(k.DerivedThroughInheriting)).ToArray(); /* 2. The concrete visitors which aren't representative of derivation. There may be overlap. */ var nonDerivedVisitors = visitorContextualDetail.Keys.Where(k => string.IsNullOrEmpty(k.DerivedThroughInheriting)).ToArray(); var directVisitors = (from context in nonDerivedVisitors let builder = GetVisitorFrom(context, visitorContextualDetail[context], resultAssembly) select builder).ToDictionary(k => k.Detail, v => v); var inheritanceTree = (from detail in inheritanceBasedDetail orderby detail.TargetContext, detail.DerivedThroughInheriting /* We group by a *new* TargetVisitorDetail since we're not interested in the DerivedThroughInheriting, which would fragment the visitors. */ group detail.DerivedThroughInheriting by new VisitorTargetDetail { TargetContext = detail.TargetContext, ContextualVisitor = detail.ContextualVisitor, YieldingVisitor = detail.YieldingVisitor }) .ToDictionary(k => k.Key, v => v.Distinct().ToArray()); var inheritanceOnlyVisitors = new Dictionary <VisitorTargetDetail, VisitorBuilder>(); foreach (var inheritanceKey in inheritanceTree.Keys) { var inheritedVisitorNames = inheritanceTree[inheritanceKey]; var iovKey = new VisitorTargetDetail { TargetContext = inheritanceKey.TargetContext, ContextualVisitor = inheritanceKey.ContextualVisitor, YieldingVisitor = inheritanceKey.YieldingVisitor }; VisitorBuilder mainBuilder; if (!directVisitors.TryGetValue(inheritanceKey, out mainBuilder) && !inheritanceOnlyVisitors.TryGetValue(iovKey, out mainBuilder)) { inheritanceOnlyVisitors.Add(iovKey, mainBuilder = new VisitorBuilder(inheritanceKey)); } var childBuilders = (from childDetail in inheritedVisitorNames .Select(k => GetRelevantDetail(nonDerivedVisitors, inheritanceKey, k)) select directVisitors.ContainsKey(childDetail) ? directVisitors[childDetail] : inheritanceOnlyVisitors.ContainsKey(childDetail) ? inheritanceOnlyVisitors[childDetail] : new VisitorBuilder(childDetail)).ToArray(); foreach (var childBuilder in childBuilders.Where(childBuilder => childBuilder.VisitorInterface == null)) { inheritanceOnlyVisitors.Add(childBuilder.Detail, childBuilder); childBuilder.ScaffoldInterface(resultAssembly); } if (mainBuilder.VisitorInterface == null) { mainBuilder.SkippedTypes = mainBuilder.RelevantTypes = childBuilders .SelectMany(k => k.RelevantTypes) .Distinct() .ToList(); mainBuilder.ScaffoldInterface(resultAssembly); } mainBuilder.ChildBuilders = childBuilders; foreach (var childBuilder in childBuilders) { mainBuilder.VisitorInterface.ImplementedInterfaces.Add(childBuilder.VisitorInterface); } } foreach (var builder in inheritanceOnlyVisitors.Values.Concat(directVisitors.Values)) { builder.BuildVisitor(); } return(inheritanceOnlyVisitors .Values .Concat(directVisitors.Values) .OrderBy(k => k.Detail.TargetContext) .ThenBy(k => k.Detail.ContextualVisitor) .ThenBy(k => k.Detail.YieldingVisitor) .ThenBy(k => string.IsNullOrEmpty(k.Detail.DerivedThroughInheriting) ? string.Empty : k.Detail.DerivedThroughInheriting) .ToArray()); }
private static VisitorTargetDetail GetRelevantDetail(VisitorTargetDetail[] nonDerivedVisitors, VisitorTargetDetail inheritanceKey, string k) { var ndvc = nonDerivedVisitors .FirstOrDefault(j => j.TargetContext == k && j.ContextualVisitor == inheritanceKey.ContextualVisitor && j.YieldingVisitor == inheritanceKey.YieldingVisitor); return(ndvc ?? new VisitorTargetDetail { TargetContext = k, ContextualVisitor = inheritanceKey.ContextualVisitor, YieldingVisitor = inheritanceKey.YieldingVisitor, }); }
public VisitorBuilder(VisitorTargetDetail detail) { this._relevantTypes = new List <IType>(); this._detail = detail; }