-
Notifications
You must be signed in to change notification settings - Fork 556
Root element for generated parts should be nullable #1922
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request makes root elements for generated parts nullable and updates related tests and generator code accordingly. Key changes include:
- Updating test files to use null‐forgiving operators where necessary.
- Adding explicit null checks in sample utility and presentation helper methods.
- Adjusting generator code with nullable annotations and a new [DisallowNull] attribute.
Reviewed Changes
Copilot reviewed 135 out of 135 changed files in this pull request and generated 2 comments.
Show a summary per file
File | Description |
---|---|
test/DocumentFormat.OpenXml.Linq.Tests/OpenXmlPartRootXElementExtensionsTests.cs | Removed "#nullable enable" directive and added null-forgiving operators on Document accesses. |
test/DocumentFormat.OpenXml.Framework.Features.Tests/RandomParagraphIdGeneratorTests.cs | Updated null-forgiving operators on Document and Body accesses. |
src/DocumentFormat.OpenXml/Packaging/WordprocessingDocument.cs | Added null-forgiving operator for Settings when appending the AttachedTemplate element. |
samples/common/PowerPointUtils.cs | Introduced an explicit null check for Presentation in CreatePresentationParts. |
samples/common/ExampleUtilities.cs | Added and adjusted null-checks and null-forgiving operators around core worksheet and workbook operations. |
samples/Linq/SvgExample/StronglyTypedTools.cs | Added null checks for Presentation and Slide elements in SVG addition methods. |
gen/DocumentFormat.OpenXml.Generator.Models/Generators/Parts/PartWriter.cs | Inserted a [DisallowNull] attribute and made the generated property return type nullable. |
Comments suppressed due to low confidence (1)
test/DocumentFormat.OpenXml.Linq.Tests/OpenXmlPartRootXElementExtensionsTests.cs:11
- Removal of '#nullable enable' may inadvertently disable nullable reference type checking in this file; consider reintroducing it if nullability enforcement is desired.
#nullable enable
samples/common/ExampleUtilities.cs
Outdated
@@ -127,7 +128,7 @@ public static void InsertText(SpreadsheetDocument sd, string sheetName, string t | |||
cell.DataType = new EnumValue<CellValues>(CellValues.SharedString); | |||
|
|||
// Save the new worksheet. | |||
worksheetPart.Worksheet.Save(); | |||
worksheetPart.Worksheet?.Save(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the null-conditional operator here may silently skip the Save() call if Worksheet is null; consider throwing an exception instead to maintain consistent failure behavior.
worksheetPart.Worksheet?.Save(); | |
if (worksheetPart.Worksheet == null) | |
{ | |
throw new InvalidOperationException("Worksheet is null. Unable to save changes."); | |
} | |
worksheetPart.Worksheet.Save(); |
Copilot uses AI. Check for mistakes.
writer.Write("public "); | ||
writer.Write(apiName); | ||
writer.Write(" "); | ||
writer.Write("? "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applying [DisallowNull] on a property whose type is rendered as nullable (using '?') is contradictory; please ensure that the nullability annotations and attributes are consistent.
writer.Write("? "); | |
writer.Write(" "); |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not contradictory (there are times you may want this), but @tomjebo why do have both? This means it may be null, but a user can't set it to that. Do we want that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@twsouthwick This was my misreading of your comment here in 959. I read that as [DisallowNull] and set the type to nullable with ?
. I think you must have meant or but I was guessing there was a reason for wanting both. I'll take out the attribute [DisallowNull] as I think the root element property will have to be null at some point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also may have been early on in nullables and I misunderstood the point of it :) for now, just setting it to be nullable is good enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so if the point is only to prevent assignment to null via static code analysis then I'm thinking we shouldn't use this as a way to enforce part root element minOccurs conformance. we should allow code to set to null (assuming eventually it will be set to a valid root element as required by the schemas) and then rely on our validation metadata to correctly catch the minOccurs constraint. that's my feeling. do you agree?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that sounds reasonable for now (that's the current behavior, right?)
@@ -22,6 +22,11 @@ public static void AddSvg(Stream stream, string svgPath, double percentageOfCy) | |||
PresentationPart presentationPart = presentationDocument.PresentationPart ?? | |||
throw new InvalidOperationException(@"PresentationDocument is invalid."); | |||
|
|||
if (presentationPart.Presentation is null) | |||
{ | |||
throw new ArgumentNullException(@"Presentation root element is missing!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, but you don't need the @ symbol when there are no characters to be escaped in a string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change both lines. I just copied that from above and didn't remove the superfluous @
.
@@ -88,6 +93,11 @@ public static void AddSvg(Stream stream, string svgPath, double percentageOfCy) | |||
new Drawing.FillRectangle())), | |||
GetShapeProperties(presentationPart, percentageOfCy)); | |||
|
|||
if (slidePart.Slide is null) | |||
{ | |||
throw new ArgumentNullException(@"Slide root element is missing!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same nit as line 27
@@ -108,6 +118,11 @@ public static TOpenXmlElement WithNamespaceDeclaration<TOpenXmlElement>( | |||
|
|||
private static Presentation.ShapeProperties GetShapeProperties(PresentationPart part, double percentageOfCy) | |||
{ | |||
if (part.Presentation is null) | |||
{ | |||
throw new ArgumentNullException(@"Presentation root element is missing!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same nit as line 27
@twsouthwick @mikeebowen one more review if you have time. there was one more thing that I needed to add here and that was to enable nullability for projects that had any tests of the part root elements. Therefore, I turned it on for I initially turned it on for |
|
||
// Get relationship ID of first slide. | ||
string sldRelId = presentationPart | ||
.Presentation | ||
.SlideIdList? | ||
.Elements<Presentation.SlideId>() | ||
.Select(slideId => (string)slideId.RelationshipId!) | ||
.FirstOrDefault() ?? throw new InvalidOperationException(@"Presentation has no slides."); | ||
.FirstOrDefault() ?? throw new InvalidOperationException("Presentation has no slides."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you want to ensure it's there, you can just call .First()
and it will throw if it's not available
Changes root elements for generated parts to be nullable.
Fixes #959 and #995