@hmos-library-adapter/fast 0.0.17-beta.0 → 0.0.17-beta.1
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/node_modules/@hmos-library-adapter/executer/README.md +2 -2
- package/node_modules/@hmos-library-adapter/executer/shared/skill-map.json +5 -1
- package/node_modules/@hmos-library-adapter/executer/shared/skills/arkts-rules/SKILL.md +400 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/CHANGELOG.md +1391 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/COMPATIBILITY.md +53 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/README.md +123 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/SKILL.md +48 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/agents/upgrade-assess-change.md +37 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/agents/upgrade-fix-file.md +23 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/package.json +19 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/26.0.0/beta1-changes-for-all-apps.md +1793 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/26.0.0/beta1-ux-style-and-effect-changes.md +288 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/26.0.0/beta2-changes-for-all-apps.md +148 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/26.0.0/release-changes-for-all-apps.md +662 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.1(13)/beta3-os-api-behavior-changes.md +652 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.1(13)/beta3-ux-style-and-effect-changes.md +222 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.1(13)/release-os-api-behavior-changes.md +444 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.1(13)/release-ux-style-and-effect-changes.md +221 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.2(14)/os-api-behavior-changes.md +1767 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.2(14)/ux-style-and-effect-changes.md +134 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.3(15)/beta1-os-api-behavior-changes.md +430 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.3(15)/beta1-ux-style-and-effect-changes.md +49 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.3(15)/beta2-os-api-behavior-changes.md +240 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.3(15)/beta2-ux-style-and-effect-changes.md +90 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.0.3(15)/release-os-api-behavior-changes.md +69 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.1.0(18)/os-api-behavior-changes.md +1294 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/5.1.0(18)/ux-style-and-effect-changes.md +147 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/6.0.0(20)/beta1-os-api-behavior-changes.md +1019 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/6.0.0(20)/beta1-ux-style-and-effect-changes.md +153 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/6.0.0(20)/beta2-os-api-behavior-changes.md +662 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/6.0.0(20)/beta2-ux-style-and-effect-changes.md +78 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/6.0.0(20)/beta3-os-api-behavior-changes.md +167 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/6.0.0(20)/beta5-os-api-behavior-changes.md +52 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs/6.1.0(23)/changes-for-all-apps.md +397 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/changelogs-index.json +883 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/common/arkts-coding-standards.md +53 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/common/compatibility.md +207 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/common/native-adaptation.md +21 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/common/runtime-functional-tests.md +62 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/common/sdk-versions.md +77 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/common/troubleshooting.md +54 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/common/verification.md +79 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/common/workflow-scan.md +41 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/deprecated/context-migration.md +274 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/deprecated/deprecated-api-adaptation.md +157 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/deprecated/deprecated-api-examples.md +219 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/toolchain/hvigor.md +50 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/upgrade/har-upgrade.md +60 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/upgrade/scanner-missed-cases.md +171 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/upgrade/upgrade-compatibility.md +112 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/upgrade/upgrade-examples.md +289 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/references/upgrade/upgrade-workflow.md +122 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/references/generate-behavior-policy.mjs +96 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/references/references.mjs +9 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/regression/compare-deprecated.mjs +57 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/regression/compare-golden.mjs +130 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/regression/regress-deprecated.mjs +120 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/test/behavior-catalog-generation.test.mjs +59 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/test/behavior-local-sources.test.mjs +44 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/test/changelog-index.test.mjs +66 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/test/compare-golden.test.mjs +103 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/test/fixtures/behavior/local-sources.csv +5 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/test/references.test.mjs +16 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/test/skill-content.test.mjs +139 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/test/skill-frontmatter.test.mjs +11 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/test/test-suite.test.mjs +65 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/validation/skill-content.mjs +125 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/validation/skill-frontmatter.mjs +6 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/maintenance/validation/validate-skill.mjs +57 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/CHANGELOG.md +506 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/GOLDEN_VALIDATION.md +42 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/README.md +137 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/behavior/behavior-policy.mjs +117 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/behavior/upgrade-coverage.mjs +29 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/bin/deveco-worker-compat.cjs +21 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/bin/harmony-api-scan.mjs +17 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/core/cli.mjs +416 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/core/deveco.mjs +348 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/core/project.mjs +81 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/core/rules.mjs +425 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/core/runtime-identity.mjs +23 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/core/scan-runner.mjs +521 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/core/sdk-deprecations.mjs +204 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/data/behavior-change-policy.json +4378 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/deprecated/arkts-deprecations.mjs +363 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/deprecated/build-log.mjs +72 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/native/native.mjs +95 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/package.json +16 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/batch-layout.test.mjs +94 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/behavior-policy.test.mjs +75 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/build-log.test.mjs +69 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/cli.test.mjs +102 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/csv.test.mjs +35 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/deprecations.test.mjs +283 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/deveco.test.mjs +262 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/helpers/scan-batch.mjs +10 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/native.test.mjs +108 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/project.test.mjs +42 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/rules.test.mjs +190 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/runtime-identity.test.mjs +53 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/scan-mode.test.mjs +38 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/scan-runner.test.mjs +481 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/scan-scope.test.mjs +110 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/source-inputs.test.mjs +64 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/scanner/test/upgrade.test.mjs +164 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/format/args.mjs +66 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/format/csv.mjs +85 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/format/json5.mjs +92 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/format/upgrade-results.mjs +45 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/format/zip.mjs +87 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/io/fs-utils.mjs +60 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/artifact-layout.mjs +74 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/changelog-index.mjs +29 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/deveco-version.mjs +40 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/document-links.mjs +30 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/errors.mjs +41 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/fs.mjs +72 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/paths.mjs +34 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/process.mjs +154 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/scan-mode.mjs +7 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/scan-statistics.mjs +7 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/scan-version-catalog.json +43 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/scan-versions.mjs +51 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/sdk-layout.mjs +27 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/source-scope.mjs +108 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/source-types.mjs +7 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/platform/version.mjs +76 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/test/deveco-version.test.mjs +50 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/test/document-links.test.mjs +13 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/test/errors.test.mjs +40 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/test/fs-utils.test.mjs +31 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/test/platform-paths.test.mjs +19 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/test/process-utils.test.mjs +68 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/test/scan-versions.test.mjs +26 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/test/sdk-version.test.mjs +17 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/shared/test/upgrade-results.test.mjs +140 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/scripts/test-suite.mjs +29 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/templates/deprecated-report.md +86 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/templates/progress.md +150 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/templates/results.md +110 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/templates/upgrade-report.md +105 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/templates/upgrade-spec.md +58 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-api-upgrade-adapter/templates/upgrade-test-report.md +47 -0
- package/node_modules/@hmos-library-adapter/executer/shared/skills/harmonyos-knowledge/SKILL.md +70 -0
- package/node_modules/@hmos-library-adapter/executer/src/config.js +3 -4
- package/node_modules/@hmos-library-adapter/executer/src/doctor.js +1 -1
- package/node_modules/@hmos-library-adapter/executer/src/install.js +1 -1
- package/node_modules/@hmos-library-adapter/executer/src/paths.js +4 -4
- package/package.json +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
4
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { classifyDeprecatedFindings, loadBehaviorPolicy, validateBehaviorPolicySources } from '../behavior/behavior-policy.mjs';
|
|
8
|
+
import { sha256 } from '../../shared/io/fs-utils.mjs';
|
|
9
|
+
|
|
10
|
+
const scannerRoot = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
11
|
+
|
|
12
|
+
test('bundled policy catalog covers 188 reviewed API13+ changes and validates their actual sources', async () => {
|
|
13
|
+
const catalog = await loadBehaviorPolicy(path.join(scannerRoot, 'data', 'behavior-change-policy.json'));
|
|
14
|
+
assert.equal(catalog.entryCount, 188);
|
|
15
|
+
assert.ok(catalog.entries.every(entry => entry.apiLevel >= 13));
|
|
16
|
+
for (const entry of catalog.entries)
|
|
17
|
+
assert.equal(entry.policyId, `${entry.sourceAnchor || 'behavior'}-${sha256(entry.sourceReference).slice(0, 8)}`);
|
|
18
|
+
assert.equal(catalog.entries.filter(entry => entry.documentConclusion === '否').length, 34);
|
|
19
|
+
const sources = await validateBehaviorPolicySources(catalog, path.resolve(scannerRoot, '..', '..', 'references', 'changelogs'));
|
|
20
|
+
assert.equal(sources.entryCount, 188);
|
|
21
|
+
assert.ok(catalog.entries.every(entry => entry.actionType && entry.rationale !== undefined));
|
|
22
|
+
for (const title of ['notofonts三方件小语种字体升级变更', '内置文本的组件文本样式优化']) {
|
|
23
|
+
const entry = catalog.entries.find(item => item.title === title);
|
|
24
|
+
assert.equal(entry.actionType, 'RUNTIME_VALIDATION');
|
|
25
|
+
assert.equal(entry.detectionMode, 'PROJECT_WIDE');
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('behavior policy source hashes are stable across LF and CRLF checkouts', async t => {
|
|
30
|
+
const root = await mkdtemp(path.join(os.tmpdir(), 'behavior-policy-newlines-'));
|
|
31
|
+
t.after(() => rm(root, { recursive: true, force: true }));
|
|
32
|
+
const file = path.join(root, 'source.md');
|
|
33
|
+
const lf = '# Title\n\nBody\n';
|
|
34
|
+
const document = {
|
|
35
|
+
entries: [{ policyId: 'policy', sourceReference: 'source.md:1', sourceFileHash: sha256(lf) }],
|
|
36
|
+
counts: {},
|
|
37
|
+
};
|
|
38
|
+
await writeFile(file, lf.replaceAll('\n', '\r\n'));
|
|
39
|
+
const result = await validateBehaviorPolicySources(document, root);
|
|
40
|
+
assert.equal(result.status, 'COMPLETE');
|
|
41
|
+
assert.equal(result.sourceFileCount, 1);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('behavior policy validation distinguishes changed and missing source files', async t => {
|
|
45
|
+
const root = await mkdtemp(path.join(os.tmpdir(), 'behavior-policy-errors-'));
|
|
46
|
+
t.after(() => rm(root, { recursive: true, force: true }));
|
|
47
|
+
const file = path.join(root, 'source.md');
|
|
48
|
+
const document = {
|
|
49
|
+
entries: [{ policyId: 'policy', sourceReference: 'source.md:1', sourceFileHash: sha256('expected\n') }],
|
|
50
|
+
counts: {},
|
|
51
|
+
};
|
|
52
|
+
await writeFile(file, 'changed\r\n');
|
|
53
|
+
await assert.rejects(validateBehaviorPolicySources(document, root), error => {
|
|
54
|
+
assert.equal(error.details[0].reason, 'SOURCE_HASH_CHANGED');
|
|
55
|
+
return true;
|
|
56
|
+
});
|
|
57
|
+
await rm(file);
|
|
58
|
+
await assert.rejects(validateBehaviorPolicySources(document, root), error => {
|
|
59
|
+
assert.equal(error.details[0].reason, 'SOURCE_NOT_FOUND');
|
|
60
|
+
return true;
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('deprecated occurrences retain separate columns, original annotations and stable grouping', () => {
|
|
65
|
+
const findings = [1, 8].map(Column => ({
|
|
66
|
+
'Change Type': 'Deprecated API', 'Rule ID': 'sdk-old', 'Code Location': 'entry/A.ets:1',
|
|
67
|
+
occurrenceId: 'old-' + Column, Column, includedInCsv: true,
|
|
68
|
+
}));
|
|
69
|
+
const result = classifyDeprecatedFindings(findings);
|
|
70
|
+
assert.equal(result.actionGroups.length, 2);
|
|
71
|
+
assert.deepEqual(result.actionGroups.flatMap(group => group.occurrences.map(item => item.Column)).sort((a,b)=>a-b), [1,8]);
|
|
72
|
+
assert.ok(result.actionRows.every(row => row['Occurrence Count'] === 1 && row['Action Type'] === 'CODE_REVIEW_REQUIRED'));
|
|
73
|
+
assert.deepEqual(result.validationGroups, []); assert.deepEqual(result.validationRows, []);
|
|
74
|
+
assert.deepEqual(result.findings.map(item => item.occurrenceId), ['old-1','old-8']);
|
|
75
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, writeFile, rm } from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { parseDeprecatedBuildLog, importDeprecatedBuildLog } from '../deprecated/build-log.mjs';
|
|
7
|
+
import { sha256 } from '../../shared/io/fs-utils.mjs';
|
|
8
|
+
import { compareDeprecated } from '../../maintenance/regression/compare-deprecated.mjs';
|
|
9
|
+
|
|
10
|
+
const log = `WARN: ArkTS:WARN File: /baseline/entry/A.ets:2:4
|
|
11
|
+
'getContext' has been deprecated.
|
|
12
|
+
WARN: ArkTS:WARN File: /baseline/oh_modules/vendor/A.ets:3:5
|
|
13
|
+
'create' has been deprecated.
|
|
14
|
+
WARN: ArkTS:WARN File: /baseline/oh_modules/vendor/A.ets:3:5
|
|
15
|
+
'create' has been deprecated.
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
test('compiler warning parser preserves columns and deduplicates repeated messages', () => {
|
|
19
|
+
const parsed = parseDeprecatedBuildLog(log);
|
|
20
|
+
assert.equal(parsed.length, 2);
|
|
21
|
+
assert.equal(parsed[1].column, 5);
|
|
22
|
+
assert.equal(parseDeprecatedBuildLog("'create' has been deprecated.")[0].located, false);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('Windows logs and historical comparisons match case variants while rejecting other roots and tampering',async t=>{
|
|
26
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'windows-build-log-'));
|
|
27
|
+
t.after(()=>rm(root,{recursive:true,force:true}));
|
|
28
|
+
const logPath=path.join(root,'build.log'),evidencePath=path.join(root,'evidence.json'),scanJson=path.join(root,'scan.json');
|
|
29
|
+
const text="WARN: ArkTS:WARN File: d:\\harmony\\APP\\oh_modules\\vendor\\A.ets:3:5\n 'create' has been deprecated.\n";
|
|
30
|
+
const project={sourceSnapshot:'source',buildProfileHash:'profile',product:{name:'default'}};
|
|
31
|
+
const catalog={platform:'win32',snapshot:'sdk',coverage:{targetSdk:'26'},deprecatedEntries:[]};
|
|
32
|
+
const evidence={schemaVersion:1,projectRoot:'D:\\Harmony\\App',sourceSnapshot:'source',buildProfileHash:'profile',sdkSnapshot:'sdk',
|
|
33
|
+
targetSdk:'26',product:'default',logHash:sha256(text),nonIncremental:true,status:'PASSED'};
|
|
34
|
+
await writeFile(logPath,text);await writeFile(evidencePath,JSON.stringify(evidence));
|
|
35
|
+
const result=await importDeprecatedBuildLog({project,catalog,logPath,evidencePath});
|
|
36
|
+
assert.equal(result.findings.length,1);
|
|
37
|
+
await writeFile(path.join(root,'build-profile.json5'),'{"modules":[{"name":"entry","srcPath":"entry"}]}');
|
|
38
|
+
await writeFile(scanJson,JSON.stringify({sourceSnapshot:'source',buildProfileHash:'profile',deprecationCoverage:{sdkSnapshot:'sdk'},deprecationCatalog:{targetSdk:'26'},findings:[]}));
|
|
39
|
+
const comparison=await compareDeprecated({project:root,buildLog:logPath,scanJson,buildProjectRoot:'d:/harmony/app',buildEvidence:evidencePath,platform:'win32'});
|
|
40
|
+
assert.equal(comparison.evidenceStatus,'MATCHED_BUILD_SNAPSHOT');assert.equal(comparison.unmappedCount,0);
|
|
41
|
+
for(const wrong of ['E:\\Harmony\\App','D:\\Harmony\\Application']) {
|
|
42
|
+
await writeFile(evidencePath,JSON.stringify({...evidence,projectRoot:wrong}));
|
|
43
|
+
assert.equal((await importDeprecatedBuildLog({project,catalog,logPath,evidencePath})).findings.length,0);
|
|
44
|
+
}
|
|
45
|
+
await writeFile(evidencePath,JSON.stringify({...evidence,sourceSnapshot:'tampered'}));
|
|
46
|
+
await assert.rejects(importDeprecatedBuildLog({project,catalog,logPath,evidencePath}),{code:'BUILD_EVIDENCE_MISMATCH'});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('only verified logs import dependencies; absent or mismatched evidence is not trusted', async (t) => {
|
|
50
|
+
const root = await mkdtemp(path.join(os.tmpdir(), 'deprecated-build-log-'));
|
|
51
|
+
t.after(() => rm(root, { recursive: true, force: true }));
|
|
52
|
+
const logPath = path.join(root, 'build.log'), evidencePath = path.join(root, 'build-evidence.json');
|
|
53
|
+
await writeFile(logPath, log);
|
|
54
|
+
const project = { sourceSnapshot: 'source', buildProfileHash: 'config', product: { name: 'default' } };
|
|
55
|
+
const catalog = { snapshot: 'sdk', coverage: { targetSdk: '26.0.0(26) Release' }, deprecatedEntries: [] };
|
|
56
|
+
const untrusted = await importDeprecatedBuildLog({ project, catalog, logPath });
|
|
57
|
+
assert.equal(untrusted.findings.length, 0);
|
|
58
|
+
assert.equal(untrusted.audit.status, 'UNVERIFIED_LOG');
|
|
59
|
+
const evidence = { schemaVersion: 1, projectRoot: '/baseline', sourceSnapshot: 'source', buildProfileHash: 'config', sdkSnapshot: 'sdk',
|
|
60
|
+
targetSdk: '26.0.0(26) Release', product: 'default', logHash: sha256(log), nonIncremental: true, status: 'PASSED' };
|
|
61
|
+
await writeFile(evidencePath, JSON.stringify(evidence));
|
|
62
|
+
const trusted = await importDeprecatedBuildLog({ project, catalog, logPath, evidencePath });
|
|
63
|
+
assert.equal(trusted.findings.length, 1);
|
|
64
|
+
assert.equal(trusted.findings[0]['Source Scope'], 'DEPENDENCY');
|
|
65
|
+
assert.equal(trusted.findings[0].evidenceStatus, 'COMPILER_ONLY');
|
|
66
|
+
assert.equal(trusted.findings[0].autoEditAllowed, false);
|
|
67
|
+
await writeFile(evidencePath, JSON.stringify({ ...evidence, sourceSnapshot: 'old' }));
|
|
68
|
+
await assert.rejects(importDeprecatedBuildLog({ project, catalog, logPath, evidencePath }), { code: 'BUILD_EVIDENCE_MISMATCH' });
|
|
69
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, mkdir, readFile, readdir, rm } from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import {
|
|
8
|
+
createRunOutputDirectory,
|
|
9
|
+
execute,
|
|
10
|
+
resolveScanTargetVersion,
|
|
11
|
+
runTimestamp,
|
|
12
|
+
selectScanRules,
|
|
13
|
+
} from '../core/cli.mjs';
|
|
14
|
+
|
|
15
|
+
test('uses an explicit scan target before the exact toolchain channel', () => {
|
|
16
|
+
assert.deepEqual(resolveScanTargetVersion('26.0.0(26) Beta1', { sdkVersion: { raw: '26.0.0(26) Beta2' } }),
|
|
17
|
+
{ version: '26.0.0(26) Beta1', source: 'to' });
|
|
18
|
+
assert.deepEqual(resolveScanTargetVersion(null, { sdkVersion: { raw: '26.0.0(26) Beta2' } }),
|
|
19
|
+
{ version: '26.0.0(26) Beta2', source: 'toolchain' });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('rejects unsupported batch sizes instead of pretending they are applied', async () => {
|
|
23
|
+
await assert.rejects(() => execute([
|
|
24
|
+
'scan', '--mode', 'upgrade', '--project', '/project', '--sdk', '/sdk', '--from', '5.0.0(12)', '--to', '5.0.1(13)',
|
|
25
|
+
'--batch-size', '500',
|
|
26
|
+
]), /supports --batch-size 1000 only/);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('rejects unsupported scan modes', async () => {
|
|
30
|
+
await assert.rejects(() => execute([
|
|
31
|
+
'scan', '--project', '/project', '--sdk', '/sdk', '--from', '5.0.0(12)', '--to', '5.0.1(13)',
|
|
32
|
+
'--mode', 'behavior-only',
|
|
33
|
+
]), { code: 'SCAN_MODE_INVALID' });
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('deprecated mode keeps only deprecated rules for the DevEco backend', () => {
|
|
37
|
+
const rules = [
|
|
38
|
+
{ ruleId: 'behavior', changeType: 'API Behavior Change', changeOperation: 'API_BEHAVIOR', affectedApis: [{ implementLanguage: 'typescript' }] },
|
|
39
|
+
{ ruleId: 'definition', changeType: 'API Definition Change', changeOperation: 'API_DEFINITION_CHANGED', affectedApis: [{ implementLanguage: 'typescript' }] },
|
|
40
|
+
{ ruleId: 'deprecated-arkts', changeType: 'Deprecated API', changeOperation: 'API_DEPRECATED', affectedApis: [{ implementLanguage: 'typescript' }] },
|
|
41
|
+
{ ruleId: 'deprecated-cpp', changeType: 'Deprecated API', changeOperation: 'API_DEPRECATED', affectedApis: [{ implementLanguage: 'c' }] },
|
|
42
|
+
];
|
|
43
|
+
assert.deepEqual(selectScanRules(rules, 'deprecated').map(rule => rule.ruleId), ['deprecated-cpp']);
|
|
44
|
+
assert.throws(() => selectScanRules(rules, 'full'), {code:'SCAN_MODE_INVALID'});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('run timestamps use local YYYYMMDDHHmmss and increment on collision', async () => {
|
|
48
|
+
const now = new Date(2026, 6, 29, 8, 23, 50);
|
|
49
|
+
assert.equal(runTimestamp(now), '20260729082350');
|
|
50
|
+
const root = await mkdtemp(path.join(os.tmpdir(), 'scanner-run-dir-'));
|
|
51
|
+
const first = await createRunOutputDirectory(root);
|
|
52
|
+
const second = await createRunOutputDirectory(root);
|
|
53
|
+
assert.match(first.stamp, /^\d{14}$/);
|
|
54
|
+
assert.equal(second.stamp, `${first.stamp}-2`);
|
|
55
|
+
const nested = await readdir(path.join(root, first.stamp));
|
|
56
|
+
assert.deepEqual(nested, []);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('scan failures identify the pipeline stage in the error and diagnostics', async t => {
|
|
60
|
+
const root = await mkdtemp(path.join(os.tmpdir(), 'scanner-stage-'));
|
|
61
|
+
t.after(() => rm(root, { recursive: true, force: true }));
|
|
62
|
+
const output = path.join(root, 'output');
|
|
63
|
+
await mkdir(output, { recursive: true });
|
|
64
|
+
await assert.rejects(execute([
|
|
65
|
+
'scan', '--mode', 'upgrade', '--project', path.join(root, 'project'), '--sdk', path.join(root, 'missing-sdk'),
|
|
66
|
+
'--from', '5.0.0(12)', '--to', '26.0.0(26) Beta1', '--output-dir', output,
|
|
67
|
+
]), error => {
|
|
68
|
+
assert.equal(error.stage, 'DISCOVER_TOOLCHAIN');
|
|
69
|
+
return true;
|
|
70
|
+
});
|
|
71
|
+
const runDirectories = (await readdir(output)).filter(name => /^\d{14}(?:-\d+)?$/.test(name));
|
|
72
|
+
assert.equal(runDirectories.length, 1);
|
|
73
|
+
const diagnostics = JSON.parse(await readFile(path.join(output, runDirectories[0], '.internal', 'scanner', 'diagnostics.json'), 'utf8'));
|
|
74
|
+
assert.equal(diagnostics.error.stage, 'DISCOVER_TOOLCHAIN');
|
|
75
|
+
const skillRoot = path.resolve(fileURLToPath(new URL('../../../', import.meta.url)));
|
|
76
|
+
assert.equal(diagnostics.runtime.skillRoot, skillRoot);
|
|
77
|
+
assert.equal(diagnostics.options.referenceRoot, path.join(skillRoot, 'references', 'changelogs'));
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
for(const mode of ['upgrade','deprecated']) test(`${mode} CLI reserves a feature batch before backend discovery`,async t=>{
|
|
81
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'scanner-batch-'));
|
|
82
|
+
t.after(()=>rm(root,{recursive:true,force:true}));
|
|
83
|
+
try {
|
|
84
|
+
await execute(['scan','--project',path.join(root,'project'),'--sdk',path.join(root,'missing-sdk'),
|
|
85
|
+
'--from','22','--to','26','--mode',mode,'--output-dir',root]);
|
|
86
|
+
assert.fail('missing SDK must fail');
|
|
87
|
+
} catch(error) { assert.equal(error.code,'SDK_ROOT_INVALID'); }
|
|
88
|
+
const folders=(await readdir(root)).filter(name=>/^\d{14}(?:-\d+)?$/.test(name));
|
|
89
|
+
assert.equal(folders.length,1);
|
|
90
|
+
const scan=path.join(root,folders[0]);
|
|
91
|
+
const metadata=JSON.parse(await readFile(path.join(scan,'.internal','scan-batch.json'),'utf8'));
|
|
92
|
+
assert.equal(metadata.schemaVersion,4);
|
|
93
|
+
assert.equal(metadata.mode,mode);
|
|
94
|
+
if(mode==='deprecated') assert.equal(metadata.scanStamp,folders[0]);
|
|
95
|
+
assert.ok((await readdir(scan)).includes(mode));
|
|
96
|
+
assert.match(metadata.batchId,/^[a-f0-9]{12}$/);
|
|
97
|
+
const diagnostics=JSON.parse(await readFile(path.join(scan,'.internal','scanner','diagnostics.json'),'utf8'));
|
|
98
|
+
assert.equal(diagnostics.error.code,'SDK_ROOT_INVALID');
|
|
99
|
+
assert.equal(diagnostics.runtime.featureMode,mode);
|
|
100
|
+
assert.equal(diagnostics.error.artifactPaths[0],path.join(scan,'.internal','scanner','diagnostics.json'));
|
|
101
|
+
await assert.rejects(readFile(path.join(scan,'diagnostics.json')),{code:'ENOENT'});
|
|
102
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { DEPRECATED_HEADERS, parseCsv, SCANNER_HEADERS, stringifyCsv, UPGRADE_HEADERS } from '../../shared/format/csv.mjs';
|
|
4
|
+
|
|
5
|
+
test('mode-specific CSV projections preserve duplicate rows, escaping and hyperlinks', () => {
|
|
6
|
+
assert.deepEqual(UPGRADE_HEADERS, ['Api Definition', 'Language', 'Changed in SDK', 'Affected Versions',
|
|
7
|
+
'Title', 'Code Location', 'Fixed', 'Change Type', 'Rule ID']);
|
|
8
|
+
assert.deepEqual(DEPRECATED_HEADERS, ['Api Definition', 'Language', 'Changed in SDK',
|
|
9
|
+
'Title', 'Code Location', 'Fixed', 'Change Type', 'Replacement API']);
|
|
10
|
+
for (const headers of [UPGRADE_HEADERS, DEPRECATED_HEADERS]) {
|
|
11
|
+
const row = Object.fromEntries(headers.map(header => [header, '']));
|
|
12
|
+
row['Api Definition'] = 'run("a,b"): void\nnext';
|
|
13
|
+
row.Title = '=HYPERLINK("https://example.test/a","标题,一")';
|
|
14
|
+
const text = stringifyCsv(headers, [{ ...row, Column: 1 }, { ...row, Column: 8 }]);
|
|
15
|
+
assert.ok(text.startsWith('\ufeff'));
|
|
16
|
+
assert.ok(text.endsWith('\r\n'));
|
|
17
|
+
assert.deepEqual(parseCsv(text), { headers, rows: [row, row] });
|
|
18
|
+
assert.deepEqual(parseCsv(stringifyCsv(headers, [])), { headers, rows: [] });
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('round trips BOM, CRLF, hyperlink formulas and scanner metadata', () => {
|
|
23
|
+
const row = Object.fromEntries(SCANNER_HEADERS.map((header) => [header, '']));
|
|
24
|
+
row['Api Definition'] = 'run(value: string, count: number): void';
|
|
25
|
+
row.Language = 'ArkTS';
|
|
26
|
+
row.Title = '=HYPERLINK("https://example.test/a","标题,一")';
|
|
27
|
+
row['Code Location'] = 'entry/src/main/ets/A.ets:3';
|
|
28
|
+
row.Fixed = 'Unfixed';
|
|
29
|
+
row['Change Type'] = 'API Behavior Change';
|
|
30
|
+
row['Rule ID'] = 'rule-1';
|
|
31
|
+
const encoded = stringifyCsv(SCANNER_HEADERS, [row]);
|
|
32
|
+
assert.ok(encoded.startsWith('\ufeff'));
|
|
33
|
+
assert.ok(encoded.includes('\r\n'));
|
|
34
|
+
assert.deepEqual(parseCsv(encoded), { headers: SCANNER_HEADERS, rows: [row] });
|
|
35
|
+
});
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { mkdir, mkdtemp, writeFile, rm } from 'node:fs/promises';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { buildSdkCatalog, catalogEntry, indexSdkFile, resolveRuleDeclarations, sdkLocationKey } from '../core/sdk-deprecations.mjs';
|
|
8
|
+
import { compilerPathIdentity, projectModuleForFile, scanArkTsDeprecations } from '../deprecated/arkts-deprecations.mjs';
|
|
9
|
+
import { loadProject } from '../core/project.mjs';
|
|
10
|
+
import { parseVersion } from '../../shared/platform/version.mjs';
|
|
11
|
+
|
|
12
|
+
const parserPath = process.env.HARMONYOS_TYPESCRIPT || '/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/ets/build-tools/ets-loader/node_modules/typescript/lib/typescript.js';
|
|
13
|
+
const available = existsSync(parserPath);
|
|
14
|
+
|
|
15
|
+
test('compiler path identity treats Windows parser and filesystem separators as the same file', () => {
|
|
16
|
+
assert.equal(
|
|
17
|
+
compilerPathIdentity('D:\\SDK\\api\\@ohos.promptAction.d.ts', 'win32'),
|
|
18
|
+
compilerPathIdentity('d:/sdk/api/@ohos.promptAction.d.ts', 'win32'),
|
|
19
|
+
);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('catalog lookup normalizes Windows separators for SDK declaration locations', () => {
|
|
23
|
+
const indexedFile = 'D:/SDK/api/@ohos.promptAction.d.ts';
|
|
24
|
+
const originalFile = { fileName: 'D:\\SDK\\api\\@ohos.promptAction.d.ts' };
|
|
25
|
+
const cloneFile = { fileName: originalFile.fileName };
|
|
26
|
+
const original = { getSourceFile: () => originalFile, getStart: () => 42 };
|
|
27
|
+
const clone = { getSourceFile: () => cloneFile, getStart: () => 42, end: 50 };
|
|
28
|
+
const entry = { symbolId: 'api-show-toast' };
|
|
29
|
+
const catalog = {
|
|
30
|
+
platform: 'win32',
|
|
31
|
+
ts: { getOriginalNode: () => original },
|
|
32
|
+
byLocation: new Map([[`${indexedFile}\0${original.getStart()}`, entry]]),
|
|
33
|
+
byComparableLocation: new Map([[sdkLocationKey(indexedFile, original.getStart(), 'win32'), entry]]),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
assert.equal(catalogEntry(catalog, clone), entry);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('maps parser-normalized Windows source paths back to their project module', () => {
|
|
40
|
+
const module = projectModuleForFile({ modules: [{
|
|
41
|
+
name: 'module_transition',
|
|
42
|
+
root: 'D:\\Work\\News\\components\\module_transition',
|
|
43
|
+
}] }, 'D:/Work/News/components/module_transition/src/main/ets/Utils.ets', 'win32');
|
|
44
|
+
|
|
45
|
+
assert.equal(module?.name, 'module_transition');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('SDK indexing ignores nameless JSDoc tags without losing known tags', () => {
|
|
49
|
+
const no = () => false;
|
|
50
|
+
const sourceFile = {
|
|
51
|
+
fileName: 'sdk.d.ts',
|
|
52
|
+
text: 'declare function legacy(): void;',
|
|
53
|
+
name: { getText: () => 'legacy' },
|
|
54
|
+
end: 32,
|
|
55
|
+
getStart: () => 0,
|
|
56
|
+
getText() { return this.text; },
|
|
57
|
+
getLineAndCharacterOfPosition: () => ({ line: 0, character: 0 }),
|
|
58
|
+
};
|
|
59
|
+
const deprecated = {
|
|
60
|
+
comment: 'since 26',
|
|
61
|
+
parent: { tags: [{}, { tagName: { text: 'useinstead' }, comment: 'modern' }] },
|
|
62
|
+
};
|
|
63
|
+
const ts = {
|
|
64
|
+
isClassDeclaration: no,
|
|
65
|
+
isStructDeclaration: no,
|
|
66
|
+
isAnnotationDeclaration: no,
|
|
67
|
+
isInterfaceDeclaration: no,
|
|
68
|
+
isEnumDeclaration: no,
|
|
69
|
+
isModuleDeclaration: no,
|
|
70
|
+
isConstructorDeclaration: no,
|
|
71
|
+
isFunctionDeclaration: node => node === sourceFile,
|
|
72
|
+
isMethodDeclaration: no,
|
|
73
|
+
isMethodSignature: no,
|
|
74
|
+
isCallSignatureDeclaration: no,
|
|
75
|
+
isGetAccessor: no,
|
|
76
|
+
isSetAccessor: no,
|
|
77
|
+
isEnumMember: no,
|
|
78
|
+
isPropertyDeclaration: no,
|
|
79
|
+
isPropertySignature: no,
|
|
80
|
+
isAnnotationPropertyDeclaration: no,
|
|
81
|
+
isVariableDeclaration: no,
|
|
82
|
+
isTypeAliasDeclaration: no,
|
|
83
|
+
getJSDocTags: () => [{}, { tagName: { text: 'throws' }, getText: () => '@throws Error' }],
|
|
84
|
+
getJSDocDeprecatedTag: () => deprecated,
|
|
85
|
+
forEachChild: () => {},
|
|
86
|
+
SyntaxKind: { StaticKeyword: 126 },
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const result = indexSdkFile(ts, sourceFile, 'openharmony', 'api/sdk.d.ts');
|
|
90
|
+
|
|
91
|
+
assert.equal(result.declarations.length, 1);
|
|
92
|
+
assert.equal(result.declarations[0].replacementApi, 'modern');
|
|
93
|
+
assert.deepEqual(result.declarations[0].throws, ['@throws Error']);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
async function fixture(t, source) {
|
|
97
|
+
const root = await mkdtemp(path.join(os.tmpdir(), 'deprecated-semantics-'));
|
|
98
|
+
t.after(() => rm(root, { recursive: true, force: true }));
|
|
99
|
+
const sdkRoot = path.join(root, 'sdk');
|
|
100
|
+
const ets = path.join(sdkRoot, 'default/openharmony/ets');
|
|
101
|
+
const files = {
|
|
102
|
+
'build-profile.json5': '{app:{products:[{name:"default"}]},modules:[{name:"entry",srcPath:"./entry"},{name:"shared",srcPath:"./shared"}]}',
|
|
103
|
+
'entry/src/main/module.json5': '{module:{type:"entry"}}',
|
|
104
|
+
'shared/src/main/module.json5': '{module:{type:"har"}}',
|
|
105
|
+
'shared/oh-package.json5': '{name:"shared",main:"Index.ets"}',
|
|
106
|
+
'shared/Index.ets': 'export { getView } from "./View";',
|
|
107
|
+
'shared/View.ets': 'import { modern } from "@kit.TestKit"; export function getView(): modern.View { return new modern.View(); }',
|
|
108
|
+
'entry/oh-package.json5': '{dependencies:{shared:"file:../shared"}}',
|
|
109
|
+
'entry/src/main/ets/A.ets': source,
|
|
110
|
+
'oh_modules/unused/A.ets': 'oldGlobal(1);',
|
|
111
|
+
};
|
|
112
|
+
for (const [f, text] of Object.entries(files)) {
|
|
113
|
+
await mkdir(path.dirname(path.join(root, f)), { recursive: true });
|
|
114
|
+
await writeFile(path.join(root, f), text);
|
|
115
|
+
}
|
|
116
|
+
await mkdir(path.join(ets, 'api'), { recursive: true });
|
|
117
|
+
await mkdir(path.join(ets, 'kits'), { recursive: true });
|
|
118
|
+
await mkdir(path.join(ets, 'component'), { recursive: true });
|
|
119
|
+
await writeFile(path.join(ets, 'component/global.d.ts'), '/** @deprecated since 18\n * @useinstead modern.View.convert\n */ declare function oldGlobal(value: number): number;');
|
|
120
|
+
await writeFile(path.join(ets, 'kits/@kit.TestKit.d.ts'), 'export { legacy, modern, Alert, Animator } from "../api/@ohos.test";');
|
|
121
|
+
await writeFile(path.join(ets, 'api/@ohos.test.d.ts'), `
|
|
122
|
+
export namespace legacy {
|
|
123
|
+
/** @deprecated since 20\n * @useinstead modern.View\n */ export class Format {
|
|
124
|
+
/** @deprecated since 20\n * @useinstead modern.View.convert\n */ format(value: number): number;
|
|
125
|
+
formatMatcher: string;
|
|
126
|
+
}
|
|
127
|
+
export class Decoder {
|
|
128
|
+
/** @deprecated since 9\n * @useinstead decodeToString\n */ decode(value: string): string;
|
|
129
|
+
decodeToString(value: string): string;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export namespace modern { export class View { convert(value: number): number; } }
|
|
133
|
+
/** @deprecated since 26\n * @useinstead modern.View\n */ export class Alert {
|
|
134
|
+
/** @deprecated since 18\n * @useinstead modern.View.convert\n */ static show(value: number): void;
|
|
135
|
+
}
|
|
136
|
+
export class Animator {
|
|
137
|
+
/** @deprecated since 18\n * @useinstead modern.View\n */ static create(value: number): void;
|
|
138
|
+
static create(value: string): void;
|
|
139
|
+
/** @deprecated since 30 */ static future(): void;
|
|
140
|
+
}
|
|
141
|
+
`);
|
|
142
|
+
const toolchain = { sdkRoot, parserPath, sdkVersion: parseVersion('26.0.0(26) Release'), sdkMetadata: { data: { apiVersion: '26', platformVersion: '26.0.0', releaseType: 'Release' } } };
|
|
143
|
+
const catalog = await buildSdkCatalog(toolchain, parseVersion('26.0.0(26) Release'));
|
|
144
|
+
const project = await loadProject(root, 'default');
|
|
145
|
+
return { root, project, catalog, toolchain, ets };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
test('SDK identity is namespace and overload exact; replacement never matches substrings', { skip: !available }, async (t) => {
|
|
149
|
+
const { catalog } = await fixture(t, '');
|
|
150
|
+
const declarations = resolveRuleDeclarations(catalog, { completePath: '/interface/sdk-js/api/@ohos.test.d.ts', className: 'Format', interfaceName: 'format', interfaceType: 'method', methodDefinition: 'format(value: number): number;' });
|
|
151
|
+
assert.equal(declarations.length, 1);
|
|
152
|
+
assert.equal(declarations[0].qualifiedName, 'legacy.Format.format');
|
|
153
|
+
assert.equal(declarations[0].replacementApi, 'modern.View.convert');
|
|
154
|
+
assert.equal(catalog.deprecatedEntries.some(e => e.name === 'future'), false);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('unrelated missing SDK exports warn, but a project use of that export blocks coverage', { skip: !available }, async t => {
|
|
158
|
+
const { project, catalog, ets } = await fixture(t, 'oldGlobal(1);');
|
|
159
|
+
const file = path.join(ets, 'api/@ohos.test.d.ts');
|
|
160
|
+
const { readFile } = await import('node:fs/promises');
|
|
161
|
+
await writeFile(file, `${await readFile(file, 'utf8')}\nexport { Missing } from './missing-in-sdk';\n`);
|
|
162
|
+
const updated = await buildSdkCatalog(catalog.toolchain, catalog.targetVersion);
|
|
163
|
+
const unrelated = await scanArkTsDeprecations({ project, catalog: updated });
|
|
164
|
+
assert.equal(unrelated.coverage.status, 'COMPLETE');
|
|
165
|
+
assert.ok(unrelated.resolutionWarnings.some(item => item.module === './missing-in-sdk'
|
|
166
|
+
&& item.reason === 'UNUSED_SDK_IMPORT_NOT_RESOLVED'));
|
|
167
|
+
await writeFile(project.sourceFiles.find(file => file.endsWith('/A.ets')),
|
|
168
|
+
'import { Missing } from "@ohos.test"; let value: Missing; oldGlobal(1);');
|
|
169
|
+
const used = await scanArkTsDeprecations({ project, catalog: updated });
|
|
170
|
+
assert.equal(used.coverage.status, 'INCOMPLETE');
|
|
171
|
+
assert.ok(used.unresolved.some(item => item.module === './missing-in-sdk'));
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test('deprecated titles link official references and prefer documented change URLs', { skip: !available }, async (t) => {
|
|
175
|
+
const { project, catalog } = await fixture(t, `import { legacy } from '@kit.TestKit';
|
|
176
|
+
const f = new legacy.Format(); f.format(1);
|
|
177
|
+
oldGlobal(1);`);
|
|
178
|
+
const moduleUrl = 'https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-test';
|
|
179
|
+
const plain = await scanArkTsDeprecations({ project, catalog });
|
|
180
|
+
const formatRow = plain.findings.find(f => f.sdkEvidence.qualifiedName === 'legacy.Format.format');
|
|
181
|
+
assert.ok(plain.findings.some(f => f.Title.includes(moduleUrl)));
|
|
182
|
+
assert.ok(plain.findings.some(f => f.Title.includes('API 废弃')));
|
|
183
|
+
const globalRows = plain.findings.filter(f => f.sdkEvidence.name === 'oldGlobal');
|
|
184
|
+
assert.ok(globalRows.length > 0 && globalRows.every(f => !String(f.Title).startsWith('=')));
|
|
185
|
+
const documented = await scanArkTsDeprecations({
|
|
186
|
+
project, catalog,
|
|
187
|
+
documentRules: [{ ruleId: 'r1', sdkSymbolIds: [formatRow['API Symbol ID']], sourceReference: 'changes/a.md:5', url: 'https://example.com/deprecated-format' }],
|
|
188
|
+
});
|
|
189
|
+
const documentedRow = documented.findings.find(f => f['API Symbol ID'] === formatRow['API Symbol ID']);
|
|
190
|
+
assert.equal(documentedRow.Title, '=HYPERLINK("https://example.com/deprecated-format","legacy.Format.format:API 废弃")');
|
|
191
|
+
assert.deepEqual(documentedRow.documentReferences, [{ ruleId: 'r1', sourceReference: 'changes/a.md:5', url: 'https://example.com/deprecated-format' }]);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test('resolves old APIs, constructors, inheritance, aliases, reexports and exact overloads', { skip: !available }, async (t) => {
|
|
195
|
+
const { project, catalog } = await fixture(t, `import { legacy as l, Alert, Animator } from '@kit.TestKit';
|
|
196
|
+
import { getView } from 'shared';
|
|
197
|
+
const f = new l.Format(); f.format(1);
|
|
198
|
+
const d = new l.Decoder(); d.decode('x');
|
|
199
|
+
class Derived extends l.Decoder {} new Derived().decode('x');
|
|
200
|
+
Alert.show(1); Animator.create(1); Animator.create('x'); Animator.future();
|
|
201
|
+
getView().convert(1); const fake = { oldGlobal(x: number) { return x; } }; fake.oldGlobal(1);
|
|
202
|
+
oldGlobal(
|
|
203
|
+
oldGlobal(1)); oldGlobal(2); oldGlobal(3);
|
|
204
|
+
`);
|
|
205
|
+
const result = await scanArkTsDeprecations({ project, catalog });
|
|
206
|
+
assert.deepEqual(result.unresolved, []);
|
|
207
|
+
assert.equal(result.findings.length, 11);
|
|
208
|
+
assert.equal(result.findings.filter(f => f['Deprecated Since'] === 9).length, 2);
|
|
209
|
+
assert.equal(result.findings.filter(f => f.sdkEvidence.qualifiedName === 'Animator.create').length, 1);
|
|
210
|
+
assert.equal(result.findings.filter(f => f.sdkEvidence.qualifiedName === 'Alert').length, 1);
|
|
211
|
+
assert.equal(result.findings.filter(f => f.sdkEvidence.qualifiedName === 'Alert.show').length, 1);
|
|
212
|
+
const alert = result.findings.filter(f => f.sdkEvidence.qualifiedName.startsWith('Alert'));
|
|
213
|
+
assert.deepEqual(alert[0].callRange, alert[1].callRange);
|
|
214
|
+
assert.equal(result.findings.filter(f => f.sdkEvidence.name === 'oldGlobal').length, 4);
|
|
215
|
+
assert.equal(new Set(result.findings.map(f => f.occurrenceId)).size, 11);
|
|
216
|
+
assert.ok(result.findings.every(f => f.Column > 0 && f['Source Scope'] === 'PROJECT'));
|
|
217
|
+
const again = await scanArkTsDeprecations({ project, catalog });
|
|
218
|
+
assert.deepEqual(again.findings, result.findings);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test('ArkUI component initializer fields resolve to the SDK struct, not a same-name object', { skip: !available }, async (t) => {
|
|
222
|
+
const fixtureData = await fixture(t, `import Card from '@ohos.card';
|
|
223
|
+
@Builder function render() { Card({ callback: () => {} }); }
|
|
224
|
+
const own = { callback: () => {} }; own.callback();`);
|
|
225
|
+
await writeFile(path.join(fixtureData.ets, 'api/@ohos.card.d.ets'), `
|
|
226
|
+
declare struct Card {
|
|
227
|
+
/** @deprecated since 19\n * @useinstead Card.onResult\n */ callback: () => void;
|
|
228
|
+
onResult: () => void;
|
|
229
|
+
build(): void;
|
|
230
|
+
}
|
|
231
|
+
export default Card;`);
|
|
232
|
+
const catalog = await buildSdkCatalog(fixtureData.toolchain);
|
|
233
|
+
const project = await loadProject(fixtureData.root, 'default');
|
|
234
|
+
const result = await scanArkTsDeprecations({ project, catalog });
|
|
235
|
+
assert.deepEqual(result.unresolved, []);
|
|
236
|
+
assert.equal(result.findings.length, 1);
|
|
237
|
+
assert.equal(result.findings[0].sdkEvidence.qualifiedName, 'Card.callback');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test('missing SDK imports are explicit unresolved evidence', { skip: !available }, async (t) => {
|
|
241
|
+
const { project, catalog } = await fixture(t, 'import { unknown } from "@kit.MissingKit"; unknown.run();');
|
|
242
|
+
const result = await scanArkTsDeprecations({ project, catalog });
|
|
243
|
+
assert.ok(result.unresolved.some(e => e.reason === 'MODULE_NOT_RESOLVED'));
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test('typed SDK receivers with missing methods fail resolution rather than silently completing', { skip: !available }, async (t) => {
|
|
247
|
+
const { project, catalog } = await fixture(t, 'import { modern } from "@kit.TestKit"; const ui = new modern.View(); ui.missing(1); ui.toString();');
|
|
248
|
+
const result = await scanArkTsDeprecations({ project, catalog });
|
|
249
|
+
assert.ok(result.unresolved.some(item => item.api === 'ui.missing' && item.reason === 'SDK_MEMBER_NOT_RESOLVED'));
|
|
250
|
+
assert.equal(result.unresolved.some(item => item.api === 'ui.toString'), false);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test('computed SDK calls still resolve the selected overload', { skip: !available }, async (t) => {
|
|
254
|
+
const { project, catalog } = await fixture(t, `import { legacy, Animator } from '@kit.TestKit';
|
|
255
|
+
const decoder = new legacy.Decoder(); decoder['decode']('x');
|
|
256
|
+
Animator['create'](1); Animator['create']('x');`);
|
|
257
|
+
const result = await scanArkTsDeprecations({ project, catalog });
|
|
258
|
+
assert.deepEqual(result.unresolved, []);
|
|
259
|
+
assert.equal(result.findings.length, 2);
|
|
260
|
+
assert.deepEqual(result.findings.map(item => item.sdkEvidence.qualifiedName), ['legacy.Decoder.decode', 'Animator.create']);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test('case-insensitive imports use the discovered source spelling', { skip: !available }, async (t) => {
|
|
264
|
+
const f = await fixture(t, 'import { run } from "./utils"; run();');
|
|
265
|
+
await mkdir(path.join(f.root, 'entry/src/main/ets/utils'));
|
|
266
|
+
await writeFile(path.join(f.root, 'entry/src/main/ets/utils/index.ets'), 'export function run() { oldGlobal(1); }');
|
|
267
|
+
const project = await loadProject(f.root, 'default');
|
|
268
|
+
const result = await scanArkTsDeprecations({ project, catalog: f.catalog });
|
|
269
|
+
assert.equal(result.findings.length, 1);
|
|
270
|
+
assert.equal(result.findings[0]['Code Location'], 'entry/src/main/ets/utils/index.ets:1');
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test('a newer compile SDK keeps its real snapshot and filters deprecations by requested target', { skip: !available }, async (t) => {
|
|
274
|
+
const { toolchain } = await fixture(t, '');
|
|
275
|
+
const full=await buildSdkCatalog(toolchain,parseVersion('26'));
|
|
276
|
+
const older=await buildSdkCatalog(toolchain,parseVersion('20'));
|
|
277
|
+
assert.equal(older.snapshot,full.snapshot);
|
|
278
|
+
assert.equal(older.coverage.compileSdk,'26.0.0(26) Release');
|
|
279
|
+
assert.equal(older.coverage.targetSdk,'6.0.0(20) Release');
|
|
280
|
+
assert.ok(older.deprecatedEntries.every(entry=>entry.deprecatedSince<=20));
|
|
281
|
+
assert.ok(older.declarations.every(entry=>entry.file.startsWith(older.toolchain.sdkRoot)));
|
|
282
|
+
await assert.rejects(buildSdkCatalog({...toolchain,sdkVersion:parseVersion('19')},parseVersion('20')),{code:'SDK_TARGET_NOT_COVERED'});
|
|
283
|
+
});
|