Skip to content

Commit 6ecbdf1

Browse files
committed
Merge branch 'main' into issue-1903
2 parents c5523f0 + 47c920c commit 6ecbdf1

File tree

337 files changed

+145944
-77093
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

337 files changed

+145944
-77093
lines changed

CONTRIBUTING.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
# Contributing
22

3-
This project has adopted the [Microsoft Open Source Code of
4-
Conduct](https://opensource.microsoft.com/codeofconduct/).
5-
For more information see the [Code of Conduct
6-
FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
7-
8-
with any additional questions or comments.
3+
This project has adopted the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/about/policies/code-of-conduct).
94

105
For our general contributing guidelines please see [our dotnet/runtime contributing guide](https://github.com/dotnet/runtime/blob/master/CONTRIBUTING.md).
116

@@ -25,4 +20,4 @@ This repository can be built on Windows, Linux, and OSX.
2520

2621
Building, testing, and packing this repository can be done by using the standard dotnet CLI commands (e.g. `dotnet build`, `dotnet test`, `dotnet pack`, etc.).
2722

28-
[VisualStudio]: https://docs.microsoft.com/dotnet/core/install/sdk?pivots=os-windows#install-with-visual-studio
23+
[VisualStudio]: https://docs.microsoft.com/dotnet/core/install/sdk?pivots=os-windows#install-with-visual-studio

Directory.Packages.props

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
55
<PackageVersion Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.14.0" />
66
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
7+
<PackageVersion Include="Microsoft.Bcl.Memory" Version="9.0.4" />
78
<PackageVersion Include="Microsoft.DotNet.BuildTools.GenAPI" Version="3.0.0-preview4-06015-01" />
89
<PackageVersion Include="Microsoft.CodeAnalysis" Version="4.11.0" />
910
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
1011
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
1112
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing" Version="1.1.2" />
1213
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.11.0-beta1.24219.2" />
13-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
14+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
1415
<PackageVersion Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" />
1516
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
1617
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="17.13.1" />

Open-XML-SDK.sln

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentFormat.OpenXml.Fram
8383
EndProject
8484
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThreadedCommentExample", "samples\ThreadedCommentExample\ThreadedCommentExample.csproj", "{5241BCF2-331D-428E-A9C4-F8DF92C8F726}"
8585
EndProject
86-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerPointModernCommentSample", "samples\PowerPointModernCommentSample\PowerPointModernCommentSample.csproj", "{3ECC7570-3501-479D-9CD9-64799C2AD149}"
87-
EndProject
8886
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SVGExample", "samples\SVGExample\SVGExample.csproj", "{BADAC0CC-F3E6-440E-B322-DA2B97625F26}"
8987
EndProject
9088
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RichData", "samples\RichData\RichData.csproj", "{8EE9F34E-EAA1-4F03-B388-8076CE44DD7B}"
@@ -175,10 +173,6 @@ Global
175173
{5241BCF2-331D-428E-A9C4-F8DF92C8F726}.Debug|Any CPU.Build.0 = Debug|Any CPU
176174
{5241BCF2-331D-428E-A9C4-F8DF92C8F726}.Release|Any CPU.ActiveCfg = Release|Any CPU
177175
{5241BCF2-331D-428E-A9C4-F8DF92C8F726}.Release|Any CPU.Build.0 = Release|Any CPU
178-
{3ECC7570-3501-479D-9CD9-64799C2AD149}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
179-
{3ECC7570-3501-479D-9CD9-64799C2AD149}.Debug|Any CPU.Build.0 = Debug|Any CPU
180-
{3ECC7570-3501-479D-9CD9-64799C2AD149}.Release|Any CPU.ActiveCfg = Release|Any CPU
181-
{3ECC7570-3501-479D-9CD9-64799C2AD149}.Release|Any CPU.Build.0 = Release|Any CPU
182176
{BADAC0CC-F3E6-440E-B322-DA2B97625F26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
183177
{BADAC0CC-F3E6-440E-B322-DA2B97625F26}.Debug|Any CPU.Build.0 = Debug|Any CPU
184178
{BADAC0CC-F3E6-440E-B322-DA2B97625F26}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -213,7 +207,6 @@ Global
213207
{C91489AB-FF14-4FAD-BA51-35371ADD7E1C} = {3653266D-2C88-4487-8977-839CB3E78A0A}
214208
{BB5DF535-E849-42AC-852A-A6D4815347C0} = {A4DF60EB-3AA5-48F0-B4D2-3F94B8E62F03}
215209
{5241BCF2-331D-428E-A9C4-F8DF92C8F726} = {7DAF7304-40CC-4180-88A5-9A89DD13C565}
216-
{3ECC7570-3501-479D-9CD9-64799C2AD149} = {7DAF7304-40CC-4180-88A5-9A89DD13C565}
217210
{BADAC0CC-F3E6-440E-B322-DA2B97625F26} = {7DAF7304-40CC-4180-88A5-9A89DD13C565}
218211
{8EE9F34E-EAA1-4F03-B388-8076CE44DD7B} = {7DAF7304-40CC-4180-88A5-9A89DD13C565}
219212
EndGlobalSection

gen/DocumentFormat.OpenXml.Generator.Models/Editor/TextWriterExtensions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ public static void WriteItem<T>(this TextWriter writer, T item, bool isConstant
128128
{
129129
writer.WriteString(item.ToString());
130130
}
131+
else if (typeof(T) == typeof(TypedQName))
132+
{
133+
writer.WriteString(item.ToString());
134+
}
131135
else if (typeof(T) == typeof(string))
132136
{
133137
writer.WriteString((string)(object)item, isConstant);

gen/DocumentFormat.OpenXml.Generator.Models/Generators/Elements/DataModelWriterExtensions.cs

Lines changed: 212 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,120 @@
55
using DocumentFormat.OpenXml.Generator.Models;
66
using DocumentFormat.OpenXml.Generator.Schematron;
77
using System.CodeDom.Compiler;
8+
using System.Runtime.CompilerServices;
89
using System.Text;
10+
using System.Xml.Linq;
911

1012
namespace DocumentFormat.OpenXml.Generator.Generators.Elements;
1113

1214
public static class DataModelWriterExtensions
1315
{
16+
public static class AttributeStrings
17+
{
18+
public const string ObsoletePropertyWarn = "[Obsolete(\"Unused property, will be removed in a future version.\", false)]";
19+
public const string ObsoletePropertyError = "[Obsolete(\"Unused property, will be removed in a future version.\", true)]";
20+
public const string ObsoleteAttributeWarn = "[Obsolete(\"Unused attribute, will be removed in a future version.\", false)]";
21+
public const string ObsoleteAttributeError = "[Obsolete(\"Unused attribute, will be removed in a future version.\", true)]";
22+
public const string EditorBrowsableAlways = "[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Always)] ";
23+
public const string EditorBrowsableAdvanced = "[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)] ";
24+
public const string EditorBrowsableNever = "[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] ";
25+
}
26+
27+
private static readonly List<string> ObsoletePropertyWarnList =
28+
[
29+
AttributeStrings.ObsoletePropertyWarn,
30+
AttributeStrings.EditorBrowsableNever,
31+
];
32+
33+
// Use this dictionary to add attributes like ObsoleteAttribute or other directives to classes, child elements or attributes.
34+
private static readonly Dictionary<TypedQName, Dictionary<TypedQName, List<string>>> _attributeData =
35+
new Dictionary<TypedQName, Dictionary<TypedQName, List<string>>>()
36+
{
37+
// Example with annotations:
38+
// {
39+
// This is the containing complex type class, in the json metadata, this comes from the fully qualified "Name": "c:CT_BubbleSer/c15:ser",
40+
// "c:CT_BubbleSer/c15:ser",
41+
// new Dictionary<TypedQName, List<string>>()
42+
// {
43+
// {
44+
// This is an example of obsoleting the whole class.
45+
// In the json metadata:
46+
// Use the same fully qualified name as the class, for example "Name": "c:CT_BubbleSer/c15:ser",
47+
// "c:CT_BubbleSer/c15:ser",
48+
// ObsoleteClassErrorList
49+
// },
50+
// {
51+
// This is an example obsoleting a child element (property in C#)
52+
// In the json metadata:
53+
// For child elements, this comes from "Name": "c:CT_PictureOptions/c:pictureOptions",
54+
// "c:CT_PictureOptions/c:pictureOptions",
55+
// ObsoletePropertyWarnList
56+
// },
57+
// {
58+
// This is an example obsoleting a child attribute (property in C#)
59+
// In the json metadata: use for example "QName" converted to a TypedQName string using the C# type from the
60+
// Type property with no prefix: ":StringValue/:formatCode",
61+
// ":StringValue/:formatCode",
62+
// ObsoleteAttributeWarnList
63+
// },
64+
// }
65+
// },
66+
{
67+
"c:CT_BubbleSer/c15:ser",
68+
new Dictionary<TypedQName, List<string>>()
69+
{
70+
{
71+
"c:CT_PictureOptions/c:pictureOptions",
72+
ObsoletePropertyWarnList
73+
},
74+
}
75+
},
76+
{
77+
"c:CT_LineSer/c15:ser",
78+
new Dictionary<TypedQName, List<string>>()
79+
{
80+
{
81+
"c:CT_PictureOptions/c:pictureOptions",
82+
ObsoletePropertyWarnList
83+
},
84+
}
85+
},
86+
{
87+
"c:CT_PieSer/c15:ser",
88+
new Dictionary<TypedQName, List<string>>()
89+
{
90+
{
91+
"c:CT_PictureOptions/c:pictureOptions",
92+
ObsoletePropertyWarnList
93+
},
94+
}
95+
},
96+
{
97+
"c:CT_RadarSer/c15:ser",
98+
new Dictionary<TypedQName, List<string>>()
99+
{
100+
{
101+
"c:CT_PictureOptions/c:pictureOptions",
102+
ObsoletePropertyWarnList
103+
},
104+
}
105+
},
106+
{
107+
"c:CT_SurfaceSer/c15:ser",
108+
new Dictionary<TypedQName, List<string>>()
109+
{
110+
{
111+
"c:CT_PictureOptions/c:pictureOptions",
112+
ObsoletePropertyWarnList
113+
},
114+
{
115+
"c:CT_Boolean/c:bubble3D",
116+
ObsoletePropertyWarnList
117+
},
118+
}
119+
},
120+
};
121+
14122
public static bool GetDataModelSyntax(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaNamespace model)
15123
{
16124
foreach (var ns in GetNamespaces(model, services).Distinct().OrderBy(n => n))
@@ -63,9 +171,39 @@ private static string GetBaseName(SchemaType type)
63171
return type.BaseClass;
64172
}
65173

174+
private static void WriteTypeDetails(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType element)
175+
{
176+
// Since some types will not be shadowing an existing static type, it's easier to just disable the warning
177+
writer.WriteLine("#pragma warning disable CS0109");
178+
writer.Write("internal static readonly new OpenXmlQualifiedName ElementQName = ");
179+
writer.WriteQName(services, element.Name.QName);
180+
writer.WriteLine(";");
181+
182+
writer.Write("internal static readonly new OpenXmlQualifiedName ElementTypeName = ");
183+
writer.WriteQName(services, element.Name.Type);
184+
writer.WriteLine(";");
185+
186+
writer.WriteLine("internal static readonly new OpenXmlSchemaType ElementType = new(ElementQName, ElementTypeName);");
187+
writer.WriteLine("#pragma warning restore CS0109");
188+
}
189+
66190
private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType element)
67191
{
68192
writer.WriteDocumentationComment(BuildTypeComments(services, element));
193+
194+
if (_attributeData.TryGetValue(element.Name, out Dictionary<TypedQName, List<string>> ctAttributeData))
195+
{
196+
// if the fully qualified CT/tag name is also one of the children of the dictionary that means the attributes of that
197+
// child's list need to be applied to the whole class, for example, if we're obsoleting an entire class.
198+
if (ctAttributeData.TryGetValue(element.Name, out List<string> attributeStrings))
199+
{
200+
foreach (string attributeString in attributeStrings)
201+
{
202+
writer.WriteLine(attributeString);
203+
}
204+
}
205+
}
206+
69207
writer.Write("public ");
70208

71209
if (element.IsAbstract)
@@ -85,6 +223,10 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
85223
var delimiter = writer.TrackDelimiter(separator: string.Empty, newLineCount: 2);
86224

87225
delimiter.AddDelimiter();
226+
227+
writer.WriteTypeDetails(services, element);
228+
writer.WriteLineNoTabs();
229+
88230
writer.WriteDocumentationComment($"Initializes a new instance of the {className} class.");
89231
writer.Write(element.GetAccessibility());
90232
writer.Write(" ");
@@ -100,7 +242,16 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
100242
foreach (var attribute in element.Attributes)
101243
{
102244
delimiter.AddDelimiter();
103-
writer.WriteAttributeProperty(services, attribute);
245+
246+
if (_attributeData.TryGetValue(element.Name, out Dictionary<TypedQName, List<string>> attrAttributeData)
247+
&& attrAttributeData.TryGetValue(":" + attribute.Type + "/" + attribute.QName.ToString(), out List<string> attrAttributeStrings))
248+
{
249+
writer.WriteAttributeProperty(services, attribute, attrAttributeStrings);
250+
}
251+
else
252+
{
253+
writer.WriteAttributeProperty(services, attribute);
254+
}
104255
}
105256

106257
delimiter.AddDelimiter();
@@ -110,7 +261,15 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
110261
{
111262
foreach (var node in element.Children)
112263
{
113-
writer.WriteElement(services, element, node, ref delimiter);
264+
if (_attributeData.TryGetValue(element.Name, out Dictionary<TypedQName, List<string>> childAttributeData)
265+
&& childAttributeData.TryGetValue(node.Name, out List<string> childAttributeStrings))
266+
{
267+
writer.WriteElement(services, element, node, ref delimiter, childAttributeStrings);
268+
}
269+
else
270+
{
271+
writer.WriteElement(services, element, node, ref delimiter);
272+
}
114273
}
115274
}
116275

@@ -187,9 +346,7 @@ private static void WriteMetadata(this IndentedTextWriter writer, OpenXmlGenerat
187346

188347
if (!containingType.Name.QName.IsEmpty)
189348
{
190-
writer.Write("builder.SetSchema(");
191-
writer.WriteItem(containingType.Name.QName);
192-
writer.WriteLine(");");
349+
writer.WriteLine("builder.SetSchema(ElementType);");
193350
}
194351

195352
if (!containingType.IsAbstract && containingType.Version > OfficeVersion.Office2007)
@@ -203,9 +360,13 @@ private static void WriteMetadata(this IndentedTextWriter writer, OpenXmlGenerat
203360
{
204361
foreach (var child in containingType.KnownChildren)
205362
{
206-
writer.Write("builder.AddChild<");
207-
writer.Write(services.FindClassName(child));
208-
writer.WriteLine(">();");
363+
var className = services.FindClassName(child);
364+
365+
writer.Write("builder.AddChild(");
366+
writer.Write(className);
367+
writer.Write(".ElementType, static () => new ");
368+
writer.Write(className);
369+
writer.WriteLine("());");
209370
}
210371
}
211372

@@ -298,7 +459,7 @@ void WriteUnion(IndentedTextWriter writer, string name, IEnumerable<Validator> v
298459
}
299460
}
300461

301-
private static void WriteElement(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType parent, SchemaElement element, ref Delimiter delimiter)
462+
private static void WriteElement(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType parent, SchemaElement element, ref Delimiter delimiter, List<string>? attributeStrings = null)
302463
{
303464
if (string.IsNullOrEmpty(element.PropertyName))
304465
{
@@ -320,22 +481,52 @@ private static void WriteElement(this IndentedTextWriter writer, OpenXmlGenerato
320481
Remarks = $"xmlns:{element.Name.QName.Prefix} = {services.GetNamespaceInfo(element.Name.QName.Prefix).Uri}",
321482
});
322483

484+
if (attributeStrings is not null)
485+
{
486+
foreach (string attributeString in attributeStrings)
487+
{
488+
writer.WriteLine(attributeString);
489+
}
490+
}
491+
323492
writer.Write("public ");
324493
writer.Write(className);
325494
writer.Write("? ");
326495
writer.WriteLine(element.PropertyName);
327496

328497
using (writer.AddBlock(new() { IncludeTrailingNewline = false }))
329498
{
330-
writer.Write("get => GetElement<");
499+
writer.Write("get => GetElement(");
331500
writer.Write(className);
332-
writer.WriteLine(">();");
501+
writer.Write(".ElementType) as ");
502+
writer.Write(className);
503+
writer.WriteLine(";");
333504

334-
writer.WriteLine("set => SetElement(value);");
505+
writer.Write("set => SetElement(value, ");
506+
writer.Write(className);
507+
writer.WriteLine(".ElementType);");
335508
}
336509
}
337510

338-
private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaAttribute attribute)
511+
private static void WriteQName(this IndentedTextWriter writer, OpenXmlGeneratorServices services, QName qname)
512+
{
513+
writer.Write("new(");
514+
writer.WriteString(services.GetNamespaceInfo(qname.Prefix).Uri);
515+
writer.Write(", ");
516+
writer.WriteString(qname.Name);
517+
writer.Write(")");
518+
}
519+
520+
internal static void WriteTypedName(this IndentedTextWriter writer, OpenXmlGeneratorServices services, TypedQName typed)
521+
{
522+
writer.Write("new(");
523+
writer.WriteQName(services, typed.Type);
524+
writer.Write(", ");
525+
writer.WriteQName(services, typed.QName);
526+
writer.Write(")");
527+
}
528+
529+
private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaAttribute attribute, List<string>? attributeStrings = null)
339530
{
340531
var remarks = default(string);
341532
var info = services.GetNamespaceInfo(attribute.QName.Prefix);
@@ -359,6 +550,14 @@ private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenX
359550
Remarks = remarks,
360551
});
361552

553+
if (attributeStrings is not null)
554+
{
555+
foreach (string attributeString in attributeStrings)
556+
{
557+
writer.WriteLine(attributeString);
558+
}
559+
}
560+
362561
writer.Write("public ");
363562
writer.Write(attribute.Type);
364563
writer.Write("? ");

0 commit comments

Comments
 (0)