#!/usr/bin/env python3 """Build shared modules and the pinned IDE adapter; verify target bytecode and docs.""" from pathlib import Path import argparse import zipfile import json import os import re import subprocess import sys ROOT = Path(__file__).resolve().parent.parent parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--idea-home", default=os.environ.get("IDEA_HOME"), required=not os.environ.get("IDEA_HOME")) parser.add_argument("--target-java-home", default=os.environ.get("TARGET_JAVA_HOME"), required=not os.environ.get("TARGET_JAVA_HOME")) args = parser.parse_args() idea = Path(args.idea_home).resolve() info = json.loads((idea / "Resources/product-info.json").read_text()) if info["buildNumber"] != "263.7307.200": sys.exit("Expected IntelliJ SDK build 263.7307.200") def run(command): subprocess.run([str(x) for x in command], cwd=ROOT, check=True) wrapper = ROOT / ("mvnw.cmd" if os.name == "nt" else "mvnw") run([sys.executable, ROOT / "scripts/check-neitzellib-artifact.py"]) run([wrapper, "-B", "-ntp", "clean", "install"]) run([wrapper, "-B", "-ntp", "-pl", "designer-target-tools", "org.apache.maven.plugins:maven-dependency-plugin:3.6.1:build-classpath", "-DincludeScope=runtime", "-Dmdep.outputFile=target/runtime-classpath.txt"]) for module in ("contracts", "model-processor", "preview-api", "core", "kit-ui", "standalone", "target-tools", "maven-plugin"): name = "designer-" + module expected = 69 if module in ("kit-ui", "standalone") else 65 with zipfile.ZipFile(ROOT / name / "target" / (name + "-0.1.0-SNAPSHOT.jar")) as jar: classes = [n for n in jar.namelist() if n.endswith(".class")] assert classes, name assert all(int.from_bytes(jar.read(n)[6:8], "big") == expected for n in classes), name classpath = str(ROOT / "designer-target-tools/target/classes") + os.pathsep + (ROOT / "designer-target-tools/target/runtime-classpath.txt").read_text().strip() target_java = Path(args.target_java_home) / "bin/java" version = subprocess.run([str(target_java), "-version"], capture_output=True, text=True, check=True) if not re.search(r'version "21[.\"]', version.stderr): sys.exit("Target linkage gate requires Java 21") run([target_java, "-cp", classpath, "de.neitzel.fxdesigner.target.TargetToolInfo"]) run([sys.executable, ROOT / "scripts/check-preview-fixtures.py", "--target-java-home", args.target_java_home]) run([wrapper, "-B", "-ntp", "-pl", "designer-standalone", "org.apache.maven.plugins:maven-dependency-plugin:3.6.1:build-classpath", "-DincludeScope=test", "-Dmdep.outputFile=target/smoke-classpath.txt"]) smoke_classpath = os.pathsep.join([str(ROOT / "designer-standalone/target/test-classes"), str(ROOT / "designer-standalone/target/classes"), (ROOT / "designer-standalone/target/smoke-classpath.txt").read_text().strip()]) run([Path(os.environ["JAVA_HOME"]) / "bin/java", "-cp", smoke_classpath, "de.neitzel.fxdesigner.build.BuildRefreshSmoke", ROOT, args.target_java_home]) run([ROOT / "designer-intellij" / ("gradlew.bat" if os.name == "nt" else "gradlew"), "-p", "designer-intellij", "--no-daemon", "-PideaHome=" + str(idea), "clean", "test", "buildPlugin", "verifyPluginProjectConfiguration"]) run([sys.executable, ROOT / "scripts/check-connected-workflow.py", "--idea-home", args.idea_home, "--target-java-home", args.target_java_home]) with zipfile.ZipFile(next((ROOT / "designer-intellij/build/distributions").glob("*.zip"))) as plugin: names = plugin.namelist() assert any("javafx-graphics-26-mac" in n for n in names), "Missing host JavaFX implementation" assert not any("designer-target-tools" in n or "designer-preview-api" in n or "designer-model-processor" in n or "designer-maven-plugin" in n or "/fx-1.0" in n for n in names), "Target dependency in IDE host" for document in [ROOT / "README.md", ROOT / "AGENTS.md", ROOT / "THIRD-PARTY-NOTICES.md", *sorted((ROOT / "docs").rglob("*.md"))]: content = document.read_text(encoding="utf-8") for example in re.findall(r"```json\n(.*?)\n```", content, re.S): json.loads(example) for target in re.findall(r"\]\(([^)]+)\)", content): if "://" in target or target.startswith("#"): continue local = document.parent / target.split("#", 1)[0] if not local.exists(): sys.exit(f"Broken local link in {document.relative_to(ROOT)}: {target}") print("PASS module builds, adapter tests, bytecode baselines, target linkage, plugin packaging and documentation")