using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.Serialization; namespace GitHub.DistributedTask.ObjectTemplating { /// /// Provides information about an error which occurred during validation. /// [DataContract] [EditorBrowsable(EditorBrowsableState.Never)] public sealed class TemplateValidationErrors : IEnumerable { public TemplateValidationErrors() { } public TemplateValidationErrors( Int32 maxErrors, Int32 maxMessageLength) { m_maxErrors = maxErrors; m_maxMessageLength = maxMessageLength; } public Int32 Count => m_errors.Count; public void Add(String message) { Add(new TemplateValidationError(message)); } public void Add(Exception ex) { Add(null, ex); } public void Add(String messagePrefix, Exception ex) { for (int i = 0; i < 50; i++) { String message = !String.IsNullOrEmpty(messagePrefix) ? $"{messagePrefix} {ex.Message}" : ex.ToString(); Add(new TemplateValidationError(message)); if (ex.InnerException == null) { break; } ex = ex.InnerException; } } public void Add(IEnumerable errors) { foreach (var error in errors) { Add(error); } } public void Add(TemplateValidationError error) { // Check max errors if (m_maxErrors <= 0 || m_errors.Count < m_maxErrors) { // Check max message length if (m_maxMessageLength > 0 && error.Message?.Length > m_maxMessageLength) { error = new TemplateValidationError(error.Code, error.Message.Substring(0, m_maxMessageLength) + "[...]"); } m_errors.Add(error); } } /// /// Throws if any errors. /// public void Check() { if (m_errors.Count > 0) { throw new TemplateValidationException(m_errors); } } /// /// Throws if any errors. /// The error message prefix /// public void Check(String prefix) { if (String.IsNullOrEmpty(prefix)) { this.Check(); } else if (m_errors.Count > 0) { var message = $"{prefix.Trim()} {String.Join(",", m_errors.Select(e => e.Message))}"; throw new TemplateValidationException(message, m_errors); } } public void Clear() { m_errors.Clear(); } public IEnumerator GetEnumerator() { return (m_errors as IEnumerable).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return (m_errors as IEnumerable).GetEnumerator(); } private readonly List m_errors = new List(); private readonly Int32 m_maxErrors; private readonly Int32 m_maxMessageLength; } }