Nuke.Cola
Loading...
Searching...
No Matches
LicenseRegion.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text.RegularExpressions;
5using System.Threading.Tasks;
6using GlobExpressions;
8using Nuke.Common;
9using Nuke.Common.IO;
10using Nuke.Common.Utilities;
11using Nuke.Common.Utilities.Collections;
12using Scriban;
13
14namespace Nuke.Cola;
15
16public record LicenseCommentData(string License, string Author, int Year);
17
19{
20 string LeadingCommentTemplate { get; }
21 string[] FileFilters { get; }
22 string RemoveExistingComment(string fileContent);
23 string TransformLicenseText(string license);
24};
25
27{
28 public string LeadingCommentTemplate =>
29 """
30 /** @noop License Comment
31 * @file
32 * @copyright
33 {{ license }}
34 *
35 * @author {{ author }}
36 * @date {{ year }}
37 */
38 """;
39 public abstract string[] FileFilters { get; }
40 public string RemoveExistingComment(string fileContent)
41 {
42 return fileContent.SplitLineBreaks()
43 .SkipWhile(l => l.StartsWithAnyOrdinalIgnoreCase(
44 "/** @noop License Comment",
45 " * ",
46 " */"
47 ))
48 .JoinNewLine();
49 }
50
51 public string TransformLicenseText(string license)
52 {
53 return license.SplitLineBreaks()
54 .Select(l => string.IsNullOrWhiteSpace(l)
55 ? " * @copyright"
56 : " * " + l
57 )
58 .JoinNewLine();
59 }
60}
61
63{
64 public override string[] FileFilters => [ "*.h", "*.cpp", "*.cxx", "*.hpp", "*.cppm", "*.ixx" ];
65}
66
68{
69 public override string[] FileFilters => [ "*.cs" ];
70}
71
72public class LicenseRegion
73{
74 private Dictionary<Type, ILicenseCommentTemplate> DefaultCommentTemplates = new()
75 {
78 };
79
80 public LicenseRegion WithCommentTemplate<T>(T template) where T : ILicenseCommentTemplate
81 {
82 DefaultCommentTemplates[typeof(T)] = template;
83 return this;
84 }
85
86 public IEnumerable<ILicenseCommentTemplate> Templates => DefaultCommentTemplates.Values;
87
88 public Func<AbsolutePath, bool>? AllowDirectory { get; set; }
89 public Func<AbsolutePath, bool>? AllowFile { get; set; }
90
91 public string LicenseRegionFile { get; set; } = "*LicenseRegion*";
92 public bool AllowDotFiles { get; set; } = false;
93 public bool AllowDotDirectories { get; set; } = false;
94}
95
96public static class LicenseRegionStatic
97{
98 public static void ProcessLicenseRegion(this INukeBuild self, AbsolutePath root, LicenseCommentData licenseData, LicenseRegion? options = null)
99 {
100 options ??= new LicenseRegion();
101 var fileFilters = options.Templates.SelectMany(t => t.FileFilters).ToArray();
102 var files = root.GlobFiles(fileFilters)
103 .Where(f => options.AllowFile?.Invoke(f) ?? true)
104 .Where(f => options.AllowDotFiles || !f.Name.StartsWith('.'))
105 .Where(f => !Glob.IsMatch(f, options.LicenseRegionFile, GlobOptions.CaseInsensitive));
106
107 foreach (var file in files)
108 {
109 var template = options.Templates.First(t => t.FileFilters.Any(f => Glob.IsMatch(file, f, GlobOptions.CaseInsensitive)));
110 var fileText = template.RemoveExistingComment(file.ReadAllText());
111 var license = template.TransformLicenseText(licenseData.License);
112 var commentTemplate = Template.Parse(template.LeadingCommentTemplate);
113 var commentText = commentTemplate.Render(licenseData with {License = license});
114 file.WriteAllText(commentText + Environment.NewLine + fileText);
115 }
116
117 root.GetDirectories()
118 .Where(d => options.AllowDirectory?.Invoke(d) ?? true)
119 .Where(d => options.AllowDotDirectories || !d.Name.StartsWith('.'))
120 .Where(d => d.GlobFiles(options.LicenseRegionFile).IsEmpty())
121 .ForEach(d => self.ProcessLicenseRegion(d, licenseData, options));
122 }
123}