From 1801cb377ab6894b717399d96b963a1fdb7d6501 Mon Sep 17 00:00:00 2001 From: Ninja Date: Tue, 13 May 2025 22:39:42 +0100 Subject: [PATCH 1/3] - Version 5.0.0 check-in --- DeveloperGuide.md | 62 ++++--- FileUtil.Core.sln | 3 +- src/FileUtil/ColumnAttribute.cs | 17 -- src/FileUtil/Configuration/IParserSettings.cs | 1 - src/FileUtil/Engine.cs | 35 ++-- src/FileUtil/File.cs | 16 +- src/FileUtil/FileLine.cs | 2 +- src/FileUtil/FileUtil.csproj | 3 + src/FileUtil/IFileLine.cs | 11 -- src/FileUtil/LineType.cs | 12 -- src/FileUtil/Parser/Extensions.cs | 40 ----- src/FileUtil/Parser/ILineParser.cs | 8 - src/FileUtil/Parser/Impl/LineParser.cs | 156 ------------------ src/FileUtil/PrefixedFileLine.cs | 18 ++ src/FileUtil/Provider/Impl/FileHelper.cs | 13 +- src/FileUtil/Resources.Designer.cs | 134 --------------- src/FileUtil/Resources.resx | 119 ------------- .../Engine/MultiDelimited/DataLine.cs | 17 +- .../Engine/MultiDelimited/EngineFixture.cs | 11 +- .../Engine/MultiDelimited/FooterLine.cs | 11 +- .../Engine/MultiDelimited/HeaderLine.cs | 14 +- .../Engine/MultiDelimited/LineType.cs | 10 ++ .../Engine/SingleDelimited/EngineFixture.cs | 10 +- .../{SingleLine.cs => RecordLine.cs} | 5 +- test/FileUtil.Tests/Parser/InvalidTestLine.cs | 9 - .../Parser/LineParserFixture.cs | 108 ------------ test/FileUtil.Tests/Parser/TestLine.cs | 32 ---- .../Provider/FileHelperFixture.cs | 2 +- 28 files changed, 161 insertions(+), 718 deletions(-) delete mode 100644 src/FileUtil/ColumnAttribute.cs delete mode 100644 src/FileUtil/IFileLine.cs delete mode 100644 src/FileUtil/LineType.cs delete mode 100644 src/FileUtil/Parser/Extensions.cs delete mode 100644 src/FileUtil/Parser/ILineParser.cs delete mode 100644 src/FileUtil/Parser/Impl/LineParser.cs create mode 100644 src/FileUtil/PrefixedFileLine.cs delete mode 100644 src/FileUtil/Resources.Designer.cs delete mode 100644 src/FileUtil/Resources.resx create mode 100644 test/FileUtil.Tests/Engine/MultiDelimited/LineType.cs rename test/FileUtil.Tests/Engine/SingleDelimited/{SingleLine.cs => RecordLine.cs} (76%) delete mode 100644 test/FileUtil.Tests/Parser/InvalidTestLine.cs delete mode 100644 test/FileUtil.Tests/Parser/LineParserFixture.cs delete mode 100644 test/FileUtil.Tests/Parser/TestLine.cs diff --git a/DeveloperGuide.md b/DeveloperGuide.md index 3e03b67..477b616 100644 --- a/DeveloperGuide.md +++ b/DeveloperGuide.md @@ -110,7 +110,7 @@ public class File where T: FileLine ------------- -**Case 2:** Let us see how we can parse a delimiter separted file with header and footer rows. +**Case 2:** Let us see how we can parse a delimiter separted file with prefixed header, data and footer rows. ------------------------------------------------------------------------ **Note:** This file will have rows with line head to determine each row type. By default, the line heads are 'H' for header, 'D' for data and 'F' for footer respectively. all these line heads are configurable via the config. @@ -131,13 +131,7 @@ The configuration is the same as before. We can override the default line heads ``` { "configSettings":{ - "parserSettings":{ "delimiter": { "value":"|"} , - "lineHeaders": { - "header":"H", - "footer":"F", - "data":"D" - } - }, + "parserSettings":{ "delimiter": { "value":"|"} }, "providerSettings":{ "folderPath":"C:work", "fileNameFormat":"File*.txt", @@ -154,21 +148,49 @@ The configuration is the same as before. We can override the default line heads Like before we need a line class to map to each type of the row in the file ie one for the header, footer and data line respectively. +However, this time we derive from `PrefixedFileLine` class instead of `FileLine` class. +The `PrefixedFileLine` class has an extra property called `Prefix` which is used to determine the type of the line. +The prefix is set to the first column of the row by default. + We continue by creating two extra classes HeaderLine and FooterLine as follows. - public class Header : FileLine - { - [Column(0)] - public string Name { get; set; } - [Column(1)] - public DateTime Date { get; set; } - } + public class Header : PrefixedFileLine + { + public override string Prefix => "H"; + + [Column(0)] + public LineType Type { get; set; } + [Column(1)] + public string Name { get; set; } + [Column(2)] + public DateTime Date { get; set; } + } - public class Footer : FileLine - { - [Column(0)] - public string FileRemarks { get; set; } - } + public class Employee : PrefixedFileLine + { + public override string Prefix => "D"; + + [Column(0)] + public LineType Type { get; set; } + [Column(1)] + public string Title { get; set; } + [Column(2)] + public string Name { get; set; } + [Column(3)] + public string Sex { get; set; } + [Column(4, "London")] + public string Location { get; set; } + } + + public class Footer : FileLine + { + public override string Prefix => "F"; + + [Column(0)] + public LineType Type { get; set; } + [Column(1)] + public string FileRemarks { get; set; } + } To parse the file you call the GetFiles() Method as follows - diff --git a/FileUtil.Core.sln b/FileUtil.Core.sln index 8061fe0..c664a39 100644 --- a/FileUtil.Core.sln +++ b/FileUtil.Core.sln @@ -11,8 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileUtil.Tests", "test\File EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{D549CC35-5318-45B0-ACCD-F28C543E482C}" ProjectSection(SolutionItems) = preProject - .github\workflows\Master-Build.yml = .github\workflows\Master-Build.yml .github\workflows\CI-Package-Release.yml = .github\workflows\CI-Package-Release.yml + .github\workflows\Master-Build.yml = .github\workflows\Master-Build.yml .github\workflows\Master-CodeQL.yml = .github\workflows\Master-CodeQL.yml .github\workflows\PR-CodeQL.yml = .github\workflows\PR-CodeQL.yml EndProjectSection @@ -25,6 +25,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".misc", ".misc", "{8EDBC8F3 ProjectSection(SolutionItems) = preProject .gitattributes = .gitattributes .gitignore = .gitignore + DeveloperGuide.md = DeveloperGuide.md GitVersion.yml = GitVersion.yml License.md = License.md nuget.config = nuget.config diff --git a/src/FileUtil/ColumnAttribute.cs b/src/FileUtil/ColumnAttribute.cs deleted file mode 100644 index b4ecf9f..0000000 --- a/src/FileUtil/ColumnAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace FileUtil -{ - public class ColumnAttribute : Attribute - { - public ColumnAttribute(int index, object defaultvalue = null) - { - Index = index; - DefaultValue = defaultvalue; - } - - public int Index { get; } - public object DefaultValue { get; } - } - -} \ No newline at end of file diff --git a/src/FileUtil/Configuration/IParserSettings.cs b/src/FileUtil/Configuration/IParserSettings.cs index c9a6f35..0f213ca 100644 --- a/src/FileUtil/Configuration/IParserSettings.cs +++ b/src/FileUtil/Configuration/IParserSettings.cs @@ -3,6 +3,5 @@ namespace FileUtil.Configuration public interface IParserSettings { IDelimiter Delimiter { get; set; } - ILineHeaders LineHeaders { get; set; } } } \ No newline at end of file diff --git a/src/FileUtil/Engine.cs b/src/FileUtil/Engine.cs index d5310ca..bb504d1 100644 --- a/src/FileUtil/Engine.cs +++ b/src/FileUtil/Engine.cs @@ -1,21 +1,21 @@ +using System.Collections.Generic; using System.Linq; using FileUtil.Configuration; -using FileUtil.Parser; -using FileUtil.Parser.Impl; using FileUtil.Provider; using FileUtil.Provider.Impl; +using parsley; namespace FileUtil { public class Engine { private readonly IFileProvider fileProvider; - private readonly ILineParser lineParser; + private readonly IParser parser; - internal Engine(ILineParser lineParser, IFileProvider fileProvider) + internal Engine(IParser parser, IFileProvider fileProvider) { this.fileProvider = fileProvider; - this.lineParser = lineParser; + this.parser = parser; } /// @@ -26,7 +26,7 @@ internal Engine(ILineParser lineParser, IFileProvider fileProvider) /// /// Configuration settings for default file provider and parser public Engine(IConfigSettings settings) - : this(new LineParser(settings.ParserSettings), new DefaulProvider(settings.ProviderSettings, new FileHelper())) + : this(new Parser((settings?.ParserSettings?.Delimiter?.Value).GetValueOrDefault(',')), new DefaulProvider(settings.ProviderSettings, new FileHelper())) { } @@ -36,7 +36,7 @@ public Engine(IConfigSettings settings) /// Parser settings. /// Custom file provider instance. public Engine(IParserSettings parserSettings, IFileProvider fileProvider) - : this(new LineParser(parserSettings), fileProvider) + : this(new Parser((parserSettings?.Delimiter?.Value).GetValueOrDefault(',')), fileProvider) { } @@ -64,9 +64,8 @@ public Engine(IParserSettings parserSettings, IFileProvider fileProvider) Lines = file.Lines, }, - Data = lineParser.Parse(file.Lines) - }) - .ToArray(); + Data = parser.Parse(file.Lines) + }).ToArray(); } /// @@ -88,14 +87,18 @@ public Engine(IParserSettings parserSettings, IFileProvider fileProvider) /// Collection of Files each parsed with header, footer and data typed arrays /// public File[] GetFiles() - where TH : FileLine, new() - where TD : FileLine, new() - where TF : FileLine, new() + where TH : PrefixedFileLine, new() + where TD : PrefixedFileLine, new() + where TF : PrefixedFileLine, new() { var files = fileProvider.GetFiles(); return files.Select(file => { + var headerLines = file.Lines.Where(line => line.StartsWith(new TH().Prefix)).ToArray(); + var footerLines = file.Lines.Where(line => line.StartsWith(new TF().Prefix)).ToArray(); + var dataLines = file.Lines.Where(line => line.StartsWith(new TD().Prefix)).ToArray(); + var parsed = new File { FileMeta = new FileMeta @@ -106,9 +109,9 @@ public File[] GetFiles() Lines = file.Lines, }, - Header = lineParser.Parse(file.Lines, LineType.Header).FirstOrDefault(), - Footer = lineParser.Parse(file.Lines, LineType.Footer).FirstOrDefault(), - Data = lineParser.Parse(file.Lines, LineType.Data) + Header = parser.Parse(headerLines).FirstOrDefault(), + Data = parser.Parse(dataLines).ToArray(), + Footer = parser.Parse(footerLines).FirstOrDefault() }; return parsed; diff --git a/src/FileUtil/File.cs b/src/FileUtil/File.cs index 4d2bfbc..18e79da 100644 --- a/src/FileUtil/File.cs +++ b/src/FileUtil/File.cs @@ -1,4 +1,4 @@ -namespace FileUtil +namespace FileUtil { public class File where T : FileLine { @@ -6,29 +6,32 @@ public class File where T : FileLine /// File meta data. /// public FileMeta FileMeta { get; set; } + /// /// Strongly typed parsed lines. /// public T[] Data { get; set; } - } - public class File where TH : FileLine, new() - where TD : FileLine, new() - where TF : FileLine, new() + public class File where TH : PrefixedFileLine, new() + where TD : PrefixedFileLine, new() + where TF : PrefixedFileLine, new() { /// /// File meta data. /// public FileMeta FileMeta { get; set; } + /// /// Parsed header line. /// public TH Header { get; set; } + /// /// Parsed data lines. /// public TD[] Data { get; set; } + /// /// Parsed footer line. /// @@ -41,14 +44,17 @@ public class FileMeta /// File Path /// public string FilePath { get; set; } + /// /// File Name /// public string FileName { get; set; } + /// /// File Size /// public long FileSize { get; set; } + /// /// Raw lines in the file (not parsed). /// diff --git a/src/FileUtil/FileLine.cs b/src/FileUtil/FileLine.cs index 3d86839..c2d2c93 100644 --- a/src/FileUtil/FileLine.cs +++ b/src/FileUtil/FileLine.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using parsley; namespace FileUtil { @@ -10,7 +11,6 @@ protected FileLine() } public int Index { get; set; } - public LineType Type { get; set; } public IList Errors { get; set; } } } \ No newline at end of file diff --git a/src/FileUtil/FileUtil.csproj b/src/FileUtil/FileUtil.csproj index db896bf..cac1ea7 100644 --- a/src/FileUtil/FileUtil.csproj +++ b/src/FileUtil/FileUtil.csproj @@ -41,4 +41,7 @@ Example: pipe delimited, csv, tsv, etc. \ + + + \ No newline at end of file diff --git a/src/FileUtil/IFileLine.cs b/src/FileUtil/IFileLine.cs deleted file mode 100644 index 5bb8b7f..0000000 --- a/src/FileUtil/IFileLine.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace FileUtil -{ - internal interface IFileLine - { - int Index { get; set; } - LineType Type { get; set; } - IList Errors { get; set; } - } -} \ No newline at end of file diff --git a/src/FileUtil/LineType.cs b/src/FileUtil/LineType.cs deleted file mode 100644 index de840c7..0000000 --- a/src/FileUtil/LineType.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace FileUtil -{ - public enum LineType - { - Unknown = 0, - Header, - Footer, - Data - } - - -} \ No newline at end of file diff --git a/src/FileUtil/Parser/Extensions.cs b/src/FileUtil/Parser/Extensions.cs deleted file mode 100644 index 884979e..0000000 --- a/src/FileUtil/Parser/Extensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using FileUtil.Configuration; - -namespace FileUtil.Parser -{ - internal static class Extensions - { - public static bool In(this string input, params string[] values) - { - return values != null && values.Contains(input); - } - - public static void SetError(this IFileLine obj, string error) - { - if (obj.Errors == null) - obj.Errors = new List(); - - obj.Errors.Add(error); - } - - public static char GetValue(this IDelimiter delimiter) - { - return delimiter?.Value ?? ','; - } - - public static string GetLineHead(this ILineHeaders lineHeaders, LineType type) - { - switch (type) - { - case LineType.Header: - return lineHeaders?.Header ?? "H"; - case LineType.Footer: - return lineHeaders?.Footer ?? "F"; - default: - return lineHeaders?.Data ?? "D"; - } - } - } -} \ No newline at end of file diff --git a/src/FileUtil/Parser/ILineParser.cs b/src/FileUtil/Parser/ILineParser.cs deleted file mode 100644 index cbf8b51..0000000 --- a/src/FileUtil/Parser/ILineParser.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace FileUtil.Parser -{ - internal interface ILineParser - { - T[] Parse(string[] lines) where T : IFileLine, new(); - T[] Parse(string[] lines, LineType type) where T : IFileLine, new(); - } -} \ No newline at end of file diff --git a/src/FileUtil/Parser/Impl/LineParser.cs b/src/FileUtil/Parser/Impl/LineParser.cs deleted file mode 100644 index 207cd28..0000000 --- a/src/FileUtil/Parser/Impl/LineParser.cs +++ /dev/null @@ -1,156 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using FileUtil.Configuration; -using Ninja.FileUtil; - -namespace FileUtil.Parser.Impl -{ - internal class LineParser : ILineParser - { - private readonly IParserSettings parserSettings; - - public LineParser(IParserSettings parserSettings) - { - this.parserSettings = parserSettings; - } - - public T[] Parse(string[] lines) where T : IFileLine, new() - { - return Parse(lines, LineType.Data, false); - } - - public T[] Parse(string[] lines, LineType type) where T : IFileLine, new() - { - var filteredLines = lines?.Where(x => x.StartsWith(parserSettings.LineHeaders.GetLineHead(type))).ToArray(); - return Parse(filteredLines, type, true); - } - - private T[] Parse(string[] lines, LineType type, bool hasLineHeader) where T : IFileLine, new() - { - - if (lines == null || lines.Length == 0) - return Enumerable.Empty().ToArray(); - - var list = new T[lines.Length]; - - var objLock = new object(); - - var index = 0; - var inputs = lines.Select(line => new { Line = line, Index = index++, Type = type }); - - Parallel.ForEach(inputs, () => new List(), - (obj, loopstate, localStorage) => - { - var parsed = ParseLine(obj.Line, hasLineHeader); - - parsed.Index = obj.Index; - parsed.Type = obj.Type; - - localStorage.Add(parsed); - return localStorage; - }, - finalStorage => - { - if (finalStorage == null) - return; - - lock (objLock) - finalStorage.ForEach(f => list[f.Index] = f); - }); - - - return list; - } - - - private T ParseLine(string line, bool hasLineHeader) where T : IFileLine, new() - { - var obj = new T(); - - var values = GetDelimiterSeparatedValues(line); - - if (values.Length == 0 || values.Length == 1) - { - obj.SetError(Resources.InvalidLineFormat); - return obj; - } - - var propInfos = GetLineClassPropertyInfos(); - - if (propInfos.Length == 0) - { - obj.SetError(string.Format(Resources.NoColumnAttributesFoundFormat, typeof(T).Name)); - return obj; - } - - if (!hasLineHeader && propInfos.Length != values.Length || - hasLineHeader && propInfos.Length + 1 != values.Length) - { - obj.SetError(Resources.InvalidLengthErrorFormat); - return obj; - } - - foreach (var propInfo in propInfos) - try - { - var attribute = (ColumnAttribute)propInfo.GetCustomAttributes(typeof(ColumnAttribute), true).First(); - - var pvalue = values[!hasLineHeader ? attribute.Index : attribute.Index + 1]; - - if (string.IsNullOrWhiteSpace(pvalue) && attribute.DefaultValue != null) - pvalue = attribute.DefaultValue.ToString(); - - if (propInfo.PropertyType.IsEnum) - { - if (string.IsNullOrWhiteSpace(pvalue)) - { - obj.SetError(string.Format(Resources.InvalidEnumValueErrorFormat, propInfo.Name)); - continue; - } - - if (long.TryParse(pvalue, out var enumLong)) - { - var numeric = Enum.ToObject(propInfo.PropertyType, enumLong); - propInfo.SetValue(obj, numeric, null); - continue; - } - - var val = Enum.Parse(propInfo.PropertyType, pvalue, true); - propInfo.SetValue(obj, val, null); - continue; - } - - var converter = TypeDescriptor.GetConverter(propInfo.PropertyType); - var value = converter.ConvertFrom(pvalue); - - propInfo.SetValue(obj, value, null); - } - catch (Exception e) - { - obj.SetError(string.Format(Resources.LineExceptionFormat, propInfo.Name, e.Message)); - } - - return obj; - } - - private static PropertyInfo[] GetLineClassPropertyInfos() where T : IFileLine, new() - { - var propInfos = typeof(T).GetProperties() - .Where(p => p.GetCustomAttributes(typeof(ColumnAttribute), true).Any() && p.CanWrite) - .ToArray(); - return propInfos; - } - - private string[] GetDelimiterSeparatedValues(string line) - { - var values = line.Split(parserSettings.Delimiter.GetValue()) - .Select(x => !string.IsNullOrWhiteSpace(x) ? x.Trim() : x) - .ToArray(); - return values; - } - } -} diff --git a/src/FileUtil/PrefixedFileLine.cs b/src/FileUtil/PrefixedFileLine.cs new file mode 100644 index 0000000..ae6b5b5 --- /dev/null +++ b/src/FileUtil/PrefixedFileLine.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using parsley; + +namespace FileUtil +{ + public abstract class PrefixedFileLine : IFileLine + { + protected PrefixedFileLine() + { + Errors = new List(); + } + + public abstract string Prefix { get; } + + public int Index { get; set; } + public IList Errors { get; set; } + } +} \ No newline at end of file diff --git a/src/FileUtil/Provider/Impl/FileHelper.cs b/src/FileUtil/Provider/Impl/FileHelper.cs index 4a91979..5670f2b 100644 --- a/src/FileUtil/Provider/Impl/FileHelper.cs +++ b/src/FileUtil/Provider/Impl/FileHelper.cs @@ -1,5 +1,6 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; +using System.Reflection.PortableExecutable; namespace FileUtil.Provider.Impl { @@ -37,6 +38,7 @@ public bool TryDeleteFile(FileInfo fileInfo) return false; } } + public void EnsureFolderExist(string folderFullName) { if (!Directory.Exists(folderFullName)) @@ -57,9 +59,12 @@ public string[] ReadToLines(string path) var lines = new List(); using (var sr = new StreamReader(File.Open(path, FileMode.Open))) { - var line = sr.ReadLine(); - if (line != null) - lines.Add(line); + while (sr.Peek() != -1) + { + var line = sr.ReadLine(); + if (line != null) + lines.Add(line); + } } return lines.ToArray(); diff --git a/src/FileUtil/Resources.Designer.cs b/src/FileUtil/Resources.Designer.cs deleted file mode 100644 index 195f184..0000000 --- a/src/FileUtil/Resources.Designer.cs +++ /dev/null @@ -1,134 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System.CodeDom.Compiler; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Resources; -using System.Runtime.CompilerServices; - -namespace Ninja.FileUtil { - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [DebuggerNonUserCode()] - [CompilerGenerated()] - internal class Resources { - - private static ResourceManager resourceMan; - - private static CultureInfo resourceCulture; - - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [EditorBrowsable(EditorBrowsableState.Advanced)] - internal static ResourceManager ResourceManager { - get { - if (ReferenceEquals(resourceMan, null)) { - ResourceManager temp = new ResourceManager("FileUtil.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [EditorBrowsable(EditorBrowsableState.Advanced)] - internal static CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to {0} failed to parse - Invalid enum value. - /// - internal static string InvalidEnumValueErrorFormat - { - get - { - return ResourceManager.GetString("InvalidEnumValueErrorFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid line format - number of column values do not match. - /// - internal static string InvalidLengthErrorFormat - { - get - { - return ResourceManager.GetString("InvalidLengthErrorFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid line format - is not delimeter separated. - /// - internal static string InvalidLineFormat - { - get - { - return ResourceManager.GetString("InvalidLineFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid line format - Invalid line type value. - /// - internal static string InvalidTypeValueError - { - get - { - return ResourceManager.GetString("InvalidTypeValueError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} failed to parse with error - {1}. - /// - internal static string LineExceptionFormat - { - get - { - return ResourceManager.GetString("LineExceptionFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No column attributes found on Line - {0}. - /// - internal static string NoColumnAttributesFoundFormat - { - get - { - return ResourceManager.GetString("NoColumnAttributesFoundFormat", resourceCulture); - } - } - } -} diff --git a/src/FileUtil/Resources.resx b/src/FileUtil/Resources.resx deleted file mode 100644 index 1ad0d7d..0000000 --- a/src/FileUtil/Resources.resx +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - {0} failed to parse - Invalid enum value - - - Invalid line format - number of column values do not match - - - Invalid line format - is not delimeter separated - - - Invalid line format - Invalid line type value - - - {0} failed to parse with error - {1} - - - No column attributes found on Line - {0} - - \ No newline at end of file diff --git a/test/FileUtil.Tests/Engine/MultiDelimited/DataLine.cs b/test/FileUtil.Tests/Engine/MultiDelimited/DataLine.cs index 1cc5276..74981ba 100644 --- a/test/FileUtil.Tests/Engine/MultiDelimited/DataLine.cs +++ b/test/FileUtil.Tests/Engine/MultiDelimited/DataLine.cs @@ -1,12 +1,21 @@ -namespace FileUtil.Tests.Engine.MultiDelimited +using parsley; + +namespace FileUtil.Tests.Engine.MultiDelimited { - public class DataLine : FileLine + public class DataLine : PrefixedFileLine { + public override string Prefix => "D"; + [Column(0)] - public string Employee { get; set; } + public LineType Type { get; set; } + [Column(1)] - public string Reference { get; set; } + public string Employee { get; set; } + [Column(2)] + public string Reference { get; set; } + + [Column(3)] public bool InService { get; set; } } } \ No newline at end of file diff --git a/test/FileUtil.Tests/Engine/MultiDelimited/EngineFixture.cs b/test/FileUtil.Tests/Engine/MultiDelimited/EngineFixture.cs index cf50335..8cbf011 100644 --- a/test/FileUtil.Tests/Engine/MultiDelimited/EngineFixture.cs +++ b/test/FileUtil.Tests/Engine/MultiDelimited/EngineFixture.cs @@ -21,9 +21,6 @@ public void Setup() delimiter = new Mock(); delimiter.Setup(x => x.Value).Returns('|'); configuration.Setup(x => x.Delimiter).Returns(delimiter.Object); - configuration.Setup(x => x.LineHeaders.Header).Returns("H"); - configuration.Setup(x => x.LineHeaders.Data).Returns("D"); - configuration.Setup(x => x.LineHeaders.Footer).Returns("F"); engine = new FileUtil.Engine(configuration.Object, provider.Object); } @@ -35,7 +32,7 @@ public void TestGetFilesForNoFileFromProviderShouldReturnEmptyCollection() } [Test] - public void TestGetFilesForFileReceivedFromProviderShouldReturnEmptyCollection() + public void TestGetFilesForFileReceivedFromProviderShouldReturnCorrectFileCollection() { var date = new DateTime(2016, 10, 22); var fileMeta = new FileMeta @@ -59,7 +56,7 @@ public void TestGetFilesForFileReceivedFromProviderShouldReturnEmptyCollection() Assert.That(parsedfiles[0].Header, Is.AssignableFrom()); Assert.That(parsedfiles[0].Header.Index, Is.EqualTo(0)); - Assert.That(parsedfiles[0].Header.Type, Is.EqualTo(LineType.Header)); + Assert.That(parsedfiles[0].Header.Type, Is.EqualTo(LineType.H)); Assert.That(parsedfiles[0].Header.Errors, Is.Empty); Assert.That(parsedfiles[0].Header.Date, Is.EqualTo(date)); Assert.That(parsedfiles[0].Header.Name, Is.EqualTo("Employee Status")); @@ -67,7 +64,7 @@ public void TestGetFilesForFileReceivedFromProviderShouldReturnEmptyCollection() Assert.That(parsedfiles[0].Data[0], Is.AssignableFrom()); Assert.That(parsedfiles[0].Data[0].Index, Is.EqualTo(0)); - Assert.That(parsedfiles[0].Data[0].Type, Is.EqualTo(LineType.Data)); + Assert.That(parsedfiles[0].Data[0].Type, Is.EqualTo(LineType.D)); Assert.That(parsedfiles[0].Data[0].Errors, Is.Empty); Assert.That(parsedfiles[0].Data[0].Employee, Is.EqualTo("John Walsh")); @@ -77,7 +74,7 @@ public void TestGetFilesForFileReceivedFromProviderShouldReturnEmptyCollection() Assert.That(parsedfiles[0].Footer, Is.AssignableFrom()); Assert.That(parsedfiles[0].Footer.Index, Is.EqualTo(0)); - Assert.That(parsedfiles[0].Footer.Type, Is.EqualTo(LineType.Footer)); + Assert.That(parsedfiles[0].Footer.Type, Is.EqualTo(LineType.F)); Assert.That(parsedfiles[0].Footer.Errors, Is.Empty); Assert.That(parsedfiles[0].Footer.TotalRecords, Is.EqualTo(1)); diff --git a/test/FileUtil.Tests/Engine/MultiDelimited/FooterLine.cs b/test/FileUtil.Tests/Engine/MultiDelimited/FooterLine.cs index 793f681..25e5552 100644 --- a/test/FileUtil.Tests/Engine/MultiDelimited/FooterLine.cs +++ b/test/FileUtil.Tests/Engine/MultiDelimited/FooterLine.cs @@ -1,8 +1,15 @@ -namespace FileUtil.Tests.Engine.MultiDelimited +using parsley; + +namespace FileUtil.Tests.Engine.MultiDelimited { - public class FooterLine : FileLine + public class FooterLine : PrefixedFileLine { + public override string Prefix => "F"; + [Column(0)] + public LineType Type { get; set; } + + [Column(1)] public int TotalRecords { get; set; } } } \ No newline at end of file diff --git a/test/FileUtil.Tests/Engine/MultiDelimited/HeaderLine.cs b/test/FileUtil.Tests/Engine/MultiDelimited/HeaderLine.cs index d153e3e..b96d1a6 100644 --- a/test/FileUtil.Tests/Engine/MultiDelimited/HeaderLine.cs +++ b/test/FileUtil.Tests/Engine/MultiDelimited/HeaderLine.cs @@ -1,10 +1,18 @@ -namespace FileUtil.Tests.Engine.MultiDelimited +using parsley; + +namespace FileUtil.Tests.Engine.MultiDelimited { - public class HeaderLine : FileLine + public class HeaderLine : PrefixedFileLine { + public override string Prefix => "H"; + [Column(0)] - public DateTime Date { get; set; } + public LineType Type { get; set; } + [Column(1)] + public DateTime Date { get; set; } + + [Column(2)] public string Name { get; set; } } } \ No newline at end of file diff --git a/test/FileUtil.Tests/Engine/MultiDelimited/LineType.cs b/test/FileUtil.Tests/Engine/MultiDelimited/LineType.cs new file mode 100644 index 0000000..43a2357 --- /dev/null +++ b/test/FileUtil.Tests/Engine/MultiDelimited/LineType.cs @@ -0,0 +1,10 @@ +namespace FileUtil.Tests.Engine.MultiDelimited +{ + public enum LineType + { + U = 0, + H, + F, + D + } +} \ No newline at end of file diff --git a/test/FileUtil.Tests/Engine/SingleDelimited/EngineFixture.cs b/test/FileUtil.Tests/Engine/SingleDelimited/EngineFixture.cs index b16811b..ce7fbba 100644 --- a/test/FileUtil.Tests/Engine/SingleDelimited/EngineFixture.cs +++ b/test/FileUtil.Tests/Engine/SingleDelimited/EngineFixture.cs @@ -27,7 +27,7 @@ public void Setup() [Test] public void TestGetFilesForNoFileFromProviderShouldReturnEmptyCollection() { - Assert.That(engine.GetFiles(), Is.Empty); + Assert.That(engine.GetFiles(), Is.Empty); } [Test] @@ -43,7 +43,7 @@ public void TestGetFilesForFileReceivedFromProviderShouldReturnEmptyCollection() provider.Setup(x => x.GetFiles()).Returns(new[] { fileMeta }); - var parsedfiles = engine.GetFiles(); + var parsedfiles = engine.GetFiles(); Assert.That(parsedfiles, Is.Not.Empty); Assert.That(parsedfiles[0].FileMeta.FileName, Is.EqualTo(fileMeta.FileName)); @@ -51,18 +51,16 @@ public void TestGetFilesForFileReceivedFromProviderShouldReturnEmptyCollection() Assert.That(parsedfiles[0].FileMeta.FileSize, Is.EqualTo(fileMeta.FileSize)); Assert.That(parsedfiles[0].FileMeta.Lines, Is.EqualTo(fileMeta.Lines)); - Assert.That(parsedfiles[0].Data[0], Is.AssignableFrom()); - Assert.That(parsedfiles[0].Data[1], Is.AssignableFrom()); + Assert.That(parsedfiles[0].Data[0], Is.AssignableFrom()); + Assert.That(parsedfiles[0].Data[1], Is.AssignableFrom()); Assert.That(parsedfiles[0].Data[0].Index, Is.EqualTo(0)); - Assert.That(parsedfiles[0].Data[0].Type, Is.EqualTo(LineType.Data)); Assert.That(parsedfiles[0].Data[0].Errors, Is.Empty); Assert.That(parsedfiles[0].Data[0].Name, Is.EqualTo("Jack Marias")); Assert.That(parsedfiles[0].Data[0].IsMember, Is.EqualTo(false)); Assert.That(parsedfiles[0].Data[1].Index, Is.EqualTo(1)); - Assert.That(parsedfiles[0].Data[1].Type, Is.EqualTo(LineType.Data)); Assert.That(parsedfiles[0].Data[0].Errors, Is.Empty); Assert.That(parsedfiles[0].Data[1].Name, Is.EqualTo("Samuel Dias")); diff --git a/test/FileUtil.Tests/Engine/SingleDelimited/SingleLine.cs b/test/FileUtil.Tests/Engine/SingleDelimited/RecordLine.cs similarity index 76% rename from test/FileUtil.Tests/Engine/SingleDelimited/SingleLine.cs rename to test/FileUtil.Tests/Engine/SingleDelimited/RecordLine.cs index fe9bfbc..2f2f150 100644 --- a/test/FileUtil.Tests/Engine/SingleDelimited/SingleLine.cs +++ b/test/FileUtil.Tests/Engine/SingleDelimited/RecordLine.cs @@ -1,9 +1,12 @@ +using parsley; + namespace FileUtil.Tests.Engine.SingleDelimited { - public class SingleLine : FileLine + public class RecordLine : FileLine { [Column(0)] public string Name { get; set; } + [Column(1)] public bool IsMember { get; set; } } diff --git a/test/FileUtil.Tests/Parser/InvalidTestLine.cs b/test/FileUtil.Tests/Parser/InvalidTestLine.cs deleted file mode 100644 index 150c746..0000000 --- a/test/FileUtil.Tests/Parser/InvalidTestLine.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace FileUtil.Tests.Parser -{ - public class InvalidTestLine : IFileLine - { - public int Index { get; set; } - public LineType Type { get; set; } - public IList Errors { get; set; } - } -} \ No newline at end of file diff --git a/test/FileUtil.Tests/Parser/LineParserFixture.cs b/test/FileUtil.Tests/Parser/LineParserFixture.cs deleted file mode 100644 index 8564ad1..0000000 --- a/test/FileUtil.Tests/Parser/LineParserFixture.cs +++ /dev/null @@ -1,108 +0,0 @@ -using FileUtil.Configuration; -using FileUtil.Parser.Impl; -using Moq; -using NUnit.Framework; - -namespace FileUtil.Tests.Parser -{ - [TestFixture] - internal class LineParserFixture - { - private Mock configuration; - private LineParser parser; - - [SetUp] - public void Setup() - { - configuration = new Mock(); - - configuration.Setup(x => x.Delimiter.Value).Returns('|'); - configuration.Setup(x => x.LineHeaders.Header).Returns("H"); - configuration.Setup(x => x.LineHeaders.Data).Returns("D"); - configuration.Setup(x => x.LineHeaders.Footer).Returns("F"); - parser = new LineParser(configuration.Object); - } - - [Test] - public void TestParseForNullInputShouldReturnEmptyArray() - { - Assert.That(parser.Parse(null), Is.Empty); - Assert.That(parser.Parse(null, LineType.Data), Is.Empty); - } - - [Test] - public void TestParseWithLineHeaderInputShouldReturnCorrectlyParsedArray() - { - var lines = new[] - { - "D|Bob Marley|True", - "D|John Walsh|False" - }; - - var parsed = parser.Parse(lines, LineType.Data); - - Assert.That(parsed.Length, Is.EqualTo(2)); - - Assert.That(parsed[0].Name, Is.EqualTo("Bob Marley")); - Assert.That(parsed[0].IsMember, Is.EqualTo(true)); - Assert.That(parsed[0].Type, Is.EqualTo(LineType.Data)); - Assert.That(parsed[0].Errors, Is.Empty); - - Assert.That(parsed[1].Name, Is.EqualTo("John Walsh")); - Assert.That(parsed[1].IsMember, Is.EqualTo(false)); - Assert.That(parsed[1].Type, Is.EqualTo(LineType.Data)); - Assert.That(parsed[1].Errors, Is.Empty); - } - - [Test] - public void TestParseWithNoLineHeaderInputShouldReturnCorrectlyParsedArray() - { - var lines = new[] - { - "Bob Marley|True", - "John Walsh|False" - }; - var prsed = parser.Parse(lines); - - Assert.That(prsed.Length, Is.EqualTo(2)); - - Assert.That(prsed[0].Name, Is.EqualTo("Bob Marley")); - Assert.That(prsed[0].IsMember, Is.EqualTo(true)); - Assert.That(prsed[0].Type, Is.EqualTo(LineType.Data)); - Assert.That(prsed[0].Errors, Is.Empty); - - Assert.That(prsed[1].Name, Is.EqualTo("John Walsh")); - Assert.That(prsed[1].IsMember, Is.EqualTo(false)); - Assert.That(prsed[1].Type, Is.EqualTo(LineType.Data)); - Assert.That(prsed[1].Errors, Is.Empty); - } - - [TestCase("hbtrb", true)] - [TestCase("hbtrb|ej ef|fer|", true)] - [TestCase("H|hbtrb", false)] - [TestCase("H|hbtrb|ej ef|fer|rc |", true)] - public void TestParseForInvalidInputShouldReturnError(string line, bool hasLineType) - { - if (!hasLineType) - parser = new LineParser(configuration.Object); - - var result = hasLineType - ? parser.Parse(new[] { line }) - : parser.Parse(new[] { line }, LineType.Header); - - Assert.That(result[0].Errors, Is.Not.Empty); - } - - [Test] - public void TestParseForInvalidFileLineWithNoColumnAttributesShouldReturnError() - { - var result = parser.Parse(new[] { "D|edndx|medmd" }, LineType.Data); - - Assert.That(result[0].Errors, Is.Not.Empty); - - result = parser.Parse(new[] { "edndx|medmd" }); - - Assert.That(result[0].Errors, Is.Not.Empty); - } - } -} \ No newline at end of file diff --git a/test/FileUtil.Tests/Parser/TestLine.cs b/test/FileUtil.Tests/Parser/TestLine.cs deleted file mode 100644 index 9fd78db..0000000 --- a/test/FileUtil.Tests/Parser/TestLine.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace FileUtil.Tests.Parser -{ - public class TestLine : IFileLine - { - public TestLine() - { - Errors = new List(); - } - - public int Index { get; set; } - public LineType Type { get; set; } - public IList Errors { get; set; } - - [Column(0)] - public string Name { get; set; } - [Column(1)] - public bool IsMember { get; set; } - } - public class FooterLine : FileLine - { - [Column(0)] - public int TotalRecords { get; set; } - } - - public class HeaderLine : FileLine - { - [Column(0)] - public string Report { get; set; } - [Column(1)] - public DateTime Date { get; set; } - } -} \ No newline at end of file diff --git a/test/FileUtil.Tests/Provider/FileHelperFixture.cs b/test/FileUtil.Tests/Provider/FileHelperFixture.cs index 191a251..33a7317 100644 --- a/test/FileUtil.Tests/Provider/FileHelperFixture.cs +++ b/test/FileUtil.Tests/Provider/FileHelperFixture.cs @@ -22,7 +22,7 @@ public void Setup() public void TestGetFilesForFileWhichDoesNotExistsShouldReturnEmptyFileCollection() { var lines = fileHelper.ReadToLines(filePath); - Assert.That(lines.Length, Is.EqualTo(1)); + Assert.That(lines.Length, Is.EqualTo(2)); } public void CreateFile(string path) From 75da08e93504ff8aac529943cf0bb540ebccbca3 Mon Sep 17 00:00:00 2001 From: Ninja Date: Tue, 13 May 2025 22:56:31 +0100 Subject: [PATCH 2/3] - Update project properties --- .github/workflows/CI-Package-Release.yml | 12 ++-- .github/workflows/Master-Build.yml | 4 +- .github/workflows/Master-CodeQL.yml | 87 ++++++++++++++++-------- .github/workflows/PR-CodeQL.yml | 78 ++++++++++++++------- GitVersion.yml | 2 +- License.md | 2 +- README.md | 3 +- src/FileUtil/FileUtil.csproj | 4 +- 8 files changed, 126 insertions(+), 66 deletions(-) diff --git a/.github/workflows/CI-Package-Release.yml b/.github/workflows/CI-Package-Release.yml index 725dd8d..460776f 100644 --- a/.github/workflows/CI-Package-Release.yml +++ b/.github/workflows/CI-Package-Release.yml @@ -13,7 +13,7 @@ jobs: github-token: '${{ secrets.GH_Packages }}' steps: - name: Step-01 Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Step-02 Lint Code Base @@ -39,7 +39,7 @@ jobs: versionSpec: 5.x - name: Step-02 Check out Code - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -67,7 +67,7 @@ jobs: working-directory: '${{ env.working-directory }}' - name: Step-08 Upload Build Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: build-artifact path: ${{env.working-directory}} @@ -88,7 +88,7 @@ jobs: versionSpec: 5.x - name: Step-02 Check out Code - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -117,7 +117,7 @@ jobs: working-directory: '${{ env.working-directory }}' - name: Step-08 Upload Build Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: build-artifact path: ${{env.working-directory}} @@ -136,7 +136,7 @@ jobs: working-directory: /home/runner/work/FileUtil.Core/FileUtil.Core steps: - name: Step-01 Retrieve Build Artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: build-artifact path: ${{env.working-directory}} diff --git a/.github/workflows/Master-Build.yml b/.github/workflows/Master-Build.yml index cb1f876..b7ff9a4 100644 --- a/.github/workflows/Master-Build.yml +++ b/.github/workflows/Master-Build.yml @@ -14,7 +14,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v3 with: @@ -32,7 +32,7 @@ jobs: github-token: '${{ secrets.GH_Packages }}' steps: - name: Step-01 Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Step-02 Lint Code Base diff --git a/.github/workflows/Master-CodeQL.yml b/.github/workflows/Master-CodeQL.yml index 4360e22..5d8c17f 100644 --- a/.github/workflows/Master-CodeQL.yml +++ b/.github/workflows/Master-CodeQL.yml @@ -7,65 +7,96 @@ # ******** NOTE ******** # We have attempted to detect the languages in your repository. Please check # the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# +# supported CodeQL languages. +# name: "Master-CodeQL" on: push: branches: [ "master" ] + paths-ignore: + - "**/*.md" + - "**/*.gitignore" + - "**/*.gitattributes" schedule: - - cron: '35 15 * * 2' + - cron: '42 7 * * 5' jobs: analyze: - name: Analyze - runs-on: ubuntu-latest + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories actions: read contents: read - security-events: write strategy: fail-fast: false matrix: - language: [ 'csharp' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - + include: + - language: actions + build-mode: none + - language: csharp + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: - category: "/language:${{matrix.language}}" \ No newline at end of file + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/PR-CodeQL.yml b/.github/workflows/PR-CodeQL.yml index c7511be..0b7d680 100644 --- a/.github/workflows/PR-CodeQL.yml +++ b/.github/workflows/PR-CodeQL.yml @@ -12,64 +12,92 @@ name: "PR-CodeQL" on: + push: pull_request: types: [opened, reopened, edited, synchronize] paths-ignore: - "**/*.md" - "**/*.gitignore" - - "**/*.gitattributes" + - "**/*.gitattributes" schedule: - cron: '35 15 * * 2' jobs: analyze: - name: Analyze - runs-on: ubuntu-latest + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories actions: read contents: read - security-events: write strategy: fail-fast: false matrix: - language: [ 'csharp' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - + include: + - language: actions + build-mode: none + - language: csharp + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" diff --git a/GitVersion.yml b/GitVersion.yml index 2ac57c8..94e320b 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,4 +1,4 @@ -next-version: 4.0.0 +next-version: 5.0.0 tag-prefix: '[vV]' mode: ContinuousDeployment branches: diff --git a/License.md b/License.md index a014359..df6574d 100644 --- a/License.md +++ b/License.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2024 Tech Ninja Labs +Copyright (c) 2025 Tech Ninja Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8344365..75b58cd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ninja FileUtil.Core v4.0.0 +# ninja FileUtil.Core v5.0.0 [![NuGet version](https://badge.fury.io/nu/FixedWidth.FileParser.svg)](https://badge.fury.io/nu/FixedWidth.FileParser) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/CodeShayk/FileUtil.Core/blob/master/LICENSE.md) [![Master-Build](https://github.com/CodeShayk/FileUtil.Core/actions/workflows/Master-Build.yml/badge.svg)](https://github.com/CodeShayk/FileUtil.Core/actions/workflows/Master-Build.yml) [![GitHub Release](https://img.shields.io/github/v/release/CodeShayk/FileUtil.Core?logo=github&sort=semver)](https://github.com/CodeShayk/FileUtil.Core/releases/latest) @@ -60,6 +60,7 @@ This project is licensed with the [MIT license](LICENSE). The main branch is now on .NET 9.0. The following previous versions are available: | Version | Release Notes | | -------- | --------| +| [`v5.0.0`](https://github.com/CodeShayk/FileUtil.Core/tree/v5.0.0) | [Notes](https://github.com/CodeShayk/FileUtil.Core/releases/tag/v5.0.0) | | [`v4.0.0`](https://github.com/CodeShayk/FileUtil.Core/tree/v4.0.0) | [Notes](https://github.com/CodeShayk/FileUtil.Core/releases/tag/v4.0.0) | | [`v3.0.0`](https://github.com/CodeShayk/FileUtil.Core/tree/v3.0.0) | [Notes](https://github.com/CodeShayk/FileUtil.Core/releases/tag/v3.0.0) | | [`v2.0.0`](https://github.com/CodeShayk/FileUtil.Core/tree/v2.0.0) | [Notes](https://github.com/CodeShayk/FileUtil.Core/releases/tag/v2.0.0) | diff --git a/src/FileUtil/FileUtil.csproj b/src/FileUtil/FileUtil.csproj index cac1ea7..33e2f15 100644 --- a/src/FileUtil/FileUtil.csproj +++ b/src/FileUtil/FileUtil.csproj @@ -15,9 +15,9 @@ Example: pipe delimited, csv, tsv, etc. Fixed Width File Parser https://github.com/CodeShayk/FileUtil.Core/wiki https://1drv.ms/u/s!Aq_ncig7TU4551b5fzxOad-pDMfL - 4.0.0 + 5.0.0 FixedWidth.FileParser - © Copyright 2024 Code Shayk. + © Copyright 2025 Code Shayk. ninja-icon-16.png README.md License.md From 5675bea70c98115cd5c91fcaaeb9139f35e08f8f Mon Sep 17 00:00:00 2001 From: Ninja Date: Tue, 13 May 2025 23:05:33 +0100 Subject: [PATCH 3/3] - Add Project Properties --- src/FileUtil/FileUtil.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/FileUtil/FileUtil.csproj b/src/FileUtil/FileUtil.csproj index 33e2f15..a507195 100644 --- a/src/FileUtil/FileUtil.csproj +++ b/src/FileUtil/FileUtil.csproj @@ -23,10 +23,15 @@ Example: pipe delimited, csv, tsv, etc. License.md True True + True + - Use Parsley.Net for parsing of files. True + + True + True