Skip to content

Commit 032f1e4

Browse files
author
andreas.hoffmann
committed
Added MaybeNullAttribute and fixed tests with the correct check. Changes to Compiler.cs are not necessary anymore.
1 parent aa97eaf commit 032f1e4

3 files changed

Lines changed: 37 additions & 59 deletions

File tree

XmlSchemaClassGenerator.Tests/Compiler.cs

Lines changed: 18 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static CompilationResult GenerateAssembly(Compilation compilation)
3333
};
3434
}
3535

36-
private static readonly ConcurrentDictionary<string, Tuple<List<SyntaxTree>, Assembly>> Assemblies = new();
36+
private static readonly ConcurrentDictionary<string, Assembly> Assemblies = new();
3737

3838
private static readonly string[] DependencyAssemblies = new[]
3939
{
@@ -55,33 +55,21 @@ public static CompilationResult GenerateAssembly(Compilation compilation)
5555
public static Assembly GetAssembly(string name)
5656
{
5757
Assemblies.TryGetValue(name, out var assembly);
58-
return assembly.Item2;
59-
}
60-
61-
public static Assembly Generate(string name, string pattern, Generator generatorPrototype = null)
62-
{
63-
(_, var assembly) = GenerateVerbose(name, pattern, generatorPrototype);
64-
return assembly;
58+
return assembly;
6559
}
6660

67-
public static (List<SyntaxTree>, Assembly) GenerateVerbose(string name, string pattern, Generator generatorPrototype = null)
68-
{
69-
if (Assemblies.TryGetValue(name, out var assembly)) { return (assembly.Item1, assembly.Item2); }
61+
public static Assembly Generate(string name, string pattern, Generator generatorPrototype = null)
62+
{
63+
if (Assemblies.ContainsKey(name)) { return Assemblies[name]; }
7064

7165
var files = Glob.ExpandNames(pattern).OrderByDescending(f => f);
7266

73-
return GenerateFilesVerbose(name, files, generatorPrototype);
67+
return GenerateFiles(name, files, generatorPrototype);
7468
}
7569

76-
public static Assembly GenerateFiles(string name, IEnumerable<string> files, Generator generatorPrototype = null)
77-
{
78-
(_, var assembly) = GenerateFilesVerbose(name, files, generatorPrototype);
79-
return assembly;
80-
}
81-
82-
public static (List<SyntaxTree>, Assembly) GenerateFilesVerbose(string name, IEnumerable<string> files, Generator generatorPrototype = null)
83-
{
84-
if (Assemblies.TryGetValue(name, out var assembly)) { return (assembly.Item1, assembly.Item2); }
70+
public static Assembly GenerateFiles(string name, IEnumerable<string> files, Generator generatorPrototype = null)
71+
{
72+
if (Assemblies.ContainsKey(name)) { return Assemblies[name]; }
8573

8674
generatorPrototype ??= new Generator
8775
{
@@ -125,6 +113,7 @@ public static (List<SyntaxTree>, Assembly) GenerateFilesVerbose(string name, IEn
125113
UniqueTypeNamesAcrossNamespaces = generatorPrototype.UniqueTypeNamesAcrossNamespaces,
126114
CreateGeneratedCodeAttributeVersion = generatorPrototype.CreateGeneratedCodeAttributeVersion,
127115
NetCoreSpecificCode = generatorPrototype.NetCoreSpecificCode,
116+
EnableNullableReferenceAttributes = generatorPrototype.EnableNullableReferenceAttributes,
128117
NamingScheme = generatorPrototype.NamingScheme
129118
};
130119

@@ -135,40 +124,28 @@ public static (List<SyntaxTree>, Assembly) GenerateFilesVerbose(string name, IEn
135124

136125
gen.Generate(files);
137126

138-
return CompileFilesVerbose(name, output.Files);
127+
return CompileFiles(name, output.Files);
139128
}
140129

141-
public static Assembly CompileFiles(string name, IEnumerable<string> files)
142-
{
143-
(_, var assembly) = CompileFilesVerbose(name, files);
144-
return assembly;
145-
}
146-
147-
public static (List<SyntaxTree>, Assembly) CompileFilesVerbose(string name, IEnumerable<string> files)
148-
{
149-
return CompileVerbose(name, files.Select(f => File.ReadAllText(f)).ToArray());
130+
public static Assembly CompileFiles(string name, IEnumerable<string> files)
131+
{
132+
return Compile(name, files.Select(f => File.ReadAllText(f)).ToArray());
150133
}
151134

152135
private static readonly LanguageVersion MaxLanguageVersion = Enum
153136
.GetValues(typeof(LanguageVersion))
154137
.Cast<LanguageVersion>()
155138
.Max();
156139

157-
public static Assembly Compile(string name, params string[] contents)
140+
public static Assembly Compile(string name, params string[] contents)
158141
{
159-
(_, var assembly) = CompileVerbose(name, contents);
160-
return assembly;
161-
}
162-
163-
public static (List<SyntaxTree>, Assembly) CompileVerbose(string name, params string[] contents)
164-
{
165142
var trustedAssembliesPaths = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")).Split(Path.PathSeparator);
166143
var references = trustedAssembliesPaths
167144
.Where(p => DependencyAssemblies.Contains(Path.GetFileNameWithoutExtension(p)))
168145
.Select(p => MetadataReference.CreateFromFile(p))
169146
.ToList();
170147
var options = new CSharpParseOptions(kind: SourceCodeKind.Regular, languageVersion: MaxLanguageVersion);
171-
var syntaxTrees = contents.Select(c => CSharpSyntaxTree.ParseText(c, options)).ToList();
148+
var syntaxTrees = contents.Select(c => CSharpSyntaxTree.ParseText(c, options));
172149
var compilation = CSharpCompilation.Create(name, syntaxTrees)
173150
.AddReferences(references)
174151
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
@@ -179,9 +156,9 @@ public static (List<SyntaxTree>, Assembly) CompileVerbose(string name, params st
179156
Assert.True(result.Result.Success);
180157
Assert.NotNull(result.Assembly);
181158

182-
Assemblies[name] = Tuple.Create(syntaxTrees, result.Assembly);
159+
Assemblies[name] = result.Assembly;
183160

184-
return (syntaxTrees, result.Assembly);
161+
return result.Assembly;
185162
}
186163
}
187164
}

XmlSchemaClassGenerator.Tests/XmlTests.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.CodeDom;
33
using System.Collections.Generic;
44
using System.Collections.ObjectModel;
5+
using System.Diagnostics.CodeAnalysis;
56
using System.IO;
67
using System.Linq;
78
using System.Reflection;
@@ -2382,27 +2383,26 @@ public void TestNullableReferenceAttributes()
23822383
GenerateNamespace = key => "Test"
23832384
}
23842385
};
2385-
//Unfortunately, I did not find access to the Attribute "AllowNull" in the generated Assembly.
2386-
//It is just not accessible via "CustomAttributes".
2387-
//So I have to parse the Syntax-Tree to find it.
2388-
(var syntaxTrees, _) = Compiler.GenerateVerbose(nameof(TestNullableReferenceAttributes), NullableReferenceAttributesPattern, generator);
2386+
var assembly = Compiler.Generate(nameof(TestNullableReferenceAttributes), NullableReferenceAttributesPattern, generator);
23892387
void assertNullable(string typename, bool nullable)
23902388
{
2391-
var root = (CompilationUnitSyntax)syntaxTrees.Single().GetRoot();
2392-
var ns = (NamespaceDeclarationSyntax)root.Members.Single();
2393-
var c1 = (ClassDeclarationSyntax)ns.Members.Single(
2394-
m => m is ClassDeclarationSyntax c && c.Identifier.ToString() == typename
2395-
);
2396-
var p = (PropertyDeclarationSyntax)c1.Members.Single(m => m is PropertyDeclarationSyntax n && n.Identifier.ToString() == "Text");
2397-
var hasAllowNullAttribute = p.AttributeLists.Any(d => d.Attributes.Any(a => a.GetText().ToString() == "System.Diagnostics.CodeAnalysis.AllowNullAttribute()"));
2389+
Type c = assembly.GetType(typename);
2390+
var property = c.GetProperty("Text");
2391+
var setParameter = property.SetMethod.GetParameters();
2392+
var getReturnParameter = property.GetMethod.ReturnParameter;
2393+
var allowNullableAttribute = setParameter.Single().CustomAttributes.SingleOrDefault(a => a.AttributeType == typeof(AllowNullAttribute));
2394+
var maybeNullAttribute = getReturnParameter.CustomAttributes.SingleOrDefault(a => a.AttributeType == typeof(MaybeNullAttribute));
2395+
var hasAllowNullAttribute = allowNullableAttribute != null;
2396+
var hasMaybeNullAttribute = maybeNullAttribute != null;
23982397
Assert.Equal(nullable, hasAllowNullAttribute);
2398+
Assert.Equal(nullable, hasMaybeNullAttribute);
23992399
}
2400-
assertNullable("ElementReferenceNullable", true);
2401-
assertNullable("ElementReferenceList", true);
2402-
assertNullable("ElementReferenceNonNullable", false);
2403-
assertNullable("AttributeReferenceNullable", true);
2404-
assertNullable("AttributeReferenceNonNullable", false);
2405-
assertNullable("AttributeValueNullableInt", false);
2400+
assertNullable("Test.ElementReferenceNullable", true);
2401+
assertNullable("Test.ElementReferenceList", true);
2402+
assertNullable("Test.ElementReferenceNonNullable", false);
2403+
assertNullable("Test.AttributeReferenceNullable", true);
2404+
assertNullable("Test.AttributeReferenceNonNullable", false);
2405+
assertNullable("Test.AttributeValueNullableInt", false);
24062406
}
24072407

24082408
[Fact, TestPriority(1)]

XmlSchemaClassGenerator/TypeModel.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,8 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
11271127
if (isNullableReferenceType && Configuration.EnableNullableReferenceAttributes)
11281128
{
11291129
member.CustomAttributes.Add(new CodeAttributeDeclaration("System.Diagnostics.CodeAnalysis.AllowNullAttribute"));
1130-
}
1130+
member.CustomAttributes.Add(new CodeAttributeDeclaration("System.Diagnostics.CodeAnalysis.MaybeNullAttribute"));
1131+
}
11311132

11321133
var attributes = GetAttributes(isArray).ToArray();
11331134
member.CustomAttributes.AddRange(attributes);

0 commit comments

Comments
 (0)