
























@@ -71,12 +71,13 @@ function formatSelectionRefList(values: readonly string[]): string {
7171return values.map((value) => `"${value}"`).join(", ");
7272}
737374-function buildSkillSelectionIndex(
74+function buildSelectionIndex(
7575items: readonly MigrationItem[],
76+refsForItem: (item: MigrationItem) => readonly string[],
7677): Map<string, ReadonlySet<string>> {
7778const index = new Map<string, Set<string>>();
7879for (const item of items) {
79-for (const ref of migrationSkillRefs(item)) {
80+for (const ref of refsForItem(item)) {
8081const normalized = normalizeSelectionRef(ref);
8182if (!normalized) {
8283continue;
@@ -89,33 +90,19 @@ function buildSkillSelectionIndex(
8990return index;
9091}
919292-function buildPluginSelectionIndex(
93-items: readonly MigrationItem[],
94-): Map<string, ReadonlySet<string>> {
95-const index = new Map<string, Set<string>>();
96-for (const item of items) {
97-for (const ref of migrationPluginRefs(item)) {
98-const normalized = normalizeSelectionRef(ref);
99-if (!normalized) {
100-continue;
101-}
102-const existing = index.get(normalized) ?? new Set<string>();
103-existing.add(item.id);
104-index.set(normalized, existing);
105-}
106-}
107-return index;
108-}
109-110-function resolveSelectedSkillItemIds(
111-items: readonly MigrationItem[],
112-selectedRefs: readonly string[],
113-): Set<string> {
114-const index = buildSkillSelectionIndex(items);
93+function resolveSelectedMigrationItemIds(params: {
94+items: readonly MigrationItem[];
95+selectedRefs: readonly string[];
96+refsForItem: (item: MigrationItem) => readonly string[];
97+formatSelectionLabel: (item: MigrationItem) => string;
98+kindLabel: "skill" | "plugin";
99+availableLabel: "skills" | "plugins";
100+}): Set<string> {
101+const index = buildSelectionIndex(params.items, params.refsForItem);
115102const selectedIds = new Set<string>();
116103const unknownRefs: string[] = [];
117104const ambiguousRefs: string[] = [];
118-for (const ref of selectedRefs) {
105+for (const ref of params.selectedRefs) {
119106const normalized = normalizeSelectionRef(ref);
120107if (!normalized) {
121108continue;
@@ -136,67 +123,54 @@ function resolveSelectedSkillItemIds(
136123}
137124138125if (unknownRefs.length > 0 || ambiguousRefs.length > 0) {
139-const available = items
140-.map(formatMigrationSkillSelectionLabel)
126+const available = params.items
127+.map(params.formatSelectionLabel)
141128.toSorted((a, b) => a.localeCompare(b));
129+const titleKind = params.kindLabel[0].toUpperCase() + params.kindLabel.slice(1);
142130const parts: string[] = [];
143131if (unknownRefs.length > 0) {
144-parts.push(`No migratable skill matched ${formatSelectionRefList(unknownRefs)}.`);
132+parts.push(
133+`No migratable ${params.kindLabel} matched ${formatSelectionRefList(unknownRefs)}.`,
134+);
145135}
146136if (ambiguousRefs.length > 0) {
147-parts.push(`Skill selection ${formatSelectionRefList(ambiguousRefs)} was ambiguous.`);
137+parts.push(`${titleKind} selection ${formatSelectionRefList(ambiguousRefs)} was ambiguous.`);
148138}
149-parts.push(`Available skills: ${available.length > 0 ? available.join(", ") : "none"}.`);
139+parts.push(
140+`Available ${params.availableLabel}: ${available.length > 0 ? available.join(", ") : "none"}.`,
141+);
150142throw new Error(parts.join(" "));
151143}
152144153145return selectedIds;
154146}
155147156-function resolveSelectedPluginItemIds(
148+function resolveSelectedSkillItemIds(
157149items: readonly MigrationItem[],
158150selectedRefs: readonly string[],
159151): Set<string> {
160-const index = buildPluginSelectionIndex(items);
161-const selectedIds = new Set<string>();
162-const unknownRefs: string[] = [];
163-const ambiguousRefs: string[] = [];
164-for (const ref of selectedRefs) {
165-const normalized = normalizeSelectionRef(ref);
166-if (!normalized) {
167-continue;
168-}
169-const matches = index.get(normalized);
170-if (!matches) {
171-unknownRefs.push(ref);
172-continue;
173-}
174-if (matches.size > 1) {
175-ambiguousRefs.push(ref);
176-continue;
177-}
178-const [id] = matches;
179-if (id) {
180-selectedIds.add(id);
181-}
182-}
183-184-if (unknownRefs.length > 0 || ambiguousRefs.length > 0) {
185-const available = items
186-.map(formatMigrationPluginSelectionLabel)
187-.toSorted((a, b) => a.localeCompare(b));
188-const parts: string[] = [];
189-if (unknownRefs.length > 0) {
190-parts.push(`No migratable plugin matched ${formatSelectionRefList(unknownRefs)}.`);
191-}
192-if (ambiguousRefs.length > 0) {
193-parts.push(`Plugin selection ${formatSelectionRefList(ambiguousRefs)} was ambiguous.`);
194-}
195-parts.push(`Available plugins: ${available.length > 0 ? available.join(", ") : "none"}.`);
196-throw new Error(parts.join(" "));
197-}
152+return resolveSelectedMigrationItemIds({
153+ items,
154+ selectedRefs,
155+refsForItem: migrationSkillRefs,
156+formatSelectionLabel: formatMigrationSkillSelectionLabel,
157+kindLabel: "skill",
158+availableLabel: "skills",
159+});
160+}
198161199-return selectedIds;
162+function resolveSelectedPluginItemIds(
163+items: readonly MigrationItem[],
164+selectedRefs: readonly string[],
165+): Set<string> {
166+return resolveSelectedMigrationItemIds({
167+ items,
168+ selectedRefs,
169+refsForItem: migrationPluginRefs,
170+formatSelectionLabel: formatMigrationPluginSelectionLabel,
171+kindLabel: "plugin",
172+availableLabel: "plugins",
173+});
200174}
201175202176export function getSelectableMigrationSkillItems(plan: MigrationPlan): MigrationItem[] {
@@ -427,6 +401,29 @@ function resolveInteractiveMigrationSelection(
427401};
428402}
429403404+function isMigrationSelectionToggleValue(value: string): boolean {
405+return (
406+value === MIGRATION_SELECTION_TOGGLE_ALL_ON || value === MIGRATION_SELECTION_TOGGLE_ALL_OFF
407+);
408+}
409+410+function selectedMigrationItemValues(selectedValues: readonly string[]): string[] {
411+return selectedValues.filter((value) => !isMigrationSelectionToggleValue(value));
412+}
413+414+function resolveMigrationSelectionBulkToggleValues(
415+activatedValue: string | undefined,
416+selectableValues: readonly string[],
417+): string[] | undefined {
418+if (activatedValue === MIGRATION_SELECTION_TOGGLE_ALL_ON) {
419+return [MIGRATION_SELECTION_TOGGLE_ALL_ON, ...selectableValues];
420+}
421+if (activatedValue === MIGRATION_SELECTION_TOGGLE_ALL_OFF) {
422+return [MIGRATION_SELECTION_TOGGLE_ALL_OFF];
423+}
424+return undefined;
425+}
426+430427export function resolveInteractiveMigrationSkillSelection(
431428items: readonly MigrationItem[],
432429selectedValues: readonly string[],
@@ -454,17 +451,12 @@ export function reconcileInteractiveMigrationSkillToggleValues(
454451activatedValue: string | undefined,
455452selectableValues: readonly string[],
456453): string[] {
457-if (activatedValue === MIGRATION_SELECTION_TOGGLE_ALL_ON) {
458-return [MIGRATION_SELECTION_TOGGLE_ALL_ON, ...selectableValues];
459-}
460-if (activatedValue === MIGRATION_SELECTION_TOGGLE_ALL_OFF) {
461-return [MIGRATION_SELECTION_TOGGLE_ALL_OFF];
454+const bulkValues = resolveMigrationSelectionBulkToggleValues(activatedValue, selectableValues);
455+if (bulkValues !== undefined) {
456+return bulkValues;
462457}
463458if (activatedValue !== undefined && selectableValues.includes(activatedValue)) {
464-return selectedValues.filter(
465-(value) =>
466-value !== MIGRATION_SELECTION_TOGGLE_ALL_ON && value !== MIGRATION_SELECTION_TOGGLE_ALL_OFF,
467-);
459+return selectedMigrationItemValues(selectedValues);
468460}
469461return selectedValues.filter(
470462(value) =>
@@ -479,17 +471,12 @@ export function reconcileInteractiveMigrationEnterValues(
479471selectableValues: readonly string[],
480472opts: { preserveDeselectedActivatedValue?: boolean } = {},
481473): string[] {
482-if (activatedValue === MIGRATION_SELECTION_TOGGLE_ALL_ON) {
483-return [MIGRATION_SELECTION_TOGGLE_ALL_ON, ...selectableValues];
484-}
485-if (activatedValue === MIGRATION_SELECTION_TOGGLE_ALL_OFF) {
486-return [MIGRATION_SELECTION_TOGGLE_ALL_OFF];
474+const bulkValues = resolveMigrationSelectionBulkToggleValues(activatedValue, selectableValues);
475+if (bulkValues !== undefined) {
476+return bulkValues;
487477}
488478if (activatedValue !== undefined && selectableValues.includes(activatedValue)) {
489-const selectedSelectableValues = selectedValues.filter(
490-(value) =>
491-value !== MIGRATION_SELECTION_TOGGLE_ALL_ON && value !== MIGRATION_SELECTION_TOGGLE_ALL_OFF,
492-);
479+const selectedSelectableValues = selectedMigrationItemValues(selectedValues);
493480if (opts.preserveDeselectedActivatedValue && !selectedValues.includes(activatedValue)) {
494481return selectedSelectableValues;
495482}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。