fix(#971): OCCTDocumentIsLabelModified names the right attribute, and the other line was the wrong one - #984
Merged
Merged
Conversation
…ribute The two-line header comment on OCCTDocumentIsLabelModified contradicted itself: line 1 attributed the function to "TDocStd_Modified on root", line 2 said it uses TDocStd_Document::GetModified() "not TDocStd_Modified attribute directly". #971 proposed keeping line 2, on the reasoning that TDocStd_Modified is never constructed anywhere in Sources/OCCTBridge (true) and that GetModified() therefore returns a document-owned map, "a different mechanism from the root-label TDocStd_Modified attribute". Measured, that last step is wrong and the correction runs the other way: line 1 was right, line 2 is the one deleted. TDocStd_Document::GetModified() is a three-line forwarder returning TDocStd_Modified::Get(Main()), and TDocStd_Modified's statics all resolve through label.Root(). TDocStd_Document owns no map of its own; it has no myModified member, and TDocStd_Document::IsModified does not exist in 8.0.1 at all (commented out in TDocStd_Document.cxx). The class never appears in the bridge because the kernel constructs it on the bridge's behalf inside TDocStd_Modified::Add, not because the bridge reaches a different store. Measured with a second construction rather than by reading the source twice: Scripts/repro/971-islabelmodified-attribution/probe.mm marks a label through the document API and reads it back through the attribute API. The root gains a TDocStd_Modified attribute, the map GetModified() returns is the same object by address as the root attribute's own Get(), PurgeModified() clears it, and TDocStd_Modified::Add is visible through GetModified(). One store, two ways in. docs/reference/Document.md attributed isModified(_:) to TDocStd_Document::IsModified, the method that does not exist; corrected to TDocStd_Document::GetModified, the one the bridge calls. The probe also records a behaviour nothing documented: GetModified() throws Standard_DomainError on a document where nothing has been marked, because TDocStd_Modified::Get raises rather than returning an empty map. The bridge's existing catch (...) returns false, which is the correct answer, so no bridge change is needed. Closes #971 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…, off the manifest okf/policies/code-style.md's manifest rule: touching a grandfathered file obliges the same PR to make it clean and remove its entry. Measured against Sources/OCCTBridge/.clang-format, that is 1,714 lines of diff -u output for this header, matching #971's own figure: 322 removed, 610 added, 72 hunks, the file growing 2,233 to 2,521 lines. Separate from the two-line correction so a reviewer can read that change without scrolling a thousand lines of whitespace, matching the ordering PR #969 used for Curve2D.swift. Verified the sweep changed no code, not just that clang-format is idempotent over it. Scripts/repro/971-islabelmodified-attribution/tokens-unchanged.py compares the before and after by token sequence rather than by line: 51,192 characters of normalized non-comment tokens identical, and 39,591 characters of comment text identical after whitespace collapse. Comparing normalized text rather than tokens is not enough, measured rather than assumed: the first run collapsed whitespace runs to a single space and reported a difference at `double *_Nonnull` becoming `double* _Nonnull`, a star moving across a space. The comparator's own --self-test runs nine cases, four reformat-shaped edits that must read as unchanged and five content-shaped edits that must not, and a one-at-a-time removal matrix confirms none is decorative: 9/9 baseline, 8/9 without the tokenizer, 7/9 without comment stripping, 8/9 without string-literal awareness. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
okf/policies/writing-style.md: no dedicated stripping pass is required, but clear them from any file you are already editing. Two MARK headings, a third MARK heading, and one parenthetical in OCCTDocumentAddComponentMatrix's note, replaced with a comma or a colon. Separate from the reformat commit so that commit's verification claim stays literal: it reported the comment stream byte-identical after whitespace collapse, which is only true of a tree that still has these four. Re-run against the same baseline after this change, the code stream is still identical to the character (51,192) and the comment stream differs at exactly the four intended sites. Still clang-format clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (7 files)
Previous Review Summary (commit 608ecca)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 608ecca)Status: No Issues Found | Recommendation: Merge Files Reviewed (6 files)
Reviewed by nemotron-3-ultra-550b-a55b:free · Input: 198.7K · Output: 3.9K · Cached: 967.7K |
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gsdali
added a commit
that referenced
this pull request
Aug 20, 2026
…ribe #984 measured what #971 asserted and found the premise backwards. TDocStd_Document::GetModified() is `return TDocStd_Modified::Get(Main());` (TDocStd_Document.cxx:172), so the header line naming the attribute was the correct one and the `Note:` denying it was the defect. This census carried the reversed version twice: - TDocStd_Modified's curated reason said GetModified() is "a different mechanism". It is the same mechanism, reached through the document. - DEFERRED_OVER_FINDINGS pinned the line #984 KEPT rather than the one it deleted, so the check would have fired on a correct tree the moment #984 landed. The deferred list is emptied, not deleted: the mechanism is sound and the comment records both the reversal and the mis-pinned phrase so nobody restores the entry from this PR's history. Also transcribes this PR's CHANGELOG entry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gsdali
added a commit
that referenced
this pull request
Aug 20, 2026
…s entry The code-style failure on this PR was the manifest rule, not the diff: OCCTBridge_Document.h was still grandfathered on style-manifest-bridge.txt while this PR edited the OCCTDocumentAssemblyItemCount signature. #984 has since brought that header fully clang-format clean and taken it off the manifest, so this branch only has to keep its own hunk clean, which it now does. Verified after merging main: zero conflict markers, swift build clean, 5656 tests / 1466 suites / 0 failures, five gates green including check-style-manifest --base origin/main. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
OCCTDocumentIsLabelModified's header comment contradicted itself across two lines: the firstattributed the function to
TDocStd_Modifiedon the root label, the second said it usesTDocStd_Document::GetModified()and "not TDocStd_Modified attribute directly". Only one couldstay.
#971 picked the wrong one, and this PR keeps the other. The issue reasoned that
TDocStd_Modifiedis never constructed anywhere inSources/OCCTBridge(true, its header is#included once and the class never named) and concluded thatGetModified()therefore returns"the document's own
TDF_LabelMap, which is a different mechanism from the root-labelTDocStd_Modifiedattribute". Measured, that last step is wrong.TDocStd_Documenthas no map ofits own; all three of its modified-label methods are forwarders
(
TDocStd_Document.cxx:151-175):and
TDocStd_Modified's statics all resolve throughlabel.Root(). The class does not appear inthe bridge because the kernel constructs it on the bridge's behalf inside
TDocStd_Modified::Add,not because the bridge reaches a different store. So the surviving line is the first:
Measured with a second construction rather than by reading the source twice.
Scripts/repro/971-islabelmodified-attribution/probe.mmmarks a label through the document API and reads it back through the attribute API, against the
pinned kernel:
The same map object by address, reachable and clearable from both sides. One store, two ways in.
Closes #971
The reformat, and how it was checked
Sources/OCCTBridge/include/OCCTBridge_Document.his grandfathered onScripts/style-manifest-bridge.txt, so touching it obliges this PR to bring it fullyclang-formatclean and remove the entry(
okf/policies/code-style.md). The 1,714 lines #971 quotesreproduce exactly: 322 lines removed, 610 added, 72 hunks, the file growing 2,233 to 2,521 lines.
The churn is 932 lines; 1,714 is the
diff -utotal including three context lines per hunk.clang-format --dry-run --Werroris clean after, and CI's own sweep over all 17 non-manifestbridge files still passes.
It is a separate commit from the two-line correction (
b3c200ethen53d6905) so the contentchange can be read without scrolling a thousand lines of whitespace, matching the ordering PR #969
used for
Curve2D.swift.Verifying that a sweep that size changed no code needed more than "clang-format is a formatter".
tokens-unchanged.pycomparesthe file before and after by token sequence, so formatting is invisible to it and a moved,
added or deleted token is not:
Comparing normalized text would not have been enough, and that is measured rather than assumed:
the first run of this comparator collapsed whitespace runs to a single space and reported
CODE DIFFERSatdouble *_Nonnullbecomingdouble* _Nonnull, a star moving across a spacerather than a token changing. Tokenizing is what tells those apart.
Prove-the-test-fails
tokens-unchanged.py --self-testruns nine cases and every one was watched failing before itpassed. Four reformat-shaped edits must read as unchanged (whitespace, pointer-star placement,
re-indentation, comment reflow); five content-shaped edits must not (an identifier rename, a
deleted declaration, an added
extern, a changed comment word, and a//inside a stringliteral). Three of the five were additionally injected into the real header and confirmed
caught before the fixture cases were written: renaming
labelIdtolabelIDreported thedivergence at char 505, deleting the
OCCTDocumentIsLabelModifieddeclaration outright at char7,784, and changing one word of
/// Clear all modification marks.reported a comment divergencewith the code stream still identical.
Under a one-at-a-time removal matrix no case is decorative: 9/9 baseline, 8/9 without the
tokenizer, 7/9 without comment stripping, 8/9 without string-literal awareness.
Second finding, fixed: a method that does not exist
docs/reference/Document.md:1399attributedDocument.isModified(_:)toTDocStd_Document::IsModified. That method does not exist in the pinned 8.0.1 kernel: it iscommented out at
TDocStd_Document.cxx:158-161and absent from the header. Corrected toTDocStd_Document::GetModified, the method the bridge actually calls. One line, called out hererather than folded in silently.
Scripts/census-doc-occt-attribution.pycannot catch this class of error today: it resolves theclass an attribution names against the pinned headers and never the method, so
TDocStd_Document::IsModifiedpasses becauseTDocStd_Documentexists. Noted, not fixed, sinceteaching it method resolution is its own change with its own false-positive budget.
Third finding, not fixed:
GetModified()throws on an untouched documentThe probe recorded a behaviour nothing documented.
TDocStd_Modified::GetraisesStandard_DomainError("TDocStd_Modified::Get : IsEmpty")rather than returning an empty map whenthe root carries no attribute, so
doc->GetModified()throws on any document where nothing hasever been marked modified.
SetModified()andPurgeModified()both tolerate the absence.OCCTDocumentIsLabelModified's existingcatch (...) { return false; }turns that into thecorrect answer, so this is not a defect and no bridge change is made here. It is written up in the
repro README because it is exactly the kind of thing a later "simplify the redundant catch" pass
would remove. It is also why the throw is unreachable from Swift:
Document.isModified(_:)answers
falsefor an untouched document rather than trapping.Fourth finding, not fixed: PR #977 carries the reversed claim in three places
#977 (
fix/810, open) propagates #971's premise into its census artifact and into the docs:Scripts/repro/810-refman-document-xde/refman_census.py, theTDocStd_Modifiedgap rationale:"
OCCTDocumentIsLabelModifiedreadsTDocStd_Document::GetModified()instead, which is adifferent mechanism".
DEFERRED_OVER_FINDINGSentry for this function, whosecorrect:text says thesame and whose
bad_phraseis the line this PR kept, not the line it deleted. That entry isdocumented as failing when the phrase disappears without moving to
KNOWN_OVER_FINDINGS, so itneeds re-pointing either way.
docs/occtswift-wrapping-gaps.md, same wording.Flagged on #977 rather than edited across PR branches. Neither file is on
mainyet, so nothing inthis diff depends on the ordering.
This unblocks PR #980
#980's
code-stylecheck is currently failing for exactly the obligation this PR discharges:it edits
OCCTBridge_Document.h(theOCCTDocumentAssemblyItemCountsignature, around line 2040)while leaving the file on the manifest. Once this lands the file is off the manifest, so #980's
rebase only has to keep its own hunk
clang-formatclean, which it already is, rather than carry a1,714-line sweep of its own. The rebase will conflict at that hunk, since the reformat moves every
line number in the file; the resolution is to re-apply #980's three-line signature onto the
formatted context.
Notes for the reviewer
Sources/OCCTBridge/src/OCCTBridge_Document.mmis deliberately not touched. fix(#964): report the assembly-count bound instead of returning it as the count #980 and Document.openNamedTransaction drops its name, and transactionNumber returns a flag rather than a number #970'swork are both in it, and the only change it would want is a comment about the
catch (...)above, which the repro README carries instead.
behaviour to assert that
Document.isModified(_:)'s existing coverage does not already assert.The verification that earns the checklist item is the token comparison and its self-test, both
run with their subject broken.
code-style.md'sterse-doc-comment rule. The
Standard_DomainErrorbehaviour that would have justified a secondline is in
docs/instead, which is where that policy puts the why.swift test5634 tests in 1464 suites, 0 failures, run twice, once against thepinned kernel and once with
OCCTSWIFT_LOCAL=1against the locally built one. That is one testshort of the 5635 quoted to me as the baseline; the difference is not from this branch, since
git diff --name-only origin/main..HEADcontains no file underTests/, so the count onorigin/mainis the same 5634 by construction. The suite count matches exactly.check-style-manifest.py --base origin/mainclean.The manifest ratchet was confirmed by measurement rather than read from the docstring: re-adding
the entry makes the script exit 1 with "still lists 1 file(s) this PR touches", and removing it
again restores exit 0.
CHANGELOG entry
OCCTDocumentIsLabelModifiedis documented against the attribute it actually reads (#971)The bridge header comment on
OCCTDocumentIsLabelModifiedcontradicted itself, namingTDocStd_Modifiedon one line and denying it on the next.TDocStd_Document::GetModified()is aforwarder to
TDocStd_Modified::Get(Main()), so the attribute on the root label is the mechanismand the denial was the wrong half; the comment now says so once.
docs/reference/Document.mdseparately attributed
Document.isModified(_:)toTDocStd_Document::IsModified, a method thatdoes not exist in OCCT 8.0.1, and now names
TDocStd_Document::GetModified.Sources/OCCTBridge/include/OCCTBridge_Document.hcomes offScripts/style-manifest-bridge.txtin the same change, per the code-style rollout'sfix-what-you-touch rule. No behaviour change: the reformat was verified to leave the file's token
sequence byte-identical.
SemVer impact
NONE. A comment, a documentation line, and a whitespace reformat. No declaration, signature,
symbol or behaviour changes; the reformat's token sequence is byte-identical before and after.