A complete context dump so a fresh conversation can continue seamlessly.
A JetBrains IDE plugin that ports the vscode-titanium
extension to the IntelliJ Platform. It develops Titanium SDK apps/modules
by wrapping the titanium (ti) and alloy CLIs.
- Language/build: Kotlin + Gradle, IntelliJ Platform Gradle Plugin
2.6.0. - Compiles against: IntelliJ IDEA Ultimate 2024.3 (
platformType=IU, build 243) because it bundles the closed-sourceJavaScriptplugin. - Runs on: EVERY IntelliJ-Platform IDE incl. Community editions + Android Studio (NOT Fleet).
- Location on disk:
/Users/AbdullahFaqeir/dev/TiDev/JetBrains Plugin/titanium-jetbrains - Git: repo exists, branch
main, remotehttps://github.com/devloopsnet/titanium-jetbrains.git. Commits must be made by the user from their Mac terminal (the sandbox can't manage git locks on the synced mount). ~72 main Kotlin files + 2 test files.
Universal-core + optional-JS split. Titanium is JS/Alloy, so JS-aware features need the bundled
JavaScript plugin — which only ships in paid IDEs. To still run on Community:
- Core (
META-INF/plugin.xml) hard-depends only oncom.intellij.modules.platform(+com.intellij.modules.xml). This is ~everything. - Optional JS layer (
META-INF/titanium-javascript.xml) loads only when the JavaScript plugin is present, via<depends optional="true" config-file="titanium-javascript.xml">JavaScript</depends>. It holds ONLYlanguage="JavaScript"contributors. - Hard rule: NO core code may
import com.intellij.lang.javascript.*. Only thealloy/js/package may, and it's wired solely from the optional descriptor. Verified clean. - Compiling against Ultimate is compile-time only; the optional
<depends>keeps runtime loadable on Community. The JS plugin is bundled-only, so usebundledPlugin("JavaScript"), neverplugin("JavaScript", …).
- Build / Run / Clean via a run configuration (
run/TiRunConfiguration*), platform/target/device/ SDK/deploy-type/build-only/LiveView options; producer fromtiapp.xmlcontext. - Debug (
debug/*): from-scratch Chrome DevTools Protocol client over JDK WebSocket, own breakpoint type, variable inspection AND expression evaluation/watches. - Package (dist builds) iOS App Store/Ad Hoc + Android Play Store (
actions/pkg/*,run/TiPackage*), cert/profile fromti info, keystore fields; runs in a console. - Create Keystore via
keytool(actions/pkg/TiCreateKeystore*). - Wizards: Create App / Create Module (
ti create); Alloy generators (controller/view/style/model/migration/widget viaalloy generate). - SDK mgmt: install/select/uninstall/check-updates (
sdk/TiSdkManager,actions/sdk/*); Update CLI/Alloy (npm i -g). - Tool windows: build explorer (tree of project → recent builds → platforms/targets/devices → SDKs → env issues, double-click to run) + Help window.
- Toolbar (New UI
MainToolbarRight): Platform picker + Device picker (ComboBoxAction, values fromti info), Build, Debug, Package, Clean, Refresh, + Titanium dropdown. - Settings (
settings/*): CLI/alloy/node paths, log level, LiveView default, dist dir, i18n lang, keystore path/alias, default creation dir, JS function template. PersistentStateComponent. - Editor intelligence: completion for Alloy views (XML), tiapp.xml, TSS, JS controllers (optional);
hover docs from
api.jsca; go-to-definition (handler→controller, i18n→strings.xml, id/class→TSS rule); intentions (insert handler, insert i18n, extract style); related-file gutter markers + Open-Related actions (Ctrl+Alt+X/V/S/A); Live Templates (ti*,al*). - TSS language: file type, hand-written lexer, syntax highlighting, flat parser (PSI), brace matcher, commenter, completion.
- SDK-backed completion:
environment/TiApiMetadataparses installed SDK'sapi.jsca. - Recent builds persisted per-workspace; clickable file paths in build/package consoles
(
run/TiFilePathFilter). - Packaging/CI: LICENSE (Apache-2.0), CHANGELOG,
.github/workflows/build.yml(test+build) andrelease.yml(sign+publish on tag).
- Compile: PROVEN GREEN.
:compileKotlinsucceeded on the user's machine. The only earlier test failure was missing JUnit — fixed by addingtestImplementation("junit:junit:4.13.2")tobuild.gradle.kts. - The big fix just made (v8 CLI): The user's CLI is Titanium CLI v8 (8.1.5).
TiCliused to append--no-prompt --no-banner --no-colors --no-progress-barsto every command and--typestoinfo. v8 rejects these, soti -vandti inforeturned nothing → the tool window showed nothing on Refresh. FIXED:TiClinow uses bareti -vandti info --output json, and builds run in the project dir (cwd) with no--project-dir/--no-*flags. TiInfoParserrewritten to the REAL v8 JSON shape (validated against the user's actualti infooutput — extracts 14 SDKs, 30 devices, 5 certs, 27 profiles, 3 issues). Real structure:titanium: map"<id>": {version, path, platforms}(noselected); selected SDK =ios.tisdkorandroid.tisdk.- iOS sims:
ios.simulators.ios.<runtime>[] {udid,name,version}. - iOS devices:
ios.devices[]. - Android emulators:
android.emulators[](NOTavds); devices:android.devices[]. - Certs:
ios.certs.keychains.<keychain>.{developer,distribution}[]. - Profiles:
ios.provisioning.{development,distribution,adhoc,enterprise}[]. - Issues:
ios.issues[]+android.issues[](objects withmessage); no top-levelissues.
A robustness sweep across all layers (compile not yet verified — run ./gradlew test buildPlugin):
- CLI layer:
TiCli.extractJsonnow strips trailing garbage too (npm warnings after JSON broke Gson);ti -vparsing tolerates banners/notices (extractVersion, regex-based); PATH injection deduped intocli/CliEnv.kt(readscmd.parentEnvironment, notSystem.getenv); missing project dir no longer set as cwd. SDK versions sort numerically (TiInfoParser.VERSION_ORDER) — 13.x above 9.x. - Services:
TiEnvironmentServicecatches unexpected refresh failures (PCE rethrown), guardsproject.isDisposedinonFinished.TiApiMetadatacoalesces concurrent loads, type-safe JSON access.TiProjectServiceauto-invalidates its cache via a VFS listener on tiapp.xml/timodule.xml changes (nowDisposable), skips hidden dirs.TiSdkManagerreports timeouts and hints when a subcommand is unsupported (v8sdk selectconcern). - Run/debug:
TiRunLauncherreuses same-name run configs instead of duplicating them.extraArgstokenized quote-aware (ParametersListUtil).CdpClient: HTTP/WS timeouts,/json/listfallback, serialized sends (JDK WS forbids overlap), callback cleanup on close, error responses logged.TiDebugProcess: retry window 5 min, bails on stop/dead build process. - UI/actions: dialogs validate names/app IDs/keystore paths/validity; background tasks
snapshot Swing values on EDT; timeouts reported;
TiVfs.refreshis async (sync refresh off-EDT can deadlock); intentions wrap VFS writes in try/IOException + XML-escape i18n keys. - TSS lexer bug fixed: trailing backslash in an unterminated string pushed
tokenEndpast the buffer (highlighting exception). Regression-tested. - Tests added:
TiCliParsingTest,TiInfoParserEdgeTest, expandedTssLexerTest(bounds/termination invariants checked for every token).
- Create TSS rule intention (
intentions/AlloyCreateTssRuleIntention.kt) +tssIdTemplate/tssClassTemplate/tssTagTemplatesettings (vscodecodeTemplates.tss*). Registered in plugin.xml + Settings UI. - Build command echo (
displayBuildCommandInConsole, default on): run console echoes theti buildline; packaging console echoes with passwords masked (TiPackager.maskedCommandLine, unit-tested inTiPackagerMaskingTest). - Snippet parity:
liveTemplates/Titanium.xmlnow 18 templates (added tiinfo, tidebug, titrace, tiopt, tiremevent, tifireevent, tianim, tifile, tisound, tiaudio, tivideo, ticamera);Alloy.xmlnow 14 (added alglo, alcfg, alargs, alcon, alcol, almod, alwid, ifios, ifand, ifwin). - Image path completion (
alloy/TiImageAssets.kt): TSS image-like properties and view attributes complete runtime-style paths (/images/foo.png) fromapp/assets,app/images,Resources; platform subdirs stripped; capped at 500. - Fix Environment Issues (
actions/sdk/TiFixEnvironmentAction.kt): CLI missing → offernpm i -g titanium alloy; no SDK → offer install latest; else listti infoissues. - Select Updates / Install All Updates (
sdk/TiUpdateChecker.kt,actions/sdk/TiUpdatesActions.kt): unified SDK + titanium + alloy check (npmview/ls -g --jsonvia newcli/NpmCli.kt), checkbox dialog, install-all. - Periodic update check (
updateCheckFrequencyHours, default 24, 0 = off) inTiStartupActivity;lastUpdateCheckMspersisted app-wide. TiToolingUpdateActionsnow reusesNpmCli/CliEnv(PATH handling deduped).
With this, all vscode-titanium commands/settings/snippets have JetBrains equivalents. Remaining qualitative gap: debugger maturity (source maps) — see §5/§6.
Titanium now appears in the IDE's New Project dialog (wizard/ package), dual-registered:
- IDEA / Android Studio:
TiNewProjectWizard(GeneratorNewProjectWizard) exposed viaTiModuleBuilderAdapter(GeneratorNewProjectWizardBuilderAdapter, registered at themoduleBuilderEP). The options form is a chainedNewProjectWizardStepafter the standard name/location step;setupProjectcallsTiProjectScaffolder. History: a first attempt used legacyModuleType/ModuleBuilder.getCustomOptionsStep— the NEW (2022.1+) wizard dialog does not render that, producing an empty page. Don't go back to it. - WebStorm-family (PyCharm, PhpStorm, GoLand…):
TiProjectGenerator(WebProjectTemplate)TiProjectGeneratorPeerimplementingProjectGeneratorPeerdirectly, registered asdirectoryProjectGenerator. Gotcha (hit live in WebStorm): the dialog renders the page viapeer.buildUI(settingsStep); extendingGeneratorPeerImplwith its no-arg constructor makesbuildUIadd an internal emptyJPanel(overridinggetComponent()is not enough) — the page shows only the Location field. Always overridebuildUIand add the component viasettingsStep.addSettingsComponent(...).
- Both share
TiNewProjectPanel/TiNewProjectSettingsandTiProjectScaffolder, which runsti create -t app|module -n <dirname> --id <id> -p <platforms> -d <parent> [-u <url>] [--ios-code-base objc|swift] [--android-code-base java|kotlin] --forcein the background, then refreshes VFS + project cache + environment. - Full option set (parity with
ti createinteractive prompts): project type (app/module); for apps a framework choice — Alloy (default) or Classic (Alloy is applied by runningalloy new <dir>after the scaffold, with graceful fallback to Classic ifalloyis missing); for modules per-platform code bases (iOS: Objective-C/Swift, Android: Java/Kotlin); app id (validated reverse-domain, auto-derived from name); platforms; optional author URL (-u). The panel shows/hides app vs module options as the type changes. - The Tools-menu Create App/Module dialogs (
actions/create/*) now embed the same panel (TiNewProjectPanel(fixedType=…)) and delegate to the same scaffolder (showOpenHint=trueshows the "open via File | Open" dialog afterwards). - Flag-validation risk (same class as §5):
--ios-code-base/--android-code-baseand thealloy newinvocation need one live run to confirm exact v8/SDK flag names. - Compile-risk watchpoints (verify on first build):
WebProjectTemplate.createPeer()signature,GeneratorPeerImplno-arg constructor, and the new-wizard chain API (RootNewProjectWizardStep/NewProjectWizardBaseStep/NewProjectWizardChainStep.Companion.nextStep/GeneratorNewProjectWizardBuilderAdapter). All standard platform APIs, but they drift between majors.
Not "unknowns" anymore — each is "run it once, paste the error, trim a flag":
- Confirm Refresh populates in the running IDE after rebuild+reinstall (logic validated vs real data, but not seen live).
- Other v8 CLI commands may reject flags (same class of fix as
info):build:--liveview,--log-level,--deploy-type,--debug-host(inrun/TiBuildCommandBuilder).sdk select: v8 may have droppedselect(lists install/uninstall only) —sdk/TiSdkManager.create:-t,--force(actions/create/*).package: dist flags (run/TiPackageCommandBuilder).
- Debugger never run against a real simulator/device (source-map fidelity, iOS needs
ios-webkit-debug-proxy).
- Structured TSS grammar/PSI for rename/find-usages of rules (go-to-definition already works).
- More test coverage (only
TiInfoParser+TssLexerare unit-tested).
cd "/Users/AbdullahFaqeir/dev/TiDev/JetBrains Plugin/titanium-jetbrains"
./gradlew test buildPlugin # -> build/distributions/Titanium-0.1.0.zip
./gradlew runIde # sandbox IDE with plugin loadedInstall: Settings → Plugins → ⚙ → Install Plugin from Disk → the ZIP → Restart.
Commit (from Mac terminal — sandbox can't): rm -f .git/index.lock && git add -A && git commit && git push.
- The assistant's shell is an isolated Linux sandbox, NOT the user's Mac. It cannot run the user's
ti, and the sandbox npm registry blocks thetitaniumpackage (403). To inspect real CLI output, the user runs the command and saves output into the project folder (mounted) for the assistant to read. - The assistant cannot compile (no IntelliJ SDK/gradle in sandbox); it grep-verifies wiring and
reasons through APIs. The user runs
./gradlewand pastes results. - Editing files in the connected folder requires reading them first in-session.
- Highest-risk APIs to watch on builds:
ComboBoxAction.createPopupActionGroup(deprecation, suppressed),RunContentExecutor,AbstractDocumentationProvider, XDebuggerXValue/evaluator, VFS writes in intentions.
"Continuing the Titanium JetBrains plugin (see HANDOFF.md in the repo). I've rebuilt and reinstalled. Refresh [does/doesn't] show devices now. When I run a Build it [works / prints: ]. Let's fix the remaining v8 CLI flag issues."