




















@@ -50,6 +50,12 @@ const BLOCKED_PLUGIN_CANDIDATE_PREFIX = "blocked plugin candidate:";
50505151type UnknownIssueRecord = Record<string, unknown>;
5252type ConfigPathSegment = string | number;
53+type ExplicitPluginReferences = {
54+entries: Set<string>;
55+allow: Set<string>;
56+deny: Set<string>;
57+slots: Map<string, string>;
58+};
5359type AllowedValuesCollection = {
5460values: unknown[];
5561incomplete: boolean;
@@ -567,6 +573,81 @@ function mapZodIssueToConfigIssue(issue: unknown): ConfigValidationIssue {
567573};
568574}
569575576+function collectExplicitPluginReferences(raw: unknown): ExplicitPluginReferences {
577+const references: ExplicitPluginReferences = {
578+entries: new Set(),
579+allow: new Set(),
580+deny: new Set(),
581+slots: new Map(),
582+};
583+if (!isRecord(raw) || !isRecord(raw.plugins)) {
584+return references;
585+}
586+const { plugins } = raw;
587+if (isRecord(plugins.entries)) {
588+for (const pluginId of Object.keys(plugins.entries)) {
589+const normalized = normalizePluginId(pluginId);
590+if (normalized) {
591+references.entries.add(normalized);
592+}
593+}
594+}
595+for (const [key, target] of [
596+["allow", references.allow],
597+["deny", references.deny],
598+] as const) {
599+const value = plugins[key];
600+if (!Array.isArray(value)) {
601+continue;
602+}
603+for (const entry of value) {
604+if (typeof entry !== "string") {
605+continue;
606+}
607+const normalized = normalizePluginId(entry);
608+if (normalized) {
609+target.add(normalized);
610+}
611+}
612+}
613+if (isRecord(plugins.slots)) {
614+for (const [slotId, pluginId] of Object.entries(plugins.slots)) {
615+if (typeof pluginId !== "string") {
616+continue;
617+}
618+const normalized = normalizePluginId(pluginId);
619+if (normalized && normalized !== "none") {
620+references.slots.set(normalized, slotId);
621+}
622+}
623+}
624+return references;
625+}
626+627+function resolveExplicitPluginReferencePath(
628+references: ExplicitPluginReferences,
629+pluginId: string,
630+): string | undefined {
631+const normalized = normalizePluginId(pluginId);
632+if (!normalized) {
633+return undefined;
634+}
635+if (references.entries.has(normalized)) {
636+return `plugins.entries.${normalized}`;
637+}
638+if (references.allow.has(normalized)) {
639+return "plugins.allow";
640+}
641+if (references.deny.has(normalized)) {
642+return "plugins.deny";
643+}
644+const slotId = references.slots.get(normalized);
645+if (slotId) {
646+return `plugins.slots.${slotId}`;
647+}
648+return undefined;
649+}
650+570651export const __testing = {
571652 mapZodIssueToConfigIssue,
572653};
@@ -830,6 +911,7 @@ function validateConfigObjectWithPluginsBase(
830911const warnings: ConfigValidationIssue[] = [];
831912const hasExplicitPluginsConfig =
832913isRecord(raw) && Object.prototype.hasOwnProperty.call(raw, "plugins");
914+const explicitPluginReferences = collectExplicitPluginReferences(raw);
833915834916const resolvePluginConfigIssuePath = (pluginId: string, errorPath: string): string => {
835917const base = `plugins.entries.${pluginId}.config`;
@@ -863,13 +945,16 @@ function validateConfigObjectWithPluginsBase(
863945}
864946registryDiagnosticsPushed = true;
865947for (const diag of registry.diagnostics) {
866-let path = diag.pluginId ? `plugins.entries.${diag.pluginId}` : "plugins";
948+const explicitPath = diag.pluginId
949+ ? resolveExplicitPluginReferencePath(explicitPluginReferences, diag.pluginId)
950+ : undefined;
951+let path = explicitPath ?? (diag.pluginId ? "plugins" : "plugins");
867952if (!diag.pluginId && diag.message.includes("plugin path not found")) {
868953path = "plugins.load.paths";
869954}
870955const pluginLabel = diag.pluginId ? `plugin ${diag.pluginId}` : "plugin";
871956const message = `${pluginLabel}: ${diag.message}`;
872-if (diag.level === "error") {
957+if (diag.level === "error" && (explicitPath || !diag.pluginId)) {
873958issues.push({ path, message });
874959} else {
875960warnings.push({ path, message });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。