feat(extraction): add ArkTS language support with ArkUI dispatch bridges (#396, #512, #890 via #648) (#1186)
Adds ArkTS (.ets, HarmonyOS/OpenHarmony) as a first-class language: full TypeScript-grade extraction via the harmony-contrib tree-sitter grammar (MIT, vendored byte-identical from the tree-sitter-arkts 0.2.0 npm tarball), plus the ArkUI constructs that make HarmonyOS apps traceable: - @Component/@ComponentV2 structs with decorators from both grammar positions; members extract as class members with qualified names. - build() component trees: child instantiation edges via arkui_component_expression, no synthesizer needed. - Attribute chains emitted dot-prefixed and resolved ONLY against @Extend/@Styles/@AnimatableExtend/@Builder helpers (unique-or-drop) — bare-name fallthrough produced 36,840 wrong edges (17% of calls) on the OpenHarmony samples monorepo. All four grammar chain shapes handled, including the detached-chain forms. - .onClick(this.handler) method-reference bindings. - ohpm workspace modules: bare imports follow oh-package.json5 file: deps (ambiguous names dropped), honoring each module's main entry — which also lets .ts consumers resolve .ets modules. - ArkUI dynamic-dispatch bridges, all provenance:'heuristic' with wiring-site metadata: assignment-gated state->build() re-render (V1 @State family + V2 @Local/@Provider/@Consumer), @ohos.events.emitter emit->subscriber pairing on static event keys (numeric ids same-file, named constants same-module, fan-out capped), and router.pushUrl literal urls -> the target page's @Entry struct. - $r/$rawfile resource intrinsics treated as built-ins; arkts joins the web language family, value-reference edges, re-export chase, and the other TS-applicable gates. Also ships a language-agnostic index-completeness guard: indexAll stamps index_state (indexing -> complete/partial/failed), reconciles discovered vs accounted files (a loaded run silently dropped 37 files), and codegraph status surfaces truncated/partial indexes in human and --json output. Validated on HarmoneyOpenEye (82 files), CoolMallArkTS (528, modular ohpm + ArkUI V2), and openharmony/applications_app_samples (11,693 files, 202,890 nodes stable across re-index, attribute false-positive audit 36,840 -> 588 residual all-plausible). Supersedes PRs #656 and #988 with credit — both informed this implementation. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
f8cdbe3c67
commit
99152212a9
+18
-3
@@ -543,7 +543,7 @@ export class ReferenceResolver {
|
||||
// `.ts` index barrel and silently break the chain (#629). Re-key
|
||||
// the parse on the barrel's extension so the chase works no matter
|
||||
// what kind of file imports through it.
|
||||
const isJsFamily = /\.(?:d\.ts|[cm]?tsx?|[cm]?jsx?)$/i.test(filePath);
|
||||
const isJsFamily = /\.(?:d\.ts|[cm]?tsx?|[cm]?jsx?|ets)$/i.test(filePath);
|
||||
const reExports = extractReExports(content, isJsFamily ? 'typescript' : language);
|
||||
this.reExportCache.set(filePath, reExports);
|
||||
return reExports;
|
||||
@@ -744,8 +744,15 @@ export class ReferenceResolver {
|
||||
// from './barrel'` where the barrel has `export { signIn as login }
|
||||
// from './auth'`) intentionally call a name that has no
|
||||
// declaration anywhere — only the renamed upstream symbol does.
|
||||
// ArkTS chained-attribute refs carry a leading dot (`.titleStyle`) that
|
||||
// routes them to the decorator-gated matcher; the symbol itself is
|
||||
// indexed under the bare name, so the existence check strips the dot.
|
||||
const existenceName =
|
||||
ref.language === 'arkts' && ref.referenceName.startsWith('.')
|
||||
? ref.referenceName.slice(1)
|
||||
: ref.referenceName;
|
||||
if (
|
||||
!this.hasAnyPossibleMatch(ref.referenceName) &&
|
||||
!this.hasAnyPossibleMatch(existenceName) &&
|
||||
!this.matchesAnyImport(ref) &&
|
||||
!this.frameworks.some((f) => f.claimsReference?.(ref.referenceName))
|
||||
) {
|
||||
@@ -1169,13 +1176,21 @@ export class ReferenceResolver {
|
||||
private isBuiltInOrExternal(ref: UnresolvedRef): boolean {
|
||||
const name = ref.referenceName;
|
||||
const isJsTs = ref.language === 'typescript' || ref.language === 'javascript'
|
||||
|| ref.language === 'tsx' || ref.language === 'jsx';
|
||||
|| ref.language === 'tsx' || ref.language === 'jsx' || ref.language === 'arkts';
|
||||
|
||||
// JavaScript/TypeScript built-ins
|
||||
if (isJsTs && JS_BUILT_INS.has(name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ArkTS resource-reference intrinsics — `$r('app.string.x')` /
|
||||
// `$rawfile('x.png')` are framework-provided and appear dozens of times
|
||||
// per UI file; without this they can resolve to a stray same-named
|
||||
// symbol (e.g. a checked-in hvigor wrapper's `$r`).
|
||||
if (ref.language === 'arkts' && (name === '$r' || name === '$rawfile')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Common JS/TS library calls (console.log, Math.floor, JSON.parse)
|
||||
if (isJsTs && (name.startsWith('console.') || name.startsWith('Math.') || name.startsWith('JSON.'))) {
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user