Skip to content

Commit 40c7ec8

Browse files
committed
Merge remote-tracking branch 'origin/main' into element-non-generic
2 parents 6357dd8 + 4219646 commit 40c7ec8

File tree

13 files changed

+861
-7
lines changed

13 files changed

+861
-7
lines changed

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
<LatestTargetFramework>net8.0</LatestTargetFramework>
7171
<SamplesFrameworks>net8.0</SamplesFrameworks>
7272
<SamplesFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(SamplesFrameworks);net472</SamplesFrameworks>
73+
<DefineConstants Condition=" '$(TargetFramework)' != 'net35' And '$(TargetFramework)' != 'net40' And '$(TargetFramework)' != 'net46' And '$(TargetFramework)' != 'net472' ">$(DefineConstants);FEATURE_ASYNC_SAX_XML</DefineConstants>
7374
</PropertyGroup>
7475
</Otherwise>
7576
</Choose>

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

Lines changed: 157 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,112 @@ namespace DocumentFormat.OpenXml.Generator.Generators.Elements;
1313

1414
public static class DataModelWriterExtensions
1515
{
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+
16122
public static bool GetDataModelSyntax(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaNamespace model)
17123
{
18124
foreach (var ns in GetNamespaces(model, services).Distinct().OrderBy(n => n))
@@ -84,6 +190,20 @@ private static void WriteTypeDetails(this IndentedTextWriter writer, OpenXmlGene
84190
private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType element)
85191
{
86192
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+
87207
writer.Write("public ");
88208

89209
if (element.IsAbstract)
@@ -122,7 +242,16 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
122242
foreach (var attribute in element.Attributes)
123243
{
124244
delimiter.AddDelimiter();
125-
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+
}
126255
}
127256

128257
delimiter.AddDelimiter();
@@ -132,7 +261,15 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
132261
{
133262
foreach (var node in element.Children)
134263
{
135-
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+
}
136273
}
137274
}
138275

@@ -318,7 +455,7 @@ void WriteUnion(IndentedTextWriter writer, string name, IEnumerable<Validator> v
318455
}
319456
}
320457

321-
private static void WriteElement(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType parent, SchemaElement element, ref Delimiter delimiter)
458+
private static void WriteElement(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType parent, SchemaElement element, ref Delimiter delimiter, List<string>? attributeStrings = null)
322459
{
323460
if (string.IsNullOrEmpty(element.PropertyName))
324461
{
@@ -340,6 +477,14 @@ private static void WriteElement(this IndentedTextWriter writer, OpenXmlGenerato
340477
Remarks = $"xmlns:{element.Name.QName.Prefix} = {services.GetNamespaceInfo(element.Name.QName.Prefix).Uri}",
341478
});
342479

480+
if (attributeStrings is not null)
481+
{
482+
foreach (string attributeString in attributeStrings)
483+
{
484+
writer.WriteLine(attributeString);
485+
}
486+
}
487+
343488
writer.Write("public ");
344489
writer.Write(className);
345490
writer.Write("? ");
@@ -377,7 +522,7 @@ internal static void WriteTypedName(this IndentedTextWriter writer, OpenXmlGener
377522
writer.Write(")");
378523
}
379524

380-
private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaAttribute attribute)
525+
private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaAttribute attribute, List<string>? attributeStrings = null)
381526
{
382527
var remarks = default(string);
383528
var info = services.GetNamespaceInfo(attribute.QName.Prefix);
@@ -401,6 +546,14 @@ private static void WriteAttributeProperty(this IndentedTextWriter writer, OpenX
401546
Remarks = remarks,
402547
});
403548

549+
if (attributeStrings is not null)
550+
{
551+
foreach (string attributeString in attributeStrings)
552+
{
553+
writer.WriteLine(attributeString);
554+
}
555+
}
556+
404557
writer.Write("public ");
405558
writer.Write(attribute.Type);
406559
writer.Write("? ");

generated/DocumentFormat.OpenXml/DocumentFormat.OpenXml.Generator/DocumentFormat.OpenXml.Generator.OpenXmlGenerator/schemas_microsoft_com_office_drawing_2012_chart.g.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2752,6 +2752,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.Marker? Marker
27522752
/// <remarks>
27532753
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
27542754
/// </remarks>
2755+
[Obsolete("Unused property, will be removed in a future version.", false)]
2756+
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
27552757
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
27562758
{
27572759
get => GetElement(DocumentFormat.OpenXml.Drawing.Charts.PictureOptions.ElementType) as DocumentFormat.OpenXml.Drawing.Charts.PictureOptions;
@@ -3262,6 +3264,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties? ChartShapePro
32623264
/// <remarks>
32633265
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
32643266
/// </remarks>
3267+
[Obsolete("Unused property, will be removed in a future version.", false)]
3268+
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
32653269
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
32663270
{
32673271
get => GetElement(DocumentFormat.OpenXml.Drawing.Charts.PictureOptions.ElementType) as DocumentFormat.OpenXml.Drawing.Charts.PictureOptions;
@@ -3454,6 +3458,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties? ChartShapePro
34543458
/// <remarks>
34553459
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
34563460
/// </remarks>
3461+
[Obsolete("Unused property, will be removed in a future version.", false)]
3462+
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
34573463
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
34583464
{
34593465
get => GetElement(DocumentFormat.OpenXml.Drawing.Charts.PictureOptions.ElementType) as DocumentFormat.OpenXml.Drawing.Charts.PictureOptions;
@@ -3634,6 +3640,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties? ChartShapePro
36343640
/// <remarks>
36353641
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
36363642
/// </remarks>
3643+
[Obsolete("Unused property, will be removed in a future version.", false)]
3644+
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
36373645
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
36383646
{
36393647
get => GetElement(DocumentFormat.OpenXml.Drawing.Charts.PictureOptions.ElementType) as DocumentFormat.OpenXml.Drawing.Charts.PictureOptions;
@@ -3808,6 +3816,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties? ChartShapePro
38083816
/// <remarks>
38093817
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
38103818
/// </remarks>
3819+
[Obsolete("Unused property, will be removed in a future version.", false)]
3820+
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
38113821
public DocumentFormat.OpenXml.Drawing.Charts.PictureOptions? PictureOptions
38123822
{
38133823
get => GetElement(DocumentFormat.OpenXml.Drawing.Charts.PictureOptions.ElementType) as DocumentFormat.OpenXml.Drawing.Charts.PictureOptions;
@@ -3847,6 +3857,8 @@ public DocumentFormat.OpenXml.Drawing.Charts.Values? Values
38473857
/// <remarks>
38483858
/// xmlns:c = http://schemas.openxmlformats.org/drawingml/2006/chart
38493859
/// </remarks>
3860+
[Obsolete("Unused property, will be removed in a future version.", false)]
3861+
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
38503862
public DocumentFormat.OpenXml.Drawing.Charts.Bubble3D? Bubble3D
38513863
{
38523864
get => GetElement(DocumentFormat.OpenXml.Drawing.Charts.Bubble3D.ElementType) as DocumentFormat.OpenXml.Drawing.Charts.Bubble3D;

src/DocumentFormat.OpenXml.Framework/OpenXmlElement.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,11 +796,30 @@ public void RemoveNamespaceDeclaration(string prefix)
796796
/// Finds the first child element in type T.
797797
/// </summary>
798798
/// <typeparam name="T">Type of element.</typeparam>
799-
/// <returns></returns>
799+
/// <returns>The first child element of type T or null</returns>
800800
public T? GetFirstChild<T>()
801801
where T : OpenXmlElement
802802
=> ChildElements.First<T>();
803803

804+
/// <summary>
805+
/// Finds the first child element of <typeparam ref="T"/> or adds a new element if it does not exist.
806+
/// </summary>
807+
/// <typeparam name="T">Type of element.</typeparam>
808+
/// <returns>The new or existing OpenXmlElement</returns>
809+
public T GetOrAddFirstChild<T>()
810+
where T : OpenXmlElement, new()
811+
{
812+
var child = GetFirstChild<T>();
813+
814+
if (child is null)
815+
{
816+
child = new T();
817+
AppendChild(child);
818+
}
819+
820+
return child;
821+
}
822+
804823
/// <summary>
805824
/// Gets the OpenXmlElement element that immediately precedes the current OpenXmlElement element.
806825
/// Returns null (Nothing in Visual Basic ) if there is no preceding OpenXmlElement element.

0 commit comments

Comments
 (0)