Skip to content

Commit d6398d3

Browse files
committed
add rootnamespace option
1 parent 1143c29 commit d6398d3

11 files changed

+107
-378
lines changed
Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,6 @@
1-
using System.Diagnostics.CodeAnalysis;
2-
31
namespace AssemblyMetadata.Generators;
42

5-
[ExcludeFromCodeCoverage]
6-
public class AssemblyConstant : IEquatable<AssemblyConstant>
7-
{
8-
public AssemblyConstant(string name, string value)
9-
{
10-
Name = name;
11-
Value = value;
12-
}
13-
14-
public string Name { get; }
15-
16-
public string Value { get; }
17-
18-
public bool Equals(AssemblyConstant other)
19-
{
20-
if (ReferenceEquals(null, other))
21-
return false;
22-
23-
if (ReferenceEquals(this, other))
24-
return true;
25-
26-
return Name == other.Name
27-
&& Value == other.Value;
28-
}
29-
30-
public override bool Equals(object value) => value is AssemblyConstant assemblyContant && Equals(assemblyContant);
31-
32-
public override int GetHashCode() => HashCode.Seed.Combine(Name).Combine(Value);
33-
34-
public static bool operator ==(AssemblyConstant left, AssemblyConstant right) => Equals(left, right);
35-
36-
public static bool operator !=(AssemblyConstant left, AssemblyConstant right) => !Equals(left, right);
37-
38-
public override string ToString() => $"Name: {Name}; Value: {Value}";
39-
}
3+
public record AssemblyConstant(
4+
string Name,
5+
string Value
6+
);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<Project>
22
<ItemGroup>
3+
<CompilerVisibleProperty Include="AssemblyName" />
4+
<CompilerVisibleProperty Include="DefineConstants" />
5+
<CompilerVisibleProperty Include="RootNamespace" />
36
<CompilerVisibleProperty Include="ThisAssemblyNamespace" />
47
</ItemGroup>
58
</Project>

src/AssemblyMetadata.Generators/AssemblyMetadataGenerator.cs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,24 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
5959
var assemblyName = context.CompilationProvider
6060
.Select(static (c, _) => c.AssemblyName);
6161

62-
var thisNamespace = context.AnalyzerConfigOptionsProvider
62+
var globalOptions = context.AnalyzerConfigOptionsProvider
6363
.Select(static (c, _) =>
6464
{
65-
c.GlobalOptions.TryGetValue("build_property.ThisAssemblyNamespace", out var methodName);
66-
return methodName;
65+
c.GlobalOptions.TryGetValue("build_property.AssemblyName", out var assemblyName);
66+
c.GlobalOptions.TryGetValue("build_property.DefineConstants", out var defineConstants);
67+
c.GlobalOptions.TryGetValue("build_property.RootNamespace", out var rootNamespace);
68+
c.GlobalOptions.TryGetValue("build_property.ThisAssemblyNamespace", out var thisNamespace);
69+
70+
var globalOptions = new GlobalOptions(
71+
AssemblyName: assemblyName,
72+
DefineConstants: defineConstants,
73+
RootNamespace: rootNamespace,
74+
ThisAssemblyNamespace: thisNamespace);
75+
76+
return globalOptions;
6777
});
6878

69-
var options = assemblyName.Combine(thisNamespace);
79+
var options = assemblyName.Combine(globalOptions);
7080

7181
context.RegisterSourceOutput(constants.Combine(options), GenerateOutput);
7282
}
@@ -127,7 +137,7 @@ private static GeneratorContext SemanticTransform(GeneratorAttributeSyntaxContex
127137
}
128138
}
129139

130-
return new GeneratorContext(Enumerable.Empty<Diagnostic>(), constants);
140+
return new GeneratorContext([], constants);
131141
}
132142

133143
private static void ReportDiagnostic(SourceProductionContext context, EquatableArray<Diagnostic> diagnostics)
@@ -136,9 +146,32 @@ private static void ReportDiagnostic(SourceProductionContext context, EquatableA
136146
context.ReportDiagnostic(diagnostic);
137147
}
138148

139-
private void GenerateOutput(SourceProductionContext context, (EquatableArray<AssemblyConstant> constants, (string? assemblyName, string? thisNamespace) options) parameters)
149+
private void GenerateOutput(SourceProductionContext context, (EquatableArray<AssemblyConstant> constants, (string? assemblyName, GlobalOptions globalOptions) options) parameters)
140150
{
141-
var source = AssemblyMetadataWriter.Generate(parameters.constants, parameters.options.assemblyName, parameters.options.thisNamespace);
151+
152+
var constants = new List<AssemblyConstant>(parameters.constants);
153+
154+
if (!constants.Any(p => p.Name == nameof(GlobalOptions.AssemblyName)))
155+
{
156+
var assemblyName = parameters.options.globalOptions.AssemblyName ?? parameters.options.assemblyName ?? string.Empty;
157+
constants.Add(new AssemblyConstant(nameof(GlobalOptions.AssemblyName), $"\"{assemblyName}\""));
158+
}
159+
160+
if (!constants.Any(p => p.Name == nameof(GlobalOptions.DefineConstants)))
161+
{
162+
var defineConstants = parameters.options.globalOptions.DefineConstants;
163+
if (!string.IsNullOrEmpty(defineConstants))
164+
constants.Add(new AssemblyConstant(nameof(GlobalOptions.DefineConstants), $"\"{defineConstants}\""!));
165+
}
166+
167+
if (!constants.Any(p => p.Name == nameof(GlobalOptions.RootNamespace)))
168+
{
169+
var rootNamespace = parameters.options.globalOptions.RootNamespace;
170+
if (!string.IsNullOrEmpty(rootNamespace))
171+
constants.Add(new AssemblyConstant(nameof(GlobalOptions.RootNamespace), $"\"{rootNamespace}\""!));
172+
}
173+
174+
var source = AssemblyMetadataWriter.Generate(constants, parameters.options.globalOptions.ThisAssemblyNamespace);
142175

143176
context.AddSource("AssemblyMetadata.g.cs", source);
144177
}

src/AssemblyMetadata.Generators/AssemblyMetadataWriter.cs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ public static class AssemblyMetadataWriter
1111
return attribute?.InformationalVersion ?? "1.0.0.0";
1212
});
1313

14-
public static string Generate(EquatableArray<AssemblyConstant> constants, string? assemblyName = null, string? thisNamespace = null)
14+
public static string Generate(IEnumerable<AssemblyConstant> constants, string? thisNamespace = null)
1515
{
16-
if (constants == null)
16+
if (constants is null)
1717
throw new ArgumentNullException(nameof(constants));
1818

1919
var codeBuilder = new IndentedStringBuilder();
@@ -48,15 +48,6 @@ public static string Generate(EquatableArray<AssemblyConstant> constants, string
4848
.IncrementIndent()
4949
.AppendLine();
5050

51-
if (!string.IsNullOrEmpty(assemblyName))
52-
{
53-
codeBuilder
54-
.Append("public const string AssemblyName = \"")
55-
.Append(assemblyName)
56-
.AppendLine("\";")
57-
.AppendLine();
58-
}
59-
6051
foreach (var constant in constants)
6152
{
6253
var name = SafeName(constant.Name);

src/AssemblyMetadata.Generators/EquatableArray.cs

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,68 +4,61 @@
44
namespace AssemblyMetadata.Generators;
55

66
[ExcludeFromCodeCoverage]
7-
public readonly struct EquatableArray<T> : IReadOnlyCollection<T>, IEquatable<EquatableArray<T>>
7+
public readonly struct EquatableArray<T> : IEquatable<EquatableArray<T>>, IEnumerable<T>
88
where T : IEquatable<T>
99
{
10-
public static readonly EquatableArray<T> Empty = new(Array.Empty<T>());
10+
public static readonly EquatableArray<T> Empty = new();
1111

12-
private readonly T[] _array;
1312

14-
public EquatableArray(T[] array)
15-
{
16-
_array = array;
17-
}
13+
public EquatableArray() : this([]) { }
1814

19-
public EquatableArray(IEnumerable<T>? array)
20-
{
21-
array ??= Enumerable.Empty<T>();
22-
_array = array.ToArray();
23-
}
15+
public EquatableArray(T[] array) => Array = array ?? [];
16+
17+
public EquatableArray(IEnumerable<T> items) => Array = items.ToArray() ?? [];
2418

25-
public bool Equals(EquatableArray<T> array)
26-
{
27-
return AsSpan().SequenceEqual(array.AsSpan());
28-
}
2919

30-
public override bool Equals(object obj)
20+
public T[] Array { get; }
21+
22+
public int Count => Array.Length;
23+
24+
25+
public ReadOnlySpan<T> AsSpan() => Array.AsSpan();
26+
27+
public T[] AsArray() => Array;
28+
29+
public T this[int i]
3130
{
32-
return obj is EquatableArray<T> array && Equals(this, array);
31+
get => Array[i];
3332
}
3433

34+
public static bool operator ==(EquatableArray<T> left, EquatableArray<T> right) => left.Equals(right);
35+
36+
public static bool operator !=(EquatableArray<T> left, EquatableArray<T> right) => !left.Equals(right);
37+
38+
public bool Equals(EquatableArray<T> array) => Array.AsSpan().SequenceEqual(array.AsSpan());
39+
40+
public override bool Equals(object? obj) => obj is EquatableArray<T> array && Equals(this, array);
41+
3542
public override int GetHashCode()
3643
{
37-
if (_array is null)
44+
if (Array is not T[] array)
3845
return 0;
3946

40-
return HashCode.Seed.CombineAll(_array);
41-
}
47+
var hashCode = 16777619;
4248

43-
public ReadOnlySpan<T> AsSpan()
44-
{
45-
return _array.AsSpan();
46-
}
49+
for (int i = 0; i < array.Length; i++)
50+
hashCode = unchecked((hashCode * -1521134295) + EqualityComparer<T>.Default.GetHashCode(array[i]));
4751

48-
IEnumerator<T> IEnumerable<T>.GetEnumerator()
49-
{
50-
IEnumerable<T> array = _array ?? Array.Empty<T>();
51-
return array.GetEnumerator();
52+
return hashCode;
5253
}
5354

54-
IEnumerator IEnumerable.GetEnumerator()
55-
{
56-
IEnumerable<T> array = _array ?? Array.Empty<T>();
57-
return array.GetEnumerator();
58-
}
5955

60-
public int Count => _array?.Length ?? 0;
56+
IEnumerator<T> IEnumerable<T>.GetEnumerator() => (Array as IEnumerable<T>).GetEnumerator();
6157

62-
public static bool operator ==(EquatableArray<T> left, EquatableArray<T> right)
63-
{
64-
return left.Equals(right);
65-
}
58+
IEnumerator IEnumerable.GetEnumerator() => Array.GetEnumerator();
6659

67-
public static bool operator !=(EquatableArray<T> left, EquatableArray<T> right)
68-
{
69-
return !left.Equals(right);
70-
}
60+
61+
public static implicit operator EquatableArray<T>(T[] array) => new(array);
62+
63+
public static implicit operator EquatableArray<T>(List<T> items) => new(items);
7164
}
Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,8 @@
1-
using System.Diagnostics.CodeAnalysis;
2-
31
using Microsoft.CodeAnalysis;
42

53
namespace AssemblyMetadata.Generators;
64

7-
[ExcludeFromCodeCoverage]
8-
public class GeneratorContext : IEquatable<GeneratorContext>
9-
{
10-
public GeneratorContext(IEnumerable<Diagnostic> diagnostics, IEnumerable<AssemblyConstant> constants)
11-
{
12-
Diagnostics = new EquatableArray<Diagnostic>(diagnostics);
13-
Constants = new EquatableArray<AssemblyConstant>(constants);
14-
}
15-
16-
public EquatableArray<Diagnostic> Diagnostics { get; }
17-
18-
public EquatableArray<AssemblyConstant> Constants { get; }
19-
20-
public bool Equals(GeneratorContext other)
21-
{
22-
if (ReferenceEquals(null, other))
23-
return false;
24-
25-
if (ReferenceEquals(this, other))
26-
return true;
27-
28-
return Diagnostics.Equals(other.Diagnostics)
29-
&& Constants.Equals(other.Constants);
30-
}
31-
32-
public override bool Equals(object value) => value is GeneratorContext context && Equals(context);
33-
34-
public override int GetHashCode() => HashCode.Seed.CombineAll(Diagnostics).CombineAll(Constants);
35-
36-
public static bool operator ==(GeneratorContext left, GeneratorContext right) => Equals(left, right);
37-
38-
public static bool operator !=(GeneratorContext left, GeneratorContext right) => !Equals(left, right);
39-
}
5+
public record GeneratorContext(
6+
EquatableArray<Diagnostic> Diagnostics,
7+
EquatableArray<AssemblyConstant> Constants
8+
);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace AssemblyMetadata.Generators;
2+
3+
public record GlobalOptions(
4+
string? AssemblyName,
5+
string? DefineConstants,
6+
string? RootNamespace,
7+
string? ThisAssemblyNamespace
8+
);

0 commit comments

Comments
 (0)