1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
/***************************************************************************************************
Copyright (C) 2025 The Qt Company Ltd.
SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
***************************************************************************************************/
global using Files = Qt.DotNet.CodeGeneration.FilePlaceholder.All;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
namespace Qt.DotNet.CodeGeneration
{
using Utils.Collections.Concurrent;
public class FilePlaceholder : Placeholder
{
public Encoding Encoding { get; set; } = Encoding.UTF8;
public bool NewLineEof { get; set; } = true;
public bool ForceWrite { get; set; } = false;
public bool ByteOrderMark { get; set; } = false;
public string IndentChars { get; set; } = " ";
public FileInfo Target { get; private set; }
public FilePlaceholder(string id, MemberInfo src, string path) : base(id, src)
{
Indent = 0;
Sorted = false;
Target = new FileInfo(Path.Combine(Rules.TargetDir.FullName, path));
Instances.Add(this);
AddToIndex();
}
public FilePlaceholder(Enum id, MemberInfo src, string path) : this(IdName(id), src, path)
{ }
public async Task<bool?> WriteAsync(IFileSink sink, CancellationToken cancelToken = default)
{
#if DEBUG
ArgumentNullException.ThrowIfNull(sink);
#endif
if (Target == null)
return null;
var text = await RenderAsync().WaitAsync(cancelToken).ConfigureAwait(false);
text = (ByteOrderMark ? "\uFEFF" : "") + text
.Replace($"{Nul}", "")
.Replace($"{Tab}", IndentChars);
text = Regex.Replace(text, $@"[ ]*{BkSpc}", "");
text = Regex.Replace(text, @"(?<=\n)[ \t]*\r?\n", "")
.Replace($"{Blank}", "\r\n")
.TrimEnd('\r', '\n', ' ')
+ (NewLineEof ? "\r\n" : "");
return await sink.WriteAsync(Target, text, Encoding, ForceWrite, cancelToken)
.ConfigureAwait(false);
}
private static ConcurrentSet<FilePlaceholder> Instances { get; } = new();
internal static class All
{
public static async Task<(FileInfo File, bool? Updated)[]> WriteAllAsync(IFileSink sink,
CancellationToken cancellationToken = default)
{
#if DEBUG
ArgumentNullException.ThrowIfNull(sink);
#endif
var filePlaceholders = Instances.ToArray(); // snapshot
var results = new (FileInfo File, bool? Updated)[filePlaceholders.Length];
await Task.WhenAll(Enumerable.Range(0, filePlaceholders.Length).Select(async i =>
{
var placeholder = filePlaceholders[i];
results[i] = (placeholder.Target, await placeholder
.WriteAsync(sink, cancellationToken).ConfigureAwait(false));
})).ConfigureAwait(false);
return results;
}
public static void Reset() => Instances.Clear();
}
public static FilePlaceholder operator +(FilePlaceholder self, string text)
{
return (FilePlaceholder)((Placeholder)self + text);
}
public static FilePlaceholder operator +(FilePlaceholder self, Placeholder placeholder)
{
return (FilePlaceholder)((Placeholder)self + placeholder);
}
}
}
|