Skip to content

Conversation

ekoneil
Copy link
Collaborator

@ekoneil ekoneil commented Oct 1, 2025

Prevent a strange issue in MeasuredResults when calling ChangeChromatograms. Passing a zero-length list causes issues with SequenceTree, undo/redo, Audit Log, and FilesTree.

Instead:

(1) Require callers to pass null to clear a non-empty list of chromatograms. Throw an exception except for one special case described below.

(2) Allow passing a zero-length list when MeasuredResults already has no chromatograms. This case happens during XML deserialization. MoleculeDocumentSerializeTest fails unless this is allowed.

…ograms.

Passing a zero-length list causes issues with SequenceTree, undo/redo, Audit Log, and FilesTree.

(1) Require callers to pass null to clear a non-empty list of chromatograms. Throw an exception except for one special case described below.

(2) Allow passing a zero-length list when MeasuredResults already has no chromatograms. This case happens during XML deserialization. MoleculeDocumentSerializeTest fails unless this is allowed.
@ekoneil
Copy link
Collaborator Author

ekoneil commented Oct 1, 2025

Below is the stack trace for the failure during XML deserialization.

Stacktrace

There is an error in XML document (40, 4).
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
at pwiz.SkylineTestUtil.AssertEx.Deserialize[TObj](String s) in C:\pwiz\pwiz_tools\Skyline\TestUtil\AssertEx.cs:line 300
at pwiz.SkylineTest.SrmDocumentTest.MoleculeDocumentSerializeTest() in C:\pwiz\pwiz_tools\Skyline\Test\SrmDocumentTest.cs:line 136
------- Stdout: -------
74. MoleculeDocumentSerializeTest

@nickshulman
Copy link
Contributor

What was the code in your branch that was causing the problem?
I don't think that giving the zero-length list to MeasuredResults is the problem.
I think the problem is that SrmSettings never wants to have a non-null MeasuredResults with a zero-length Chromatograms list.
So, calling "ChangeMeasuredResults(MeasuredResults.Empty)" is the thing that we want to prevent.

@ekoneil ekoneil closed this Oct 1, 2025
@ekoneil ekoneil deleted the Skyline/work/20251001_MeasuredResults_ZeroLengthList_Fix branch October 1, 2025 23:22
@brendanx67 brendanx67 restored the Skyline/work/20251001_MeasuredResults_ZeroLengthList_Fix branch October 1, 2025 23:36
@brendanx67
Copy link
Contributor

I will fix this PR.

@brendanx67 brendanx67 reopened this Oct 1, 2025
@brendanx67
Copy link
Contributor

What was the code in your branch that was causing the problem? I don't think that giving the zero-length list to MeasuredResults is the problem. I think the problem is that SrmSettings never wants to have a non-null MeasuredResults with a zero-length Chromatograms list. So, calling "ChangeMeasuredResults(MeasuredResults.Empty)" is the thing that we want to prevent.

Agreed. Though, I also removed MeasuredResults.Empty, since it was only used in a single function that did not really need it. Having and Empty member just encouraged its use and potential to be set to SrmSettings. Having it around seemed confusing, since we use Empty in place of null in many places. Maybe if we wrote this code today we would use an Empty static, but I did not when I first wrote it and changing now seems not worth the effort.

// 10.23.12 -- The order of <measured_results> and <data_settings> has been switched to enable parsing (in Panorama)
// of all annotation definitions before reading any replicate annotations in <measured_results>.
// We want Skyline to be able to read older documents where <measured_results> come before <data_settings>
MeasuredResults NullIfEmpty(MeasuredResults val)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably be cleaner if "NullIfEmpty" were a method on MeasuredResults:
public MeasuredResults NullIfEmpty() { return Chromatograms.Count == 0 ? null : this);}

Then you would do:
MeasuredResults = reader.DeserializeElement<MeasuredResults>()?.NullIfEmpty();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My original implementation was in this direction, but I forgot about using ?.NullIfEmpty(). Yeah. That seems cleaner.

@brendanx67 brendanx67 merged commit 55d16a3 into master Oct 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants