name: jmix-ide-static-analysis
description: Gate-1 static checks. PRIMARY when connected: run a Jmix-aware IDE/semantic inspection (e.g. JetBrains get_file_problems) on every file you created/edited — it catches the *-view.xml defects a compiler cannot (unresolved msg://, invalid property paths, missing data containers). Fall back to compileJava plus mechanical descriptor checks when no inspection is available. Read before relying on any static check.
Static analysis (Gate 1)
Gate 1 = every file you created or edited passes a static check before you move
on. Run the IDE inspection first when it is connected; fall back to compile +
mechanical descriptor checks when it is not.
1. Semantic / IDE inspection — PRIMARY when connected
If you have a Jmix-aware IDE/semantic inspection (e.g. JetBrains
get_file_problems), run it PER FILE on every .java and especially every
*-view.xml you touched — this is your primary Gate-1 check. It is the only STATIC
catch for the descriptor defects a compiler cannot see: unresolved msg:// keys,
invalid property paths, missing data containers, broken component bindings (and it
flags the same Java errors a compile would). Rules when you use one:
- Always pass
projectPath — your project's absolute root (pwd). The project
you work in is opened as its own root, so projectPath = your current working
directory. Pass it on EVERY JetBrains MCP call (get_file_problems,
get_project_modules, create_new_file, …): with more than one project open the
IDE cannot tell which you mean and the call fails — No exact project is specified
or a malformed -32602 response — so the gate silently does nothing. If you do
not know the root: issue any JetBrains MCP call once WITHOUT projectPath; the
error lists every open project as Currently open projects: {"projects":[{"path": …}]}. Pick the entry equal to (or the deepest one containing) your pwd, then
reuse it as projectPath for all later calls.
- Surface WARNINGS, not just errors. Jmix-plugin findings (unresolved
msg://, bad fetch/entity refs, broken bindings) are typically reported as
WARNINGS — an errors-only view looks clean when it is not. Include warnings and
treat Jmix-inspection / unresolved-reference warnings as blockers.
- Never trust an EMPTY result you did not confirm. An inspection that
silently targeted the wrong project/module returns "no problems" on a file it
never looked at — that is false-clean. Confirm the file was actually inspected
before calling it clean.
- The inspection needs the project opened as a STANDALONE Gradle project (its
own root, not a subdirectory of another open project) — a nested path resolves to
the wrong module and returns generic noise (e.g. "URI is not registered"), not
Jmix findings. Even when it works it can miss unknown components / bad attributes,
so keep the mechanical descriptor checks alongside it.
- Fallback decision rule. If the inspection returns "URI is not registered" or
only generic/non-Jmix findings on a file you KNOW has a descriptor (a
*-view.xml
you just edited), treat the inspection as UNAVAILABLE for this run — do NOT call
the file clean. Fall through to compileJava + the mechanical descriptor checks.
2. Compile — Java ground truth, and floor when no inspection
./gradlew --no-daemon compileJava
Authoritative for .java: unresolved symbols, wrong imports/packages, type
mismatches, bad handler signatures. Run it regardless — it is cheap and is the
precondition for Gate 2. But compileJava is BLIND to XML descriptors. A
*-view.xml with an enum bound to entityComboBox instead of comboBox, an
itemsQuery without :searchString, a msg:// typo, or an action opening a
non-existent view id compiles perfectly clean and then throws at render time. A
clean compile proves NOTHING about any .xml, and a 0-byte .java/.xml also
compiles clean — confirm written files are non-empty.
3. Mechanical descriptor checks — floor when no inspection
When you have no semantic inspection, these are your static floor for the
render-time defect classes. Run them from the project directory; each maps to a
defect that passes a clean compile (and even a green clean test).
Two kinds below: the find checks are pass/fail (any output = a defect to fix);
the grep checks only SURFACE candidates — a non-empty result is not
automatically a failure, but you MUST explain every hit (e.g. each msg:// key
must actually resolve in a messages_*.properties; each = : loader param must
be bound/guarded).
find src/main/java -name '*.java' | while read f; do head -1 "$f" | grep -q '^package ' || echo "MISSING package: $f"; done
grep -rn "nullable = false\|@NotNull" src/main/java --include='*.java'
grep -rn "= :" src/main/resources --include='*-view.xml'
grep -rn "CREATE\|MODIFY\|VIEW" src/main/java --include='*Role.java'
grep -rn "itemsQuery" src/main/resources --include='*-view.xml'
grep -rn "com.vaadin.flow.component.dialog.Dialog" src/main/java --include='*.java'
grep -rhoE 'msg://[^"<> ]+' src/main/resources --include='*.xml' | sort -u
find src/main -type f \( -name '*.java' -o -name '*.xml' \) -size 0
These are MANDATORY whenever you have neither an inspection nor a Gate-3 render
walk — they are then your ONLY catch for those defects.
Per-file loop
For each file you created or edited: inspection-if-connected (else compile) → fix
every error and every unresolved-reference / Jmix-inspection warning → repeat until
clean. Run it on EVERY file, not a sample — the defects that survive are the ones
you were confident about and never checked. After the last edit, a full
compileJava is the precondition for Gate 2 (clean test).
For verifying a symbol BEFORE you type an unfamiliar API, see jmix-verify-api-symbol
— the cheapest, earliest defense against hallucinated names.