private void MarkDeprecate(String baseFolder, FrameworkEntity e, TextWriter writer) { String file = e.GetPath(baseFolder, DocumentType.Model); if (file == null || !File.Exists(file)) { return; } this.Log(Level.Verbose, String.Format("Checking {0}...", e.name)); Action <TypedEntity> markFunctions = (t) => Mark <FunctionEntity>(t.Functions); Action <ClassEntity> markMethods = (c) => Mark <MethodEntity>(c.Methods); Action <ClassEntity> markProperties = (c) => Mark <PropertyEntity>(c.Properties); switch (e.type) { case FrameworkEntityType.T: LoadAndMark <TypedEntity> (e.name, file, writer, markFunctions); break; case FrameworkEntityType.C: LoadAndMark <ClassEntity> (e.name, file, writer, markFunctions, markMethods, markProperties); break; case FrameworkEntityType.P: LoadAndMark <ProtocolEntity> (e.name, file, writer, markFunctions, markMethods, markProperties); break; default: throw new NotSupportedException("Unsupported type: " + e.type); } }
private List <PackageDependencyEntity> InitializePackageDependencies( PackageDependencyGroups package, long packageKey, IReadOnlyDictionary <string, FrameworkEntity> originalValueToFramework, IReadOnlyDictionary <string, PackageRegistrationEntity> idToPackageRegistration) { var output = new Dictionary <UniqueDependency, PackageDependencyEntity>(); InitializePackageDependencies( output, package.DependencyGroups.Dependencies, packageKey, idToPackageRegistration, framework: null); foreach (var group in package.DependencyGroups.Groups) { FrameworkEntity framework = null; if (!string.IsNullOrEmpty(group.TargetFramework)) { originalValueToFramework.TryGetValue(group.TargetFramework, out framework); } InitializePackageDependencies( output, group.Dependencies, packageKey, idToPackageRegistration, framework); } return(output.Values.ToList()); }
protected void Patch(IEnumerable <String> paths, FrameworkEntity e, IEnumerable <PatchReplace> replacements) { foreach (var path in paths) { if (!File.Exists(path)) { continue; } this.Log(Level.Verbose, String.Format("Probing '{0}'...", e.name)); String contents = File.ReadAllText(path); bool modified = false; foreach (PatchReplace replacement in replacements) { String source = replacement.Source; String with = replacement.With; if (contents.Contains(source)) { contents = contents.Replace(source, with); modified |= true; } } if (modified) { this.Log(Level.Info, String.Format("Patching '{0}'...", e.name)); File.WriteAllText(path, contents); } else { this.Log(Level.Verbose, String.Format("Skipping '{0}'...", e.name)); } } }
protected void Patch(String baseFolder, FrameworkEntity entity, IEnumerable <PatchReplace> replacements) { String path = entity.GetPath(baseFolder, this.Type); if (path == null) { return; } IList <String> paths = new List <String>(); switch (this.Type) { case DocumentType.Generated: paths.Add(path + ".cs"); paths.Add(path + ".Class.cs"); paths.Add(path + ".Constants.cs"); paths.Add(path + ".Constructors.cs"); paths.Add(path + ".Protocol.cs"); paths.Add(path + ".Protocols.cs"); break; default: paths.Add(path); break; } this.Patch(paths, entity, replacements); }
private void Convert(Framework f, FrameworkEntity e, String sourcePath, String destinationPath, TextWriter writer = null) { switch (e.type) { case FrameworkEntityType.T: { IXhtmlTypeParser parser = this.GetTypeParser(f, e, writer); TypedEntity entity = new TypedEntity(); entity.Namespace = f.name; entity.Name = e.name; entity.Nature = e.type; parser.Parse(entity, sourcePath); entity.SaveTo(destinationPath); } break; case FrameworkEntityType.C: { IXhtmlClassParser parser = this.GetClassParser(f, e, writer); ClassEntity entity = new ClassEntity(); entity.Namespace = f.name; entity.Name = e.name; entity.Nature = e.type; parser.Parse(entity, sourcePath); entity.SaveTo(destinationPath); } break; case FrameworkEntityType.P: { IXhtmlClassParser parser = this.GetProtocolParser(f, e, writer); ProtocolEntity entity = new ProtocolEntity(); entity.Namespace = f.name; entity.Name = e.name; entity.Nature = e.type; parser.Parse(entity, sourcePath); entity.SaveTo(destinationPath); } break; default: break; } }
private async Task <IReadOnlyDictionary <string, FrameworkEntity> > AddOrUpdateFrameworksAsync(IReadOnlyList <ParsedFramework> parsedFrameworks) { using (var entityContext = new EntityContext()) { var originalValueToValue = parsedFrameworks .GroupBy(x => x.OriginalValue) .ToDictionary(x => x.Key, x => x.First().Value); var allOriginalValues = originalValueToValue.Keys.ToList(); var existingEntities = await entityContext .Frameworks .Where(x => allOriginalValues.Contains(x.OriginalValue)) .ToListAsync(); _logger.LogInformation("Found {ExistingCount} existing frameworks.", existingEntities.Count); var newOriginalValues = allOriginalValues .Except(existingEntities.Select(x => x.OriginalValue)) .ToList(); var newEntities = new List <FrameworkEntity>(); foreach (var newOriginalValue in newOriginalValues) { var newEntity = new FrameworkEntity { OriginalValue = newOriginalValue, Value = originalValueToValue[newOriginalValue], }; entityContext.Frameworks.Add(newEntity); newEntities.Add(newEntity); } _logger.LogInformation("Adding {NewCount} new frameworks.", newEntities.Count); var commitStopwatch = Stopwatch.StartNew(); var changes = await entityContext.SaveChangesAsync(); _logger.LogInformation( "Committed {Changes} framework changes. {ElapsedMilliseconds}ms", changes, commitStopwatch.ElapsedMilliseconds); return(existingEntities .Concat(newEntities) .ToDictionary(x => x.OriginalValue)); } }
private IXhtmlClassParser GetProtocolParser(Framework f, FrameworkEntity e, TextWriter writer) { switch (f.style) { case PageStyle.Cocoa: return(new XhtmlCocoaClassParser(this.settings, this.typeManager, writer)); case PageStyle.Classic: return(new XhtmlClassicClassParser(this.settings, this.typeManager, writer)); case PageStyle.Doxygen: return(new XhtmlDoxygenClassParser(this.settings, this.typeManager, writer)); default: throw new NotSupportedException("No style defined for " + f.name); } }
private void InitializePackageDependency( Dictionary <UniqueDependency, PackageDependencyEntity> output, Dependency dependency, long packageKey, IReadOnlyDictionary <string, PackageRegistrationEntity> idToPackageRegistration, FrameworkEntity framework) { if (!idToPackageRegistration.TryGetValue(dependency.Id, out var packageRegistration)) { _logger.LogWarning( "Skipping dependency {Id} {Version} since no such package registration exists.", dependency.Id, dependency.Version); return; } var dependencyEntity = new PackageDependencyEntity { ParentPackageKey = packageKey, FrameworkKey = framework?.FrameworkKey, OriginalVersionRange = dependency.Version, VersionRange = dependency.ParsedVersionRange?.ToNormalizedString(), DependencyPackageRegistrationKey = packageRegistration.PackageRegistrationKey, }; var key = new UniqueDependency( dependencyEntity.DependencyPackageRegistrationKey, dependencyEntity.FrameworkKey); if (!output.TryGetValue(key, out var existingDependencyEntity)) { output.Add(key, dependencyEntity); } else { _logger.LogWarning( "Dependency {Id} (framework '{OriginalFrameworkValue}') is a duplicate. The " + "version range that will be used is '{OriginalVersionRange}'. The " + "version range '{VersionRange}' will be skipped.", dependency.Id, framework.OriginalValue, existingDependencyEntity.OriginalVersionRange, dependency.Version); } }
private void InitializePackageDependencies( Dictionary <UniqueDependency, PackageDependencyEntity> output, IReadOnlyList <Dependency> dependencies, long packageKey, IReadOnlyDictionary <string, PackageRegistrationEntity> idToPackageRegistration, FrameworkEntity framework) { foreach (var dependency in dependencies) { InitializePackageDependency( output, dependency, packageKey, idToPackageRegistration, framework); } }
protected T FindAndLoad <T>(String baseFolder, IList <FrameworkEntity> entities, FrameworkEntityType type, String name, bool useCache = true) where T : BaseEntity { if (String.IsNullOrEmpty(name)) { return(null); } // Try the cache first String key = type + ":" + name; BaseEntity result = null; if (useCache && !cache.TryGetValue(key, out result)) { //this.Log (Level.Verbose, "Cache miss for '" + type + "' and name '" + name + "'"); var candidates = entities.Where(e => e.type == type && e.name == name).ToList(); FrameworkEntity candidate = candidates.FirstOrDefault(); // Print a warning if multiple if (candidates.Count > 1) { this.Log(Level.Warning, "Found several entities with the type '" + type + "' and name '" + name + "'"); } if (candidate != null) { String file = candidate.GetPath(baseFolder, DocumentType.Model); result = BaseEntity.LoadFrom <T> (file); } } else { //this.Log (Level.Verbose, "Cache hit for '" + type + "' and name '" + name + "'"); } // Add to MRU if (useCache && result != null) { cache.Add(key, result); } return(result as T); }
protected void Change(String baseFolder, FrameworkEntity e, IEnumerable <String> changes, TextWriter writer) { String file = e.GetPath(baseFolder, DocumentType.Model); if (file == null || !File.Exists(file)) { return; } this.Log(Level.Verbose, String.Format("Patching '{0}'...", e.name)); switch (e.type) { case FrameworkEntityType.T: LoadAndChange <TypedEntity> (e.name, file, changes, writer); break; case FrameworkEntityType.C: LoadAndChange <ClassEntity> (e.name, file, changes, writer); break; case FrameworkEntityType.P: LoadAndChange <ProtocolEntity> (e.name, file, changes, writer); break; case FrameworkEntityType.S: LoadAndChange <StructureEntity> (e.name, file, changes, writer); break; case FrameworkEntityType.E: LoadAndChange <EnumerationEntity> (e.name, file, changes, writer); break; default: throw new NotSupportedException("Unsupported type: " + e.type); } }
protected void PatchDiscussion(String baseFolder, DocSet docSet, Framework f, FrameworkEntity entity) { String path = entity.GetPath(baseFolder, this.Type); if (path == null || !File.Exists(path)) { return; } String contents = File.ReadAllText(path); bool modified = false; // Search for discussion parts int index = 0; int beginning = 0; int ending = 0; while ((beginning = contents.IndexOf(DISCUSSION_BEGIN, index)) != -1) { ending = contents.IndexOf(DISCUSSION_END, beginning); String content = contents.Substring(beginning, ending + DISCUSSION_END.Length - beginning); String replacement = content; // Count opening and closing paragraphs int opening = DISCUSSION_OPENING_REGEX.Matches(replacement).Count; int closing = DISCUSSION_CLOSING_REGEX.Matches(replacement).Count; if (opening < closing) { throw new NotSupportedException(); } if (opening > closing) { replacement = replacement.Replace("<!-- begin discussion -->", String.Empty); replacement = replacement.Replace("<!-- end discussion -->", String.Empty); for (int i = closing; i < opening; i++) { replacement += "</p>"; } replacement = "<!-- begin discussion -->" + replacement; replacement = replacement + "<!-- end discussion -->"; contents = contents.Replace(content, replacement); modified |= true; } index = beginning + replacement.Length; } if (modified) { this.Log(Level.Info, String.Format("Patching {0} for '{1}'...", this.Type, entity.name)); File.WriteAllText(path, contents); } else { this.Log(Level.Debug, String.Format("Skipping {0} for '{1}'...", this.Type, entity.name)); } }
private void Generate(String baseFolder, IList <FrameworkEntity> entities, Framework f, FrameworkEntity e, String sourcePath, String destinationPath) { switch (e.type) { case FrameworkEntityType.T: this.GenerateTypedEntity(baseFolder, entities, f, e, sourcePath, destinationPath); break; case FrameworkEntityType.C: this.GenerateClassEntity(baseFolder, entities, f, e, sourcePath, destinationPath); break; case FrameworkEntityType.P: this.GenerateProtocolEntity(baseFolder, entities, f, e, sourcePath, destinationPath); break; case FrameworkEntityType.E: this.GenerateEnumerationEntity(baseFolder, entities, f, e, sourcePath, destinationPath); break; default: break; } }
private void GenerateEnumerationEntity(String baseFolder, IList <FrameworkEntity> entities, Framework f, FrameworkEntity e, String sourcePath, String destinationPath) { String file; EnumerationEntity entity = BaseEntity.LoadFrom <EnumerationEntity> (sourcePath); if (!entity.Generate) { return; } this.Log(Level.Info, String.Format("Generating '{0}'...", e.name)); file = destinationPath + ".cs"; this.Generate <EnumerationGenerator> (f, entity, file); }
private void GenerateProtocolEntity(String baseFolder, IList <FrameworkEntity> entities, Framework f, FrameworkEntity e, String sourcePath, String destinationPath) { String file; ProtocolEntity entity = BaseEntity.LoadFrom <ProtocolEntity> (sourcePath); if (!entity.Generate) { return; } this.Log(Level.Info, String.Format("Generating '{0}'...", e.name)); this.LoadProtocolDependencies(baseFolder, entities, entity); file = destinationPath + ".Protocol.cs"; this.Generate <ProtocolGenerator> (f, entity, file); if (entity.DelegatorEntity != null) { String property = entity.DelegateProperty ?? "Delegate"; String dir = Path.GetDirectoryName(destinationPath); file = Path.Combine(dir, entity.DelegatorEntity.Name + "." + property + ".cs"); this.Generate <ClassDelegateGenerator> (f, entity, file); } if (entity.HasConstants || entity.HasEnumerations) { file = destinationPath + ".Constants.cs"; this.Generate <ClassConstantsGenerator> (f, entity, file); } }
private void GenerateClassEntity(String baseFolder, IList <FrameworkEntity> entities, Framework f, FrameworkEntity e, String sourcePath, String destinationPath) { String file; ClassEntity entity = BaseEntity.LoadFrom <ClassEntity> (sourcePath); if (!entity.Generate) { return; } this.Log(Level.Info, String.Format("Generating '{0}'...", e.name)); this.LoadClassDependencies(baseFolder, entities, entity); if (entity.ExtendedClass == null) { file = destinationPath + ".cs"; this.Generate <ClassDefinitionGenerator> (f, entity, file); file = destinationPath + ".Class.cs"; this.Generate <ClassMembersGenerator> (f, entity, file); if (entity.HasConstructors) { file = destinationPath + ".Constructors.cs"; this.Generate <ClassConstructorsGenerator> (f, entity, file); } if (entity.HasConstants || entity.HasEnumerations) { file = destinationPath + ".Constants.cs"; this.Generate <ClassConstantsGenerator> (f, entity, file); } if (entity.Protocols != null && entity.Protocols.Count > 0) { file = destinationPath + ".Protocols.cs"; this.Generate <ClassProtocolsGenerator> (f, entity, file); } } else { file = destinationPath + ".cs"; this.Generate <ClassAdditionsGenerator> (f, entity, file); if (entity.HasConstants || entity.HasEnumerations) { file = destinationPath + ".Constants.cs"; this.Generate <ClassConstantsGenerator> (f, entity, file); } } }
private void GenerateTypedEntity(String baseFolder, IList <FrameworkEntity> entities, Framework f, FrameworkEntity e, String sourcePath, String destinationPath) { String file; TypedEntity entity = BaseEntity.LoadFrom <TypedEntity> (sourcePath); if (!entity.Generate) { return; } this.Log(Level.Info, String.Format("Generating '{0}'...", e.name)); file = destinationPath + ".cs"; this.Generate <TypedGenerator> (f, entity, file); if (entity.HasOpaqueFunctions) { file = destinationPath + ".Wrap.cs"; this.Generate <OpaqueTypedGenerator> (f, entity, file); } }
private void GenerateTypedEntity(String baseFolder, IList <FrameworkEntity> entities, Framework f, FrameworkEntity e, String sourcePath, String destinationPath) { String file; TypedEntity entity = BaseEntity.LoadFrom <TypedEntity> (sourcePath); // Make sure that availability is ready entity.AdjustAvailability(); this.Log(Level.Info, String.Format("Generating '{0}'...", e.name)); if (entity.Generate) { file = destinationPath + ".cs"; this.Generate <TypedGenerator>(f, entity, file); } }
/// <summary> /// Executes the task. /// </summary> protected override void ExecuteTask() { String baseFolder = this.CreateBaseDir(); DocSet docSet = this.CreateDocSet(); IEnumerable <Framework> frameworks = this.CreateFrameworks(docSet); IList <FrameworkEntity> entities = frameworks.SelectMany(f => f.GetEntities()).ToList(); TextWriter writer = null; if (this.Report != null) { writer = new StreamWriter(this.Report.ToString()); } foreach (var f in frameworks) { if (writer != null) { writer.WriteLine(); writer.WriteLine("Framework " + f.name); writer.WriteLine(); } foreach (var e in f.GetEntities()) { this.Log(Level.Verbose, String.Format("Processing '{0}'...", e.name)); String path = e.GetPath(baseFolder, DocumentType.DocSet); if (String.IsNullOrEmpty(path)) { continue; } if (e.type == FrameworkEntityType.C) { String content = File.ReadAllText(path); Match m = PATTERN_DELEGATE.Match(content); if (!m.Success) { continue; } String name = e.name + "Delegate"; FrameworkEntity delegateEntity = entities.FirstOrDefault(v => v.name == name); if (delegateEntity == null) { continue; } if (writer != null) { writer.WriteLine(); writer.WriteLine("Entity " + delegateEntity.name); writer.WriteLine(); writer.WriteLine("<Patch type=\"Model\">"); writer.WriteLine("<Change><![CDATA[DelegateFor=\"{0}\"]]></Change>", e.name); writer.WriteLine("<Change><![CDATA[DelegateProperty=\"{0}\"]]></Change>", "Delegate"); writer.WriteLine("</Patch>"); } } if (e.type == FrameworkEntityType.P && e.name.EndsWith("Delegate")) { String name = e.name.Replace("Delegate", String.Empty); FrameworkEntity classEntity = entities.FirstOrDefault(v => v.name == name); if (classEntity == null) { continue; } if (writer != null) { writer.WriteLine(); writer.WriteLine("Entity " + e.name); writer.WriteLine(); writer.WriteLine("<Patch type=\"Model\">"); writer.WriteLine("<Change><![CDATA[DelegateFor=\"{0}\"]]></Change>", classEntity.name); writer.WriteLine("<Change><![CDATA[DelegateProperty=\"{0}\"]]></Change>", "Delegate"); writer.WriteLine("</Patch>"); } } } } if (this.Report != null) { writer.Close(); writer.Dispose(); } }