feat: ArkTS (.ets) and HarmonyOS project config support#339
Open
davien wants to merge 3 commits intosafishamsi:v4from
Open
feat: ArkTS (.ets) and HarmonyOS project config support#339davien wants to merge 3 commits intosafishamsi:v4from
davien wants to merge 3 commits intosafishamsi:v4from
Conversation
ArkTS is HarmonyOS's UI language — a strict superset of TypeScript with two non-TS additions: the `struct` keyword for UI components, and a set of HarmonyOS-specific decorators (@Component/@ComponentV2, @State/@Local, @prop, @link, @provide, @consume, @watch, @builder, @Styles, etc.). Implementation: - detect.py: register '.ets' in CODE_EXTENSIONS - extract.py: - _extract_generic gains a source_override parameter so callers can inject pre-processed bytes while keeping metadata tied to the real file (preserves node IDs and source_location line numbers) - extract_ets() preprocesses `struct` → `class ` (same byte length, line numbers preserved) then runs the standard TypeScript extractor - _enrich_arkts() post-processes the original source to recognize ArkTS decorators and emit two new node types: • arkts_decorator — @Component/@Entry/etc. wired via `decorates` edge to the struct they annotate • arkts_state — @State/@Local/@Prop/etc. fields, wired via `contains_state` edge to the file node - Handles multi-line decorator args like @entry({ routeName: "..." }) via paren-depth tracking - Covers both V1 (@component, @State, @observed) and V2 (@ComponentV2, @Local, @ObservedV2, @trace, @param, @event, @monitor, @computed) decorator families - Dispatch registered for '.ets' in extract() Tests: - tests/fixtures/sample.ets exercising both decorator flavors, struct, regular class, multi-line decorator args, and state fields - 10 new tests in test_languages.py covering parsing, decorators, state nodes, no dangling edges, line-number preservation Verified on a real HarmonyOS project (ZKJAIRTCDemo): EnvCheckPage.ets → 22 nodes / 42 edges, @entry + @ComponentV2 recognized, 7 @trace state fields captured. Full test suite: 443 passed, 0 regressions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…composition, resources, provide/consume, storage bindings Extends extract_ets() beyond decorator-name recognition to actual state- management semantics. Multi-pass enrichment over the original source text: Pass 1 — Decorators + fields + methods: • @Component/@ComponentV2 struct → upgraded to node_type "arkts_component" • @ObservedV2/@observed class → arkts_observed_v2 / arkts_observed • Lifecycle methods (aboutToAppear, onPageShow, onBackPress, onCreate, onWindowStageCreate, etc.) → arkts_lifecycle + `has_lifecycle` edge • @trace field inside @ObservedV2 class → `observes` edge from class • @watch('methodName') (both multi-line and single-line layouts) → arkts_watch node + `watches` edge to target method • Decorated getters `@Computed get total(): T {...}` now recognized Pass 2 — build() UI composition: • Finds each struct's build() method body via brace counting • Collects Capitalized-identifier + '(' calls as child UI components • Emits arkts_ui_component_usage nodes + `uses_component` edges • Parent components → built-in containers (Column, Row, NavDestination, List, Scroll, ForEach, ...) + user-defined components (TitleBar, ...) Pass 3 — resource references: • $r("app.xxx.yyy") / $rawfile("...") → arkts_resource nodes • struct → resource via `references_resource` edges • Cross-file resource nodes are shared by key (same $r call in multiple components merges into one node) Pass 4 — @Provide/@consume cross-component flow: • @provide('key') / @Provider('key') → `provides` edge to arkts_provide_key • @consume('key') / @consumer('key') → `consumes` edge to same key • Synthetic key nodes automatically join parent/child producers+consumers Pass 5 — Storage bindings: • @storagelink('key') / @StorageProp('key') → arkts_app_storage_key + `storage_binds` edge (AppStorage global singletons) • @LocalStorageLink / @LocalStorageProp → arkts_local_storage_key + `local_storage_binds` edge (LocalStorage per-component) Pass 6 — @monitor targets: • @monitor('checkState', 'model.titleName') → one arkts_monitor_target per string arg + `monitors` edges Support helpers: • _find_struct_ranges: brace-balanced struct/class scanner with string literal awareness (handles '...' "..." `...` without mis-counting) • _containing_struct: line→struct lookup for contextual edges New decorators covered: Provider, Consumer (V2 equivalents of Provide/Consume). Fixture expanded to exercise the full surface: both V1 and V2 decorators, lifecycle methods, @watch on a field, @monitor multi-arg, @computed getter, @Provider+@consume pair, @storagelink + @LocalStorageProp, nested UI tree. Tests: 22 passing (was 10), 455 total passing, 0 regressions. Real-world verification on ZKJAIRTCDemo/EnvCheckPage.ets: 60 nodes / 87 edges (was 22/42) 27 $r() resource refs, 10 UI components, 5 observes edges, 2 lifecycle methods, 2 @ObservedV2 classes, 1 @entry+@ComponentV2 pair. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…5 / build-profile.json5
Adds structured extraction of HarmonyOS project configuration files so the
knowledge graph captures real project-level semantics: abilities, permissions,
routes, HAR dependencies, build profile.
detect.py:
- New HARMONY_CONFIG_FILES set with exact filenames
- classify_file() routes these to FileType.CODE so they enter extraction
extract.py:
- _parse_json5(): minimal JSON5 parser (strips // comments, /* */ block
comments, trailing commas) — no external dependency
- extract_harmony_config(): dispatch-by-filename handler
Per-file handlers:
module.json5 →
• harmony_module (name, type, deviceTypes)
• harmony_ability per entry in abilities[] + `declares_ability` edge
• harmony_extension_ability + `declares_extension_ability` edge
• harmony_permission per requestPermissions[] + `requires_permission` edge
router_map.json →
• harmony_route (name, pageSourceFile, buildFunction)
• `route_maps_to` INFERRED edge from route → page component (ID inferred
from pageSourceFile stem + route name)
oh-package.json5 →
• harmony_package (name, version, main)
• harmony_dependency per dep + `depends_on` / `dev_depends_on` /
`dynamic_depends_on` edges (distinguishing dep kinds)
build-profile.json5 →
• harmony_build_profile + `configures_module` edges to declared modules
extract() dispatch updated: filename-based lookup checked before suffix
lookup (same pattern as .blade.php).
Fixtures: module.json5, router_map.json, oh-package.json5 exercising
abilities, permissions, multiple routes, three dependency kinds, and
both JSON5 features (// comments, trailing commas).
Tests: 7 new harmony_* cases + comment/trailing-comma tolerance +
classify_file routing check. 462 total passing, 0 regressions.
Real-world verification on ZKJAIRTCDemo:
router_map.json → 6 routes + 6 route_maps_to edges
oh-package.json5 → 5 HAR deps (zrtc, msxf_face, msxf_ocr, axios, librecorder.so)
module.json5 → module:zkj_ai_record (HAR type, no abilities as expected)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ec38381 to
ac43948
Compare
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.
Adds full first-class support for HarmonyOS development.
ArkTS language (
.ets)ArkTS is HarmonyOS's UI language — a strict superset of TypeScript. The only non-TS syntactic feature is the
structkeyword for UI components; decorators are already valid TS (experimentalDecorators). We preprocessstruct→class(same byte length, line numbers preserved) and then enrich the extraction with HarmonyOS-specific semantics.Decorators with real semantics (not just names)
decoratesedges, struct upgraded toarkts_component):@Component,@ComponentV2,@Entry,@Preview,@CustomDialog,@Reusable,@ReusableV2observesedges):@Observed,@ObservedV2+@Tracefield bindingcontains_stateedges, distinctarkts_statenode type per field):@State,@Prop,@Link,@Local,@Param,@Provide/@Consume,@Provider/@Consumer,@StorageLink,@StorageProp,@LocalStorageLink,@LocalStorageProp,@Computed,@Event,@Once,@Watch,@Monitor,@Require,@BuilderParam,@ObjectLink@Builder,@Styles,@Extend,@AnimatableExtend,@ConcurrentSemantic edges beyond decorator names
watchesedge to the target method in the same structmonitorsedge per target expressionarkts_provide_keynodes that producers and consumers join on — lets you query "who provides key X and who consumes it"arkts_app_storage_keynode +storage_bindsedgearkts_local_storage_keynode +local_storage_bindsedgeuses_componentedges from parent struct to every capitalized-identifier-called-as-function inside the build tree (Column(),NavDestination(),ForEach(), user components, etc.)arkts_resourcenodes +references_resourceedges, shared by key across componentsaboutToAppear,aboutToDisappear,onPageShow,onPageHide,onBackPress,onCreate,onWindowStageCreate, etc.) → taggedarkts_lifecycle+has_lifecycleedge@Entry({ routeName: ... })) handled via paren-depth trackingHelpers
_find_struct_ranges: brace-balanced struct/class scanner with string-literal awareness (handles'...',"...",`...`without miscounting)_containing_struct: line → struct lookup so all enrichment edges attach to the right parentHarmonyOS project config files
Adds structured extraction of project-level config that previously was silently skipped:
module.json5harmony_module+harmony_ability+harmony_extension_ability+harmony_permission, withdeclares_ability,declares_extension_ability,requires_permissionedgesrouter_map.jsonharmony_routeper entry + INFERREDroute_maps_toedge to the page component (ID inferred frompageSourceFilestem + route name)oh-package.json5harmony_package+harmony_dependency, withdepends_on/dev_depends_on/dynamic_depends_ondistinguishing the three dep kindsbuild-profile.json5harmony_build_profile+configures_moduleedges_parse_json5()helper — strips//comments,/* */block comments, and trailing commas, then hands tojson.loads. No new dependency.extract()(same pattern already used for.blade.php).detect.pyroutes these files toFileType.CODEso they enter the normal extraction pipeline.Tests
29 new tests covering ArkTS language (10), V1+V2 semantic enrichment (12), and HarmonyOS config files (7). 462 total passing, zero regressions.
Verified on a real HarmonyOS RTC SDK (ZKJAIRTCDemo):
EnvCheckPage.ets→ 60 nodes / 87 edges (27 resources, 10 UI components, 5observesedges, 2@ObservedV2classes)router_map.json→ 6 routes + 6route_maps_toedgesoh-package.json5→ 5 HAR dependencies extractedMigration / compatibility
_extract_genericgains an optionalsource_overrideparameter soextract_etscan inject preprocessed bytes while keeping metadata tied to the real file. All other callers unaffected..etsprojects.Happy to split into smaller PRs or adjust the API (e.g. factoring
_enrich_arktsinto a separate module) if preferred.