Repository navigation
Sync ako/mxcli: incremental catalog refresh (5.7 s → 0.7 s), E015 string-function-vs-empty warning, Windows bootstrap under Git Bash - #1682
Merged
Conversation
…y (E015) `if trim($Value) != empty` passed check, exec and mx check, and is always true: trim, toLowerCase, toUpperCase, substring, replaceAll and toString return '' for an empty input, never empty. Measured on the Mendix 10.18.5 runtime with `mxcli test --local`, the bare variable as the control. E015 is a warning: the model is valid and builds, only the logic is wrong. The fix it suggests, comparing with '', also covers an empty input. Pitfalls gain the E015 case and a second measured one that check cannot warn about: `+` renders an empty operand as the text 'null'. Refs mendixlabs#580 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82rJKSgq9KUoUNdLnrL
The SessionStart bootstrap script built the release asset name from `uname -s`, which is MINGW64_NT-10.0-26200 (or MSYS_NT-/CYGWIN_NT-) on Windows, so it requested mxcli-mingw64_nt-10.0-26200-amd64 and got a 404. The hook runs under `|| true`, so the session then started without mxcli. Detect the platform once at the top of the script: map MINGW*/MSYS*/ CYGWIN* to windows with an .exe suffix, and keep the binary path in $MXCLI (./mxcli, or ./mxcli.exe on Windows) for every guard, link, download and invocation. On Windows, a non-executable ./mxcli (the Linux build `mxcli new` leaves) is removed before installing ./mxcli.exe, since Git Bash would otherwise resolve ./mxcli to it. Fixes mendixlabs#1680 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82tr6TGuPpuRmehciwH
`trim($v) != empty and trim($v) != ''` has a dead first half, but the '' comparison decides it and the condition does what it says. E015 reported it, which failed TestExprCheckRoundTrip_DescribeProducesZeroHints on the Studio Pro-authored fixture (FeedbackModule.VAL_Feedback): noise on real projects, not the silent wrong result the rule exists for. The check now runs over the finished tree and is skipped when the same and/or chain compares the same call with ''. A guard on another call or in another chain still reports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82rJKSgq9KUoUNdLnrL
exprcheck: warn when a String function's result is compared with empty (E015)
Every refresh rebuilt every catalog table from every unit after any save: about 4.5 s of decoding and inserting on a 4,753-unit project, 5.6-8 s end to end. Each row is now recorded under the unit it came from (a wrapper on the build's transaction; passes mark their owner with own()), and the next build loads the cached catalog, deletes the rows of the changed units, the units whose refs name them and the project-wide rows, and rebuilds only those, listing and decoding only those through a unit-scoped backend view. Anything the plan cannot vouch for falls back to a full build. A refresh after one edit on that project now takes 0.7 s, with or without the source index. Tests compare every table with a forced full build over 19 kinds of edit in full and fast mode; guards count unowned rows, units decoded per incremental refresh and whole-project listings. ADR-0014 records the decision. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82ttaGzay5CwiC2V7cf
…tables # Conflicts: # CHANGELOG.md
…es (#1804) An incremental build rebuilds a document when a unit its refs name changes, so refs must cover every other document a pass reads for it. The lookups that read other documents (the member-ref index, association ends, entity and flow names by ID) now report each name they read per document, and DependencyCoverage checks every read the way the plan would. TestCatalog_RefsCoverEveryCrossDocumentRead holds the fixture at 100%; TestCatalog_RefCoverageOfProject measures a real project on demand (99.4% on FactoryManagement and EVORA - ICX). The trace found that a flow branching on a specialization (`split type $x when M.E`) had no edge to the entity, which `show references` missed too: it gets a `split` edge now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82ttaGzay5CwiC2V7cf
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82ttaGzay5CwiC2V7cf
fix(init): bootstrap script downloads the Windows asset under Git Bash
Rebuild only the changed units on a catalog refresh (#1804)
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.
Syncs
ako/mxcli:maininto upstream: 6 commits from fork PRs ako#1816, ako#1817 and ako#1820.Fixes #1680. Refs #580.
Incremental catalog refresh
Problem: every catalog refresh rebuilt every table from every document after any save. On a 4,753-unit app that was about 4.5 s of decoding and inserting, and 5.6–8 s end to end. This is the second step after the unit store.
Fix:
Row ownership: each catalog row is recorded under the document it came from.
What an incremental refresh rebuilds: it loads the cached catalog and deletes only:
refsname a changed document;It then rebuilds those.
Full-build fallback: anything the plan can't vouch for falls back to a full build. That covers folder, module, settings, security and navigation changes, another mxcli build or catalog level, and
FORCE.refresh catalog fullrefresh catalog full sourceCorrectness:
Equivalence:
TestCatalog_IncrementalBuildEqualsFullBuildand its fast-mode twin compare every table with a forced full build, across 19 kinds of edit. Each step runs a second time with no change.Ref coverage: cross-document reads are recorded, and coverage is checked. It is 100% on the fixture and 99.4% on two real projects.
refsedge to their entity, soshow referencesmissed those flows too. They now get a newsplitedge.Performance guards: three tests fail if a rule of the incremental build is broken:
Breaking one of these would leave the catalog correct but slow, so no correctness test would notice.
Docs: ADR-0014 records the decision and its downsides.
/mxcli-dev:reviewgains a "Catalog builder passes" checklist.Notes:
Idcolumns ofrefsandpermissionsmay differ from a full build.incremental: N units rebuilt, M carried overline instead of per-table counts.E015: a String function's result compared with
empty(refs #580)The problem:
if trim($Value) != empty then …passes check, exec and mx check, but is always true. These functions return'', neverempty. Measured on 10.18.5 withmxcli test --local:empty''' 'trim''''''toLowerCase/toUpperCase/substring/replaceAll''''toString(<empty Integer>)''$v + '''null'''$v(control)empty''The new warning:
string-func-vs-emptyis a warning, because the model is valid. It fires only for the measured functions.'', the guard idiom. Otherwise it was noise on a Studio Pro-authored fixture.Not a warning:
+with anemptyoperand gives the textnull. That is documented as pitfall #18 instead, because whether an operand is empty can't be known at check time.Not measured: Mendix 11.x and nanoflows.
init: the bootstrap script downloads the Windows asset under Git Bash (#1680)The problem: the script built the release asset name from
uname -s. Under Git Bash, MSYS2 and Cygwin that givesmingw64_nt-…, neverwindows, so the download returned 404. The hook runs with|| true, so the session started without mxcli and nothing said why.The fix:
MINGW*,MSYS*andCYGWIN*now map towindows, with the.exesuffix../mxcli.exeon Windows../mxcliis removed first. Otherwise Git Bash resolves./mxclito that file.Tests: they run the generated script with a fake
unameandcurl, for Git Bash (64- and 32-bit), MSYS2, Cygwin and Windows on ARM, with Linux and macOS as the controls.Validation
make ci-localpasses, except for twocmd/mxcli/dockerTestSyncJavaDependencies_*tests that fail the same way onmainin the authors' environment