homegraph 1.6.2 → 1.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/extraction/languages/arkts.js +139 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,16 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
## [1.6.3] - 2026-10-22
|
|
14
|
+
|
|
15
|
+
### Improvements
|
|
16
|
+
|
|
17
|
+
- Release workflow jobs are split so a failed stage can be re-run alone: unit tests, CHANGELOG prepare, GitHub Release, npm publish, long registry verify, then OHOS API db packages.
|
|
18
|
+
|
|
19
|
+
### Fixes
|
|
20
|
+
|
|
21
|
+
- ArkTS: cross-file `imports` and `extends`/`implements` edges are no longer dropped during per-file persist. They ride the same `crossFileEdges` path as calls. Built-in ArkUI decorators (`@State`, `@Builder`, …) are not fuzzy-matched onto unrelated same-named symbols (Spec 0059).
|
|
22
|
+
|
|
13
23
|
## [1.6.2] - 2026-10-19
|
|
14
24
|
|
|
15
25
|
### New Features
|
|
@@ -305,3 +315,4 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
305
315
|
[1.6.0]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.6.0
|
|
306
316
|
[1.6.1]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.6.1
|
|
307
317
|
[1.6.2]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.6.2
|
|
318
|
+
[1.6.3]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.6.3
|
|
@@ -2026,6 +2026,47 @@ function filesHaveArkUiEntries(files) {
|
|
|
2026
2026
|
// ArkUI ViewTree — component tree, @Prop/@Link transfer, event bindings
|
|
2027
2027
|
// =============================================================================
|
|
2028
2028
|
const VIEWTREE_CALLBACK_ATTRS = new Set(arkanalyzer_1.CALLBACK_METHOD_NAME);
|
|
2029
|
+
/**
|
|
2030
|
+
* Framework decorators with no project-local definition. Emitting them as
|
|
2031
|
+
* unresolved `decorates` refs lets name-matcher bind @State → enum State, etc.
|
|
2032
|
+
*/
|
|
2033
|
+
const ARKUI_BUILTIN_DECORATORS = new Set([
|
|
2034
|
+
'State',
|
|
2035
|
+
'Prop',
|
|
2036
|
+
'Link',
|
|
2037
|
+
'Provide',
|
|
2038
|
+
'Consume',
|
|
2039
|
+
'Watch',
|
|
2040
|
+
'Builder',
|
|
2041
|
+
'BuilderParam',
|
|
2042
|
+
'Styles',
|
|
2043
|
+
'Extend',
|
|
2044
|
+
'AnimatableExtend',
|
|
2045
|
+
'Component',
|
|
2046
|
+
'ComponentV2',
|
|
2047
|
+
'Entry',
|
|
2048
|
+
'CustomDialog',
|
|
2049
|
+
'Observed',
|
|
2050
|
+
'ObservedV2',
|
|
2051
|
+
'ObjectLink',
|
|
2052
|
+
'LocalStorageLink',
|
|
2053
|
+
'LocalStorageProp',
|
|
2054
|
+
'StorageLink',
|
|
2055
|
+
'StorageProp',
|
|
2056
|
+
'Track',
|
|
2057
|
+
'Require',
|
|
2058
|
+
'Once',
|
|
2059
|
+
'Reusable',
|
|
2060
|
+
'Concurrent',
|
|
2061
|
+
'Sendable',
|
|
2062
|
+
'Local',
|
|
2063
|
+
'Param',
|
|
2064
|
+
'Event',
|
|
2065
|
+
'Monitor',
|
|
2066
|
+
'Computed',
|
|
2067
|
+
'Trace',
|
|
2068
|
+
'Type',
|
|
2069
|
+
]);
|
|
2029
2070
|
/** State decorator kinds on a field (@State, @Prop, @Link, …) from arkanalyzer. */
|
|
2030
2071
|
function stateDecoratorKinds(field) {
|
|
2031
2072
|
const decs = field.getStateDecorators?.();
|
|
@@ -2727,6 +2768,11 @@ class ArkTSAdapter {
|
|
|
2727
2768
|
continue;
|
|
2728
2769
|
if (!this.scanned.has(rel) || !isArkAnalyzerSourcePath(rel))
|
|
2729
2770
|
continue;
|
|
2771
|
+
// Already indexed (usually streamed to DB). Re-running indexScannedFile
|
|
2772
|
+
// would hit addNode's nodeIds short-circuit and leave an empty shell;
|
|
2773
|
+
// live IR rebind is handled by bindLiveMapsFromResident.
|
|
2774
|
+
if (this.nodeIds.has(`file:${rel}`))
|
|
2775
|
+
continue;
|
|
2730
2776
|
this.indexScannedFile(arkFile);
|
|
2731
2777
|
if (this.fileResults.has(rel))
|
|
2732
2778
|
seeded.push(rel);
|
|
@@ -3279,6 +3325,20 @@ class ArkTSAdapter {
|
|
|
3279
3325
|
const result = this.fileResults.get(relativePath);
|
|
3280
3326
|
return result?.nodes.some((n) => n.id === nodeId) ?? false;
|
|
3281
3327
|
}
|
|
3328
|
+
/**
|
|
3329
|
+
* Same-file edges stay on the file's ExtractionResult (persistFileResult FK
|
|
3330
|
+
* filter). Cross-file edges go to crossFileEdges and are inserted after all
|
|
3331
|
+
* modules persist — do not require nodeIds.has(target) at emit time (target
|
|
3332
|
+
* may be indexed later in the same batch).
|
|
3333
|
+
*/
|
|
3334
|
+
addMaybeCrossFileEdge(result, callerFile, edge) {
|
|
3335
|
+
if (this.nodeInFile(edge.target, callerFile)) {
|
|
3336
|
+
result.edges.push(edge);
|
|
3337
|
+
}
|
|
3338
|
+
else {
|
|
3339
|
+
this.crossFileEdges.push(edge);
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3282
3342
|
ensureFileResult(relativePath, lineCount) {
|
|
3283
3343
|
let result = this.fileResults.get(relativePath);
|
|
3284
3344
|
if (!result) {
|
|
@@ -3431,6 +3491,10 @@ class ArkTSAdapter {
|
|
|
3431
3491
|
const kind = dec.getKind();
|
|
3432
3492
|
if (!kind)
|
|
3433
3493
|
continue;
|
|
3494
|
+
// Built-in ArkUI/ArkTS decorators have no project definition; name-match
|
|
3495
|
+
// would falsely link @State → enum State, @Builder → class Builder, etc.
|
|
3496
|
+
if (ARKUI_BUILTIN_DECORATORS.has(kind))
|
|
3497
|
+
continue;
|
|
3434
3498
|
result.unresolvedReferences.push({
|
|
3435
3499
|
fromNodeId,
|
|
3436
3500
|
referenceName: kind,
|
|
@@ -3529,17 +3593,62 @@ class ArkTSAdapter {
|
|
|
3529
3593
|
if (superName) {
|
|
3530
3594
|
const superCls = cls.getHeritageClass(superName);
|
|
3531
3595
|
if (superCls && !superCls.isDefaultArkClass()) {
|
|
3532
|
-
const superId = this.classToId.get(superCls);
|
|
3596
|
+
const superId = this.classToId.get(superCls) ?? this.resolveClassNodeId(superCls);
|
|
3597
|
+
const edgeKind = superCls.getCategory() === CLASS_CATEGORY.INTERFACE ? 'implements' : 'extends';
|
|
3533
3598
|
if (superId) {
|
|
3534
|
-
|
|
3535
|
-
|
|
3599
|
+
this.addMaybeCrossFileEdge(result, relativePath, arkEdge(classNode.id, superId, edgeKind));
|
|
3600
|
+
}
|
|
3601
|
+
else {
|
|
3602
|
+
const simple = superName.includes('.') ? superName.split('.').pop() : superName;
|
|
3603
|
+
if (simple && simple !== 'Object') {
|
|
3604
|
+
result.unresolvedReferences.push({
|
|
3605
|
+
fromNodeId: classNode.id,
|
|
3606
|
+
referenceName: simple,
|
|
3607
|
+
referenceKind: edgeKind,
|
|
3608
|
+
line,
|
|
3609
|
+
column: col,
|
|
3610
|
+
filePath: relativePath,
|
|
3611
|
+
language,
|
|
3612
|
+
});
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
}
|
|
3616
|
+
else if (superName && superName !== 'Object') {
|
|
3617
|
+
const simple = superName.includes('.') ? superName.split('.').pop() : superName;
|
|
3618
|
+
if (simple) {
|
|
3619
|
+
result.unresolvedReferences.push({
|
|
3620
|
+
fromNodeId: classNode.id,
|
|
3621
|
+
referenceName: simple,
|
|
3622
|
+
referenceKind: 'extends',
|
|
3623
|
+
line,
|
|
3624
|
+
column: col,
|
|
3625
|
+
filePath: relativePath,
|
|
3626
|
+
language,
|
|
3627
|
+
});
|
|
3536
3628
|
}
|
|
3537
3629
|
}
|
|
3538
3630
|
}
|
|
3539
3631
|
for (const ifaceName of cls.getImplementedInterfaceNames()) {
|
|
3540
3632
|
const iface = cls.getImplementedInterface(ifaceName);
|
|
3541
|
-
|
|
3542
|
-
|
|
3633
|
+
const ifaceId = iface
|
|
3634
|
+
? (this.classToId.get(iface) ?? this.resolveClassNodeId(iface))
|
|
3635
|
+
: null;
|
|
3636
|
+
if (ifaceId) {
|
|
3637
|
+
this.addMaybeCrossFileEdge(result, relativePath, arkEdge(classNode.id, ifaceId, 'implements'));
|
|
3638
|
+
}
|
|
3639
|
+
else if (ifaceName) {
|
|
3640
|
+
const simple = ifaceName.includes('.') ? ifaceName.split('.').pop() : ifaceName;
|
|
3641
|
+
if (simple) {
|
|
3642
|
+
result.unresolvedReferences.push({
|
|
3643
|
+
fromNodeId: classNode.id,
|
|
3644
|
+
referenceName: simple,
|
|
3645
|
+
referenceKind: 'implements',
|
|
3646
|
+
line,
|
|
3647
|
+
column: col,
|
|
3648
|
+
filePath: relativePath,
|
|
3649
|
+
language,
|
|
3650
|
+
});
|
|
3651
|
+
}
|
|
3543
3652
|
}
|
|
3544
3653
|
}
|
|
3545
3654
|
for (const method of cls.getMethods(true)) {
|
|
@@ -4017,12 +4126,34 @@ class ArkTSAdapter {
|
|
|
4017
4126
|
const targetFile = exportInfo.getDeclaringArkFile();
|
|
4018
4127
|
if (targetFile) {
|
|
4019
4128
|
const targetRel = this.normalizeRelPath(targetFile.getFilePath());
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4129
|
+
if (targetRel) {
|
|
4130
|
+
const targetFileId = `file:${targetRel}`;
|
|
4131
|
+
this.addMaybeCrossFileEdge(result, relativePath, arkEdge(importNode.id, targetFileId, 'imports', {
|
|
4023
4132
|
metadata: { synthesizedBy: 'arkanalyzer', module: modulePath },
|
|
4024
4133
|
}));
|
|
4025
4134
|
}
|
|
4135
|
+
else if (modulePath) {
|
|
4136
|
+
result.unresolvedReferences.push({
|
|
4137
|
+
fromNodeId: importNode.id,
|
|
4138
|
+
referenceName: modulePath,
|
|
4139
|
+
referenceKind: 'imports',
|
|
4140
|
+
line,
|
|
4141
|
+
column: 0,
|
|
4142
|
+
filePath: relativePath,
|
|
4143
|
+
language,
|
|
4144
|
+
});
|
|
4145
|
+
}
|
|
4146
|
+
}
|
|
4147
|
+
else if (modulePath) {
|
|
4148
|
+
result.unresolvedReferences.push({
|
|
4149
|
+
fromNodeId: importNode.id,
|
|
4150
|
+
referenceName: modulePath,
|
|
4151
|
+
referenceKind: 'imports',
|
|
4152
|
+
line,
|
|
4153
|
+
column: 0,
|
|
4154
|
+
filePath: relativePath,
|
|
4155
|
+
language,
|
|
4156
|
+
});
|
|
4026
4157
|
}
|
|
4027
4158
|
}
|
|
4028
4159
|
else if (modulePath) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homegraph",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"description": "Supercharge AI coding agents with semantic code intelligence — surgical context, fewer tool calls, faster answers. 100% local.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|