/// <summary> /// Determines the requried upversioning when code transitions from the old Napack to the new Napack. /// </summary> /// <remarks> /// Major == breaking changes. /// Minor == publically-facing API was added (but not changed or removed) from the new Napack. /// Patch == The publically-facing API is identical between both Napacks, excluding documentation. /// </remarks> public static UpversionType DeterminedRequiredUpversioning(NapackSpec oldNapack, NapackSpec newNapack) { UpversionType maxUpversionType = UpversionType.Patch; foreach (ClassSpec oldClassSpec in oldNapack.Classes) { ClassSpec newClassSpec = newNapack.Classes .FirstOrDefault(cls => cls.Name.Name.Equals(oldClassSpec.Name.Name, StringComparison.InvariantCulture)); UpversionType upversionType = NapackAnalyst.AnalyzeClass(oldClassSpec, newClassSpec); if (upversionType == UpversionType.Major) { // Exit early, as we found a breaking change. return(UpversionType.Major); } else if (upversionType == UpversionType.Minor) { maxUpversionType = UpversionType.Minor; } } foreach (InterfaceSpec oldInterfaceSpec in oldNapack.Interfaces) { InterfaceSpec newInterfaceSpec = newNapack.Interfaces .FirstOrDefault(cls => cls.Name.Name.Equals(oldInterfaceSpec.Name.Name, StringComparison.InvariantCulture)); UpversionType upversionType = NapackAnalyst.AnalyzeInterface(oldInterfaceSpec, newInterfaceSpec); if (upversionType == UpversionType.Major) { // Exit early, as we found a breaking change. return(UpversionType.Major); } else if (upversionType == UpversionType.Minor) { maxUpversionType = UpversionType.Minor; } } // No APIs added in the prior classes. Did the new package add classes? if (maxUpversionType == UpversionType.Patch && (newNapack.Classes.Count != oldNapack.Classes.Count || newNapack.Interfaces.Count != oldNapack.Interfaces.Count)) { maxUpversionType = UpversionType.Minor; } return(maxUpversionType); }
private static UpversionType AnalyzeClass(ClassSpec oldClassSpec, ClassSpec newClassSpec) { UpversionType maxUpversionType = UpversionType.Patch; if (newClassSpec == null) { // The new spec removed a publically facing class. return(UpversionType.Major); } // Check if any modifier changes force a major (breaking) change. if ((!oldClassSpec.IsAbstract && newClassSpec.IsAbstract) || (oldClassSpec.IsStatic != newClassSpec.IsStatic) || (!oldClassSpec.IsSealed && newClassSpec.IsSealed)) { return(UpversionType.Major); } // Verify all old fields exist UpversionType upversionType = NapackAnalyst.AnalyzeFields(oldClassSpec.PublicFields, newClassSpec.PublicFields); if (upversionType == UpversionType.Major) { return(upversionType); } else if (upversionType == UpversionType.Minor) { maxUpversionType = UpversionType.Minor; } upversionType = NapackAnalyst.AnalyzeProperties(oldClassSpec.PublicProperties, newClassSpec.PublicProperties); if (upversionType == UpversionType.Major) { return(upversionType); } else if (upversionType == UpversionType.Minor) { maxUpversionType = UpversionType.Minor; } upversionType = NapackAnalyst.AnalyzeConstructors(oldClassSpec.PublicConstructors, newClassSpec.PublicConstructors); if (upversionType == UpversionType.Major) { return(upversionType); } else if (upversionType == UpversionType.Minor) { maxUpversionType = UpversionType.Minor; } upversionType = NapackAnalyst.AnalyzeMethods(oldClassSpec.PublicMethods, newClassSpec.PublicMethods); if (upversionType == UpversionType.Major) { return(upversionType); } else if (upversionType == UpversionType.Minor) { maxUpversionType = UpversionType.Minor; } // Analyze classes recursively. foreach (ClassSpec oldClass in oldClassSpec.PublicClasses) { ClassSpec newClass = newClassSpec.PublicClasses .FirstOrDefault(cls => cls.Name.Name.Equals(oldClass.Name.Name, StringComparison.InvariantCulture)); upversionType = NapackAnalyst.AnalyzeClass(oldClass, newClass); if (upversionType == UpversionType.Major) { return(upversionType); } else if (upversionType == UpversionType.Minor) { maxUpversionType = UpversionType.Minor; } } if (maxUpversionType == UpversionType.Patch && oldClassSpec.PublicClasses.Count != newClassSpec.PublicClasses.Count) { maxUpversionType = UpversionType.Minor; } return(maxUpversionType); }