From 2b45938f77395d63c5f223e9592a09b68b0d4e96 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 5 Jul 2026 13:47:35 +0000 Subject: [PATCH 01/15] docs: update install.sh stable version to 1.2.0 --- docs/public/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/public/install.sh b/docs/public/install.sh index 0a432fa43..87af8cafa 100755 --- a/docs/public/install.sh +++ b/docs/public/install.sh @@ -346,7 +346,7 @@ download_and_install() { } # Version -LATEST_STABLE_VERSION="1.1.7" +LATEST_STABLE_VERSION="1.2.0" if [ -n "${__SPECIFIED_VERSION}" ]; then VERSION="${__SPECIFIED_VERSION}" print_step "Using specified version: ${VERSION}" From aa5ed086f7c1f0e2797c03204e49500427fddd6f Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Sun, 5 Jul 2026 22:58:26 +0900 Subject: [PATCH 02/15] Stabilize diagnostic collection names (#2000) --- crates/tombi-lsp/src/handler/initialize.rs | 1 + editors/vscode/src/options/client-options.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/crates/tombi-lsp/src/handler/initialize.rs b/crates/tombi-lsp/src/handler/initialize.rs index 5d11c99ce..e28416b99 100644 --- a/crates/tombi-lsp/src/handler/initialize.rs +++ b/crates/tombi-lsp/src/handler/initialize.rs @@ -171,6 +171,7 @@ pub fn server_capabilities( ), diagnostic_provider: if backend_capabilities.diagnostic_mode == DiagnosticMode::Pull { Some(DiagnosticServerCapabilities::Options(DiagnosticOptions { + identifier: Some("tombi".to_string()), inter_file_dependencies: false, workspace_diagnostics: true, ..Default::default() diff --git a/editors/vscode/src/options/client-options.ts b/editors/vscode/src/options/client-options.ts index 4201e9c70..9a936fa05 100644 --- a/editors/vscode/src/options/client-options.ts +++ b/editors/vscode/src/options/client-options.ts @@ -9,6 +9,7 @@ export function clientOptions( workspaceFolder?: vscode.WorkspaceFolder, ): languageclient.LanguageClientOptions { const options = { + diagnosticCollectionName: "tombi", documentSelector: SUPPORT_TOML_LANGUAGES.flatMap((language) => [ { scheme: "file", language }, { scheme: "untitled", language }, From aaa0da854bfb33180c188678d1727936bfe6bfb3 Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Sun, 5 Jul 2026 23:34:58 +0900 Subject: [PATCH 03/15] fix(lint): avoid false unused deprecated directive (#2001) --- .../tests/integration/tombi_schema.rs | 19 +++++++++++++++++++ crates/tombi-validator/src/validate/table.rs | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/tombi-linter/tests/integration/tombi_schema.rs b/crates/tombi-linter/tests/integration/tombi_schema.rs index 0a0ca34e6..2e191bc83 100644 --- a/crates/tombi-linter/tests/integration/tombi_schema.rs +++ b/crates/tombi-linter/tests/integration/tombi_schema.rs @@ -182,6 +182,25 @@ test_lint! { ) -> Ok(_) } +test_lint! { + #[test] + fn test_tombi_schema_deprecated_key_disabled_does_not_report_unused_noqa_on_value( + r#" + [extensions] + "tombi-toml/tombi" = { + lsp = { + document-link = { + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = true } + }, + goto-definition.path.enabled = true, + } + } + "#, + SchemaPath(tombi_schema_path()), + ) -> Ok(_) +} + test_lint! { #[test] fn test_tombi_schema_lint_rules_deprecated( diff --git a/crates/tombi-validator/src/validate/table.rs b/crates/tombi-validator/src/validate/table.rs index fe69ae846..17369fa7f 100644 --- a/crates/tombi-validator/src/validate/table.rs +++ b/crates/tombi-validator/src/validate/table.rs @@ -748,7 +748,7 @@ async fn validate_table( } } - if total_diagnostics.is_empty() { + if total_diagnostics.is_empty() && table_schema.deprecation.is_some() { handle_deprecated( &mut total_diagnostics, table_schema.deprecation.as_ref(), From 758aac98b462112f1734ba7a11887266fbda9968 Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Mon, 6 Jul 2026 09:54:57 +0900 Subject: [PATCH 04/15] fix(vscode): make executable settings machine-scoped (#2002) --- editors/vscode/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/editors/vscode/package.json b/editors/vscode/package.json index 8e1c01143..5bf616f7b 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -219,14 +219,14 @@ "string", "null" ], - "scope": "resource", + "scope": "machine", "default": null, "pattern": "^.*tombi(\\.exe)?$" }, "tombi.args": { "description": "Arguments to `tombi` command.", "type": "array", - "scope": "resource", + "scope": "machine", "default": null, "items": { "type": "string", @@ -236,7 +236,7 @@ "tombi.env": { "description": "Environment variables to pass to `tombi` command.", "type": "object", - "scope": "resource", + "scope": "machine", "default": null, "patternProperties": { "^.+$": { From b0da7bc8c246d2c1a0ab308b0b8c19b422f16422 Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Tue, 7 Jul 2026 10:51:43 +0900 Subject: [PATCH 05/15] docs: document deprecationMessage as non-standard support (#2003) --- docs/src/routes/docs/json-schema.mdx | 33 +++++++++++++++++++++------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/docs/src/routes/docs/json-schema.mdx b/docs/src/routes/docs/json-schema.mdx index 1604540a7..5860e1bec 100644 --- a/docs/src/routes/docs/json-schema.mdx +++ b/docs/src/routes/docs/json-schema.mdx @@ -346,6 +346,31 @@ It removes **all file caches** and fetches the latest schema over the network fo VSCode supports associating a TOML schema with a file match pattern. See [VSCode Extension](/docs/editors/vscode-extension#json-schema-association) for details. +## Non-standard Supported Features + +Tombi supports the following features for compatibility with existing schema tooling, even though +they are not part of the JSON Schema specification. + +### deprecationMessage + +`deprecationMessage` is a non-standard keyword originating from the VS Code JSON language service. +Tombi accepts it for compatibility, but only honors it alongside `deprecated: true`. + +When both are present, the `deprecationMessage` string is used as the deprecation diagnostic message +instead of the generic one. A `deprecationMessage` without `deprecated: true` is ignored. + +```json +{ + "properties": { + "old-key": { + "type": "string", + "deprecated": true, + "deprecationMessage": "Use `new-key` instead." + } + } +} +``` + ## Compliance Status The table below summarizes keyword membership in each JSON Schema dialect and whether Tombi @@ -432,14 +457,6 @@ accepted even before draft-2020-12. Some are used as annotations for validation behavior, hover, completion, or diagnostics. - -`deprecationMessage` is a non-standard keyword originating from the VS Code JSON language service -(it is not part of any JSON Schema dialect), and Tombi accepts it for compatibility. It is only -honored alongside `deprecated: true`: when both are present, the `deprecationMessage` string is -used as the deprecation diagnostic message (instead of the generic one). A `deprecationMessage` -without `deprecated: true` is ignored. - - Tombi defaults to a non-standard `strict` behavior: when `additionalProperties` is omitted, objects are treated as closed unless you disable `schema.strict`. From ed489678210ab5d3455f731d5115a613708b2693 Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Wed, 8 Jul 2026 08:03:36 +0900 Subject: [PATCH 06/15] chore: resolve OSV code scanning alerts (#2004) * chore: resolve OSV code scanning alerts * ci: run OSV scanner on main events --- .github/workflows/osv-scanner.yml | 22 ++++++++++++++++++++++ Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- 3 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/osv-scanner.yml diff --git a/.github/workflows/osv-scanner.yml b/.github/workflows/osv-scanner.yml new file mode 100644 index 000000000..da1bd1d28 --- /dev/null +++ b/.github/workflows/osv-scanner.yml @@ -0,0 +1,22 @@ +name: OSV-Scanner + +on: + schedule: + - cron: "25 4 * * 2" + push: + branches: ["main"] + workflow_dispatch: + +permissions: + actions: read + contents: read + security-events: write + +jobs: + scan-scheduled: + uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@b56b5191101d5f27d4787d5583d8d01e9518a7af" # v2.4.0 + with: + scan-args: |- + --include-git-root + -r + ./ diff --git a/Cargo.lock b/Cargo.lock index d09c981c2..ce4214d52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "arbitrary" @@ -507,9 +507,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] @@ -1753,9 +1753,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e" dependencies = [ "bytes", "getrandom 0.3.3", diff --git a/Cargo.toml b/Cargo.toml index 84d52d004..e8762b809 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ license = "MIT" [workspace.dependencies] addr = "0.15.6" -anyhow = "1.0.98" +anyhow = "1.0.103" bytes = "1.11.1" chrono = { version = "0.4.41", features = ["serde"] } clap = { version = "4.5.37", features = ["derive", "env", "string"] } From 536bb36974d9217756c7f9561363e73f5951700a Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Wed, 8 Jul 2026 08:18:30 +0900 Subject: [PATCH 07/15] ci: pin OSV scanner workflow to existing action ref (#2005) --- .github/workflows/osv-scanner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/osv-scanner.yml b/.github/workflows/osv-scanner.yml index da1bd1d28..1e230208a 100644 --- a/.github/workflows/osv-scanner.yml +++ b/.github/workflows/osv-scanner.yml @@ -14,7 +14,7 @@ permissions: jobs: scan-scheduled: - uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@b56b5191101d5f27d4787d5583d8d01e9518a7af" # v2.4.0 + uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@9a498708959aeaef5ef730655706c5a1df1edbc2" # v2.3.8 with: scan-args: |- --include-git-root From 9e9360badd9ba54c4b889b88c7a21849527f5337 Mon Sep 17 00:00:00 2001 From: Taku Kodama <79110363+risu729@users.noreply.github.com> Date: Thu, 16 Jul 2026 13:02:42 +1000 Subject: [PATCH 08/15] fix(validator): report not schema resolution errors (#2007) * test(validator): cover unresolved not schema refs * fix(validator): report not schema resolution errors * fix(validator): address not schema review findings * test(lsp): update schema path completion --------- Co-authored-by: ya7010 --- crates/tombi-linter/tests/integration.rs | 2 + .../tests/integration/not_schema.rs | 54 +++++++++++++++++++ .../tombi-lsp/tests/test_completion_labels.rs | 1 + .../src/validate/not_schema.rs | 44 +++++++++------ schemas/not-schema-test.schema.json | 24 +++++++++ 5 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 crates/tombi-linter/tests/integration/not_schema.rs create mode 100644 schemas/not-schema-test.schema.json diff --git a/crates/tombi-linter/tests/integration.rs b/crates/tombi-linter/tests/integration.rs index 6c38b6401..edd486973 100644 --- a/crates/tombi-linter/tests/integration.rs +++ b/crates/tombi-linter/tests/integration.rs @@ -28,6 +28,8 @@ mod json_schema_test_suite; mod min_max_contains_test_schema; #[path = "integration/non_schema.rs"] mod non_schema; +#[path = "integration/not_schema.rs"] +mod not_schema; #[path = "integration/other_schema.rs"] mod other_schema; #[path = "integration/prefix_items_test_schema.rs"] diff --git a/crates/tombi-linter/tests/integration/not_schema.rs b/crates/tombi-linter/tests/integration/not_schema.rs new file mode 100644 index 000000000..91ab7fe57 --- /dev/null +++ b/crates/tombi-linter/tests/integration/not_schema.rs @@ -0,0 +1,54 @@ +use tombi_diagnostic::Level; +use tombi_linter::test_lint; + +fn schema_path() -> std::path::PathBuf { + tombi_test_lib::project_root_path() + .join("schemas") + .join("not-schema-test.schema.json") +} + +test_lint! { + #[test] + fn test_invalid_ref_reports_error_diagnostic( + r#" + value = "foo" + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_inline_not_rejects_matching_value( + r#" + inline = "foo" + "#, + SchemaPath(schema_path()), + ) -> Err([ + tombi_validator::DiagnosticKind::NotSchemaMatch + ]) +} + +test_lint! { + #[test] + fn test_inline_not_accepts_non_matching_value( + r#" + inline = "bar" + "#, + SchemaPath(schema_path()), + ) -> Ok(_) +} + +test_lint! { + #[test] + fn test_inline_not_treats_warning_only_result_as_match( + r#" + warning = "foo" + "#, + SchemaPath(schema_path()), + ) -> Err([ + tombi_validator::DiagnosticKind::NotSchemaMatch + ]) +} diff --git a/crates/tombi-lsp/tests/test_completion_labels.rs b/crates/tombi-lsp/tests/test_completion_labels.rs index 358eb40cd..a10438fb8 100644 --- a/crates/tombi-lsp/tests/test_completion_labels.rs +++ b/crates/tombi-lsp/tests/test_completion_labels.rs @@ -740,6 +740,7 @@ mod completion_labels { "issue-1895-rustfmt-like.schema.json", "lsp-consistency-test.schema.json", "min-max-contains-test.schema.json", + "not-schema-test.schema.json", "one-of-hover-discriminator-test.schema.json", "partial-taskipy.schema.json", "prefix-items-test.schema.json", diff --git a/crates/tombi-validator/src/validate/not_schema.rs b/crates/tombi-validator/src/validate/not_schema.rs index 4f29363d5..f5f8de4ca 100644 --- a/crates/tombi-validator/src/validate/not_schema.rs +++ b/crates/tombi-validator/src/validate/not_schema.rs @@ -3,7 +3,10 @@ use tombi_document_tree::ValueImpl; use tombi_schema_store::{CurrentSchema, SchemaContext}; use tombi_severity_level::SeverityLevelDefaultError; -use crate::{Validate, validate::handle_unused_noqa}; +use crate::{ + Validate, + validate::{handle_unused_noqa, is_assertion_success}, +}; pub async fn validate_not<'a, T>( value: &T, @@ -17,22 +20,31 @@ pub async fn validate_not<'a, T>( where T: Validate + ValueImpl + Sync + Send, { - if let Ok(Some(current_schema)) = not_schema - .schema - .write() - .await - .resolve( - current_schema.schema_uri.clone(), - current_schema.definitions.clone(), - schema_context.store, - ) - .await - .inspect_err(|err| log::warn!("{err}")) - && value - .validate(accessors, Some(¤t_schema), schema_context) - .await - .is_ok() + let matches_not_schema = match tombi_schema_store::resolve_schema_item( + ¬_schema.schema, + current_schema.schema_uri.clone(), + current_schema.definitions.clone(), + schema_context.store, + ) + .await { + Ok(Some(current_schema)) => is_assertion_success( + &value + .validate(accessors, Some(¤t_schema), schema_context) + .await, + ), + Ok(None) => false, + Err(err) => { + return Err(vec![tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + value.range(), + )] + .into()); + } + }; + + if matches_not_schema { let mut diagnostics = Vec::with_capacity(1); crate::Diagnostic { kind: Box::new(crate::DiagnosticKind::NotSchemaMatch), diff --git a/schemas/not-schema-test.schema.json b/schemas/not-schema-test.schema.json new file mode 100644 index 000000000..13831d506 --- /dev/null +++ b/schemas/not-schema-test.schema.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "value": { + "type": "string", + "not": { + "$ref": "#/$defs/missing" + } + }, + "inline": { + "type": "string", + "not": { + "pattern": "^foo$" + } + }, + "warning": { + "type": "string", + "not": { + "deprecated": true + } + } + } +} From 1ea3ac2dee54f4d36acdc7a6f0afac91f9ef5371 Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Thu, 16 Jul 2026 13:09:28 +0900 Subject: [PATCH 09/15] test(lsp): remove brittle schema path completion test (#2009) --- .../tombi-lsp/tests/test_completion_labels.rs | 59 ------------------- 1 file changed, 59 deletions(-) diff --git a/crates/tombi-lsp/tests/test_completion_labels.rs b/crates/tombi-lsp/tests/test_completion_labels.rs index a10438fb8..de9821b63 100644 --- a/crates/tombi-lsp/tests/test_completion_labels.rs +++ b/crates/tombi-lsp/tests/test_completion_labels.rs @@ -708,65 +708,6 @@ mod completion_labels { ]); } - test_completion_labels! { - #[tokio::test] - async fn tombi_schemars_path_file_completion( - r#" - [[schemas]] - path = "█" - "#, - SourcePath(project_root_path().join("schemas").join("tombi.toml")), - SchemaPath(tombi_schema_path()), - ) -> Ok([ - "additional-properties-branch-keys-test.schema.json", - "adjacent-applicators-test.schema.json", - "adjacent-one-of-additional-properties-test.schema.json", - "adjacent-one-of-hover-test.schema.json", - "anchor-dynamic-ref-test.schema.json", - "anchor-table-test.schema.json", - "array-const-enum-test.schema.json", - "contains-test.schema.json", - "dependencies-strict-mode-test.schema.json", - "dependencies-test.schema.json", - "dependent-required-test.schema.json", - "dependent-schemas-test.schema.json", - "deprecated-test.schema.json", - "exact-index-hover-test.schema.json", - "exact-index-override-test.schema.json", - "exact-index-string-test.schema.json", - "format-annotation-test.schema.json", - "format-assertion-vocab-test.schema.json", - "if-then-else-test.schema.json", - "issue-1895-rustfmt-like.schema.json", - "lsp-consistency-test.schema.json", - "min-max-contains-test.schema.json", - "not-schema-test.schema.json", - "one-of-hover-discriminator-test.schema.json", - "partial-taskipy.schema.json", - "prefix-items-test.schema.json", - "recursive-anchor-ref-test.schema.json", - "recursive-defs-any-of-test.schema.json", - "recursive-schema.schema.json", - "ref-sibling-annotations-test.schema.json", - "root-ref-test.schema.json", - "string-format-test.schema.json", - "subschema-singleton-label-test.schema.json", - "table-const-enum-test.schema.json", - "tuple-items-test.schema.json", - "type-test.schema.json", - "unevaluated-items-test.schema.json", - "unevaluated-properties-branch-additional-test.schema.json", - "unevaluated-properties-test.schema.json", - "untagged-union.schema.json", - "x-tombi-table-keys-order.schema.json", - "\"https://www.schemastore.org/cargo.json\"", - "\"https://www.schemastore.org/pyproject.json\"", - "\"tombi://www.schemastore.org/cargo.json\"", - "\"tombi://www.schemastore.org/pyproject.json\"", - "\"tombi://www.schemastore.org/tombi.json\"", - ]); - } - test_completion_labels! { #[tokio::test] async fn tombi_schemars_path_file_completion_from_dot_config_project_root( From 9d92045c02e18fefa485cef20a87935aef5526cd Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Thu, 16 Jul 2026 17:25:13 +0900 Subject: [PATCH 10/15] fix(validator): report schema resolution errors (#2010) * fix(validator): report schema resolution errors * fix: satisfy Rust 1.97 clippy --- crates/tombi-extension/src/completion.rs | 2 +- crates/tombi-linter/tests/integration.rs | 2 + .../integration/schema_resolution_error.rs | 241 +++++++++++++ .../tombi-lsp/src/completion/value/table.rs | 4 +- crates/tombi-schema-store/src/schema.rs | 4 +- .../src/schema/referable_schema.rs | 42 ++- crates/tombi-validator/src/validate/all_of.rs | 23 +- crates/tombi-validator/src/validate/any_of.rs | 23 +- crates/tombi-validator/src/validate/array.rs | 160 ++++++--- .../src/validate/if_then_else.rs | 77 +++-- crates/tombi-validator/src/validate/one_of.rs | 40 ++- crates/tombi-validator/src/validate/table.rs | 325 +++++++++++------- rust/serde_tombi/src/config.rs | 12 +- rust/tombi-cli/src/app/command/format.rs | 2 +- .../schema-resolution-error-test.schema.json | 144 ++++++++ 15 files changed, 842 insertions(+), 259 deletions(-) create mode 100644 crates/tombi-linter/tests/integration/schema_resolution_error.rs create mode 100644 schemas/schema-resolution-error-test.schema.json diff --git a/crates/tombi-extension/src/completion.rs b/crates/tombi-extension/src/completion.rs index 993536034..9d037cd85 100644 --- a/crates/tombi-extension/src/completion.rs +++ b/crates/tombi-extension/src/completion.rs @@ -512,7 +512,7 @@ impl FromLsp for tower_lsp::lsp_types::CompletionItem { ) -> tower_lsp::lsp_types::CompletionItem { const SECTION_SEPARATOR: &str = "-----"; - let sorted_text = format!("{}_{}", source.priority.as_prefix(), &source.label); + let sorted_text = format!("{}_{}", source.priority.as_prefix(), source.label); let mut schema_text = None; if let Some(schema_uri) = &source.schema_uri { diff --git a/crates/tombi-linter/tests/integration.rs b/crates/tombi-linter/tests/integration.rs index edd486973..40de5ee0c 100644 --- a/crates/tombi-linter/tests/integration.rs +++ b/crates/tombi-linter/tests/integration.rs @@ -38,6 +38,8 @@ mod prefix_items_test_schema; mod recursive_anchor_ref_test_schema; #[path = "integration/recursive_defs_any_of_test_schema.rs"] mod recursive_defs_any_of_test_schema; +#[path = "integration/schema_resolution_error.rs"] +mod schema_resolution_error; #[path = "integration/string_format_test_schema.rs"] mod string_format_test_schema; #[path = "integration/table_const_enum_test_schema.rs"] diff --git a/crates/tombi-linter/tests/integration/schema_resolution_error.rs b/crates/tombi-linter/tests/integration/schema_resolution_error.rs new file mode 100644 index 000000000..52136af04 --- /dev/null +++ b/crates/tombi-linter/tests/integration/schema_resolution_error.rs @@ -0,0 +1,241 @@ +use tombi_diagnostic::Level; +use tombi_linter::test_lint; + +fn schema_path() -> std::path::PathBuf { + tombi_test_lib::project_root_path() + .join("schemas") + .join("schema-resolution-error-test.schema.json") +} + +test_lint! { + #[test] + fn test_property_schema_resolution_error( + r#" + direct = 1 + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_all_of_schema_resolution_error( + r#" + all-of-error = 1 + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_any_of_schema_resolution_error( + r#" + any-of-error = 1 + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_one_of_schema_resolution_error( + r#" + one-of-error = 1 + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_if_schema_resolution_error( + r#" + if-error = {} + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_then_schema_resolution_error( + r#" + then-error = {} + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_else_schema_resolution_error( + r#" + else-error = {} + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_items_schema_resolution_error( + r#" + items-error = [1] + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_prefix_items_schema_resolution_error( + r#" + prefix-items-error = [1] + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_overflow_items_schema_resolution_error( + r#" + overflow-items-error = [1, 2] + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_overflow_items_schema_not_applied( + r#" + overflow-items-error = [1] + "#, + SchemaPath(schema_path()), + ) -> Ok(_) +} + +test_lint! { + #[test] + fn test_contains_schema_resolution_error( + r#" + contains-error = [1] + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_unevaluated_items_schema_resolution_error( + r#" + unevaluated-items-error = [1] + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_pattern_property_schema_resolution_error( + r#" + [pattern-properties-error] + pat-key = 1 + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_additional_property_schema_resolution_error( + r#" + [additional-properties-error] + extra = 1 + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_unevaluated_property_schema_resolution_error( + r#" + [unevaluated-properties-error] + extra = 1 + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR }, + { code: "table-strict-additional-keys", level: Level::WARNING } + ]) +} + +test_lint! { + #[test] + fn test_property_names_schema_resolution_error( + r#" + [property-names-error] + key = 1 + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_dependency_schema_resolution_error( + r#" + [dependencies-error] + trigger = "x" + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} + +test_lint! { + #[test] + fn test_dependent_schema_resolution_error( + r#" + [dependent-schemas-error] + trigger = "x" + "#, + SchemaPath(schema_path()), + ) -> Diagnostics([ + { code: "invalid-json-pointer", level: Level::ERROR } + ]) +} diff --git a/crates/tombi-lsp/src/completion/value/table.rs b/crates/tombi-lsp/src/completion/value/table.rs index a3f0adc3e..292833c22 100644 --- a/crates/tombi-lsp/src/completion/value/table.rs +++ b/crates/tombi-lsp/src/completion/value/table.rs @@ -248,7 +248,7 @@ impl FindCompletionContents for tombi_document_tree::Table { { log::trace!( "property_schema = {:?}", - ¤t_schema.value_schema + current_schema.value_schema ); let Some(mut contents) = @@ -311,7 +311,7 @@ impl FindCompletionContents for tombi_document_tree::Table { if pattern.is_match(accessor_str) { log::trace!( "pattern_property_schema = {:?}", - ¤t_schema.value_schema + current_schema.value_schema ); if let Ok(Some(current_schema)) = table_schema .resolve_pattern_property_schema( diff --git a/crates/tombi-schema-store/src/schema.rs b/crates/tombi-schema-store/src/schema.rs index c5579846e..4bfb84155 100644 --- a/crates/tombi-schema-store/src/schema.rs +++ b/crates/tombi-schema-store/src/schema.rs @@ -42,8 +42,8 @@ pub use not_schema::NotSchema; pub use offset_date_time_schema::OffsetDateTimeSchema; pub use one_of_schema::OneOfSchema; pub use referable_schema::{ - CurrentSchema, Referable, is_online_url, resolve_and_collect_schemas, resolve_json_pointer, - resolve_schema_item, + CurrentSchema, Referable, is_online_url, resolve_and_collect_schemas, + resolve_and_collect_schemas_with_errors, resolve_json_pointer, resolve_schema_item, }; pub use schema_context::{ResolvedFormatOrder, SchemaContext}; pub use schema_cycle_guard::{SchemaCycleGuard, SchemaVisits}; diff --git a/crates/tombi-schema-store/src/schema/referable_schema.rs b/crates/tombi-schema-store/src/schema/referable_schema.rs index f696279c8..c5fb9fe3e 100644 --- a/crates/tombi-schema-store/src/schema/referable_schema.rs +++ b/crates/tombi-schema-store/src/schema/referable_schema.rs @@ -692,19 +692,45 @@ fn is_plain_name_fragment(fragment: &str) -> bool { !fragment.is_empty() && !fragment.contains('/') } +pub async fn resolve_and_collect_schemas( + schemas: &super::ReferableValueSchemas, + schema_uri: Cow<'_, SchemaUri>, + definitions: Cow<'_, SchemaDefinitions>, + schema_store: &crate::SchemaStore, + schema_visits: &crate::SchemaVisits, + accessors: &[crate::Accessor], +) -> Option>> { + let (collected, errors) = resolve_and_collect_schemas_with_errors( + schemas, + schema_uri, + definitions, + schema_store, + schema_visits, + accessors, + ) + .await?; + + for err in errors { + log::warn!("{err}"); + } + + Some(collected) +} + /// Two-path schema collection: tries a read lock first for already-resolved schemas, /// resolves refs on cloned entries, and writes back only newly-resolved entries. /// +/// Returns the successfully resolved schemas together with any resolution errors. /// Returns `None` when schema traversal is re-entrant (cycle guard) or when /// an initial read lock cannot be acquired due to concurrent mutation. -pub async fn resolve_and_collect_schemas( +pub async fn resolve_and_collect_schemas_with_errors( schemas: &super::ReferableValueSchemas, schema_uri: Cow<'_, SchemaUri>, definitions: Cow<'_, SchemaDefinitions>, schema_store: &crate::SchemaStore, schema_visits: &crate::SchemaVisits, accessors: &[crate::Accessor], -) -> Option>> { +) -> Option<(Vec>, Vec)> { let Some(_cycle_guard) = schema_visits.get_cycle_guard(schemas) else { log::debug!( "detected composite schema cycle while collecting schemas: schema_uri={schema_uri} accessors={accessors} reason=reentrant_schema_traversal", @@ -749,6 +775,7 @@ pub async fn resolve_and_collect_schemas( // Build output from read result and avoid cloning the whole referable vector. if let Some(resolved_schemas) = resolved_schemas { let mut collected = Vec::with_capacity(resolved_schemas.len()); + let mut errors = Vec::new(); let default_schema_uri = schema_uri.as_ref().clone(); let default_definitions = definitions.clone().into_owned(); @@ -765,7 +792,7 @@ pub async fn resolve_and_collect_schemas( ), Ok(None) => (default_schema_uri.clone(), default_definitions.clone()), Err(err) => { - log::warn!("{err}"); + errors.push(err); continue; } } @@ -780,11 +807,12 @@ pub async fn resolve_and_collect_schemas( }); } - return Some(collected); + return Some((collected, errors)); } // Slow path: unresolved refs exist. Resolve on cloned entries and cache back. let mut collected = Vec::with_capacity(schema_entries.len()); + let mut errors = Vec::new(); let mut resolved_indices = Vec::new(); for (index, referable_schema) in schema_entries.iter_mut().enumerate() { let was_ref = referable_schema.is_ref(); @@ -795,7 +823,7 @@ pub async fn resolve_and_collect_schemas( Ok(Some(current_schema)) => collected.push(current_schema.into_owned()), Ok(None) => {} Err(err) => { - log::warn!("{err}"); + errors.push(err); } } @@ -812,7 +840,7 @@ pub async fn resolve_and_collect_schemas( schema_uri = schema_uri.as_ref(), accessors = crate::Accessors::from(accessors.to_vec()) ); - return Some(collected); + return Some((collected, errors)); }; for index in resolved_indices { @@ -826,7 +854,7 @@ pub async fn resolve_and_collect_schemas( } } - Some(collected) + Some((collected, errors)) } /// Resolve a schema item without holding its write lock across await points. diff --git a/crates/tombi-validator/src/validate/all_of.rs b/crates/tombi-validator/src/validate/all_of.rs index ba21e6ef3..35291be5d 100644 --- a/crates/tombi-validator/src/validate/all_of.rs +++ b/crates/tombi-validator/src/validate/all_of.rs @@ -33,19 +33,24 @@ where let mut total_score = 0; let mut evaluated_locations = crate::EvaluatedLocations::new(); - let Some(resolved_schemas) = tombi_schema_store::resolve_and_collect_schemas( - &all_of_schema.schemas, - current_schema.schema_uri.clone(), - current_schema.definitions.clone(), - schema_context.store, - &schema_context.schema_visits, - accessors, - ) - .await + let Some((resolved_schemas, resolution_errors)) = + tombi_schema_store::resolve_and_collect_schemas_with_errors( + &all_of_schema.schemas, + current_schema.schema_uri.clone(), + current_schema.definitions.clone(), + schema_context.store, + &schema_context.schema_visits, + accessors, + ) + .await else { return Ok(crate::EvaluatedLocations::new()); }; + total_diagnostics.extend(resolution_errors.into_iter().map(|err| { + tombi_diagnostic::Diagnostic::new_error(err.to_string(), err.code(), value.range()) + })); + for resolved_schema in &resolved_schemas { match value .validate(accessors, Some(resolved_schema), schema_context) diff --git a/crates/tombi-validator/src/validate/any_of.rs b/crates/tombi-validator/src/validate/any_of.rs index acbcf6304..f05ac0bf9 100644 --- a/crates/tombi-validator/src/validate/any_of.rs +++ b/crates/tombi-validator/src/validate/any_of.rs @@ -66,15 +66,16 @@ where } } - let Some(resolved_schemas) = tombi_schema_store::resolve_and_collect_schemas( - &any_of_schema.schemas, - current_schema.schema_uri.clone(), - current_schema.definitions.clone(), - schema_context.store, - &schema_context.schema_visits, - accessors, - ) - .await + let Some((resolved_schemas, resolution_errors)) = + tombi_schema_store::resolve_and_collect_schemas_with_errors( + &any_of_schema.schemas, + current_schema.schema_uri.clone(), + current_schema.definitions.clone(), + schema_context.store, + &schema_context.schema_visits, + accessors, + ) + .await else { if total_diagnostics.is_empty() { return Ok(base_evaluated_locations); @@ -87,6 +88,10 @@ where } }; + total_diagnostics.extend(resolution_errors.into_iter().map(|err| { + tombi_diagnostic::Diagnostic::new_error(err.to_string(), err.code(), value.range()) + })); + let mut total_error = crate::Error::new(); let mut matched = false; let mut matched_diagnostics = Vec::new(); diff --git a/crates/tombi-validator/src/validate/array.rs b/crates/tombi-validator/src/validate/array.rs index f98bb6398..60d76a20d 100644 --- a/crates/tombi-validator/src/validate/array.rs +++ b/crates/tombi-validator/src/validate/array.rs @@ -150,34 +150,39 @@ async fn validate_array( } if let Some(prefix_items) = &array_schema.prefix_items { - // Resolve the overflow schema once before the loop - let overflow_schema = - if let Some(additional_items_schema) = &array_schema.additional_items_schema { - tombi_schema_store::resolve_schema_item( - additional_items_schema, - current_schema.schema_uri.clone(), - current_schema.definitions.clone(), - schema_context.store, - ) - .await - .inspect_err(|err| log::warn!("{err}")) - .ok() - .flatten() - } else if let Some(items) = &array_schema.items { - // 2020-12: items acts as additionalItems when prefixItems is present - tombi_schema_store::resolve_schema_item( - items, - current_schema.schema_uri.clone(), - current_schema.definitions.clone(), - schema_context.store, - ) - .await - .inspect_err(|err| log::warn!("{err}")) - .ok() - .flatten() - } else { - None - }; + // Resolve the overflow schema once before the loop. + // 2020-12: items acts as additionalItems when prefixItems is present. + let overflow_schema = if array_value.values().len() > prefix_items.len() { + match array_schema + .additional_items_schema + .as_ref() + .or(array_schema.items.as_ref()) + { + Some(overflow_item) => { + match tombi_schema_store::resolve_schema_item( + overflow_item, + current_schema.schema_uri.clone(), + current_schema.definitions.clone(), + schema_context.store, + ) + .await + { + Ok(overflow_schema) => overflow_schema, + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + array_value.range(), + )); + None + } + } + } + None => None, + } + } else { + None + }; // Tuple validation: validate each element against its positional schema for (index, value) in array_value.values().iter().enumerate() { @@ -189,19 +194,30 @@ async fn validate_array( if index < prefix_items.len() { evaluated[index] = true; - if let Ok(Some(item_schema)) = tombi_schema_store::resolve_schema_item( + match tombi_schema_store::resolve_schema_item( &prefix_items[index], current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) - && let Err(crate::Error { diagnostics, .. }) = value - .validate(&new_accessors, Some(&item_schema), schema_context) - .await { - total_diagnostics.extend(diagnostics); + Ok(Some(item_schema)) => { + if let Err(crate::Error { diagnostics, .. }) = value + .validate(&new_accessors, Some(&item_schema), schema_context) + .await + { + total_diagnostics.extend(diagnostics); + } + } + Ok(None) => {} + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + value.range(), + )); + } } } else if let Some(overflow) = &overflow_schema { evaluated[index] = true; @@ -229,43 +245,65 @@ async fn validate_array( } } else if let Some(items) = &array_schema.items { // Single schema for all items - if let Ok(Some(current_schema)) = tombi_schema_store::resolve_schema_item( + match tombi_schema_store::resolve_schema_item( items, current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) { - for (index, value) in array_value.values().iter().enumerate() { - evaluated[index] = true; - let new_accessors = accessors - .iter() - .cloned() - .chain(std::iter::once(tombi_schema_store::Accessor::Index(index))) - .collect_vec(); - - if let Err(crate::Error { diagnostics, .. }) = value - .validate(&new_accessors, Some(¤t_schema), schema_context) - .await - { - total_diagnostics.extend(diagnostics); + Ok(Some(current_schema)) => { + for (index, value) in array_value.values().iter().enumerate() { + evaluated[index] = true; + let new_accessors = accessors + .iter() + .cloned() + .chain(std::iter::once(tombi_schema_store::Accessor::Index(index))) + .collect_vec(); + + if let Err(crate::Error { diagnostics, .. }) = value + .validate(&new_accessors, Some(¤t_schema), schema_context) + .await + { + total_diagnostics.extend(diagnostics); + } } } + Ok(None) => {} + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + array_value.range(), + )); + } } } - if let Some(contains) = &array_schema.contains - && let Ok(Some(contains_schema)) = tombi_schema_store::resolve_schema_item( + let contains_schema = match &array_schema.contains { + Some(contains) => match tombi_schema_store::resolve_schema_item( contains, current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) - { + { + Ok(contains_schema) => contains_schema, + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + array_value.range(), + )); + None + } + }, + None => None, + }; + + if let Some(contains_schema) = contains_schema { let min_contains = array_schema.min_contains.unwrap_or(1); let max_contains = array_schema.max_contains; let needs_full_count = max_contains.is_some() || has_unevaluated_items; @@ -342,16 +380,24 @@ async fn validate_array( // Run unevaluatedItems after all applicators that can mark items as evaluated. if has_unevaluated_items { let unevaluated_schema = if let Some(schema_item) = &array_schema.unevaluated_items_schema { - tombi_schema_store::resolve_schema_item( + match tombi_schema_store::resolve_schema_item( schema_item, current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) - .ok() - .flatten() + { + Ok(unevaluated_schema) => unevaluated_schema, + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + array_value.range(), + )); + None + } + } } else { None }; diff --git a/crates/tombi-validator/src/validate/if_then_else.rs b/crates/tombi-validator/src/validate/if_then_else.rs index 5505156ef..4f7876079 100644 --- a/crates/tombi-validator/src/validate/if_then_else.rs +++ b/crates/tombi-validator/src/validate/if_then_else.rs @@ -32,57 +32,90 @@ where }; // Resolve and validate the `if` schema - let if_result = if let Ok(Some(if_current_schema)) = tombi_schema_store::resolve_schema_item( + let if_result = match tombi_schema_store::resolve_schema_item( &if_then_else_schema.if_schema, current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) { - value - .validate(accessors, Some(&if_current_schema), schema_context) - .await - } else { - return Ok(crate::EvaluatedLocations::new()); + Ok(Some(if_current_schema)) => { + value + .validate(accessors, Some(&if_current_schema), schema_context) + .await + } + Ok(None) => return Ok(crate::EvaluatedLocations::new()), + Err(err) => { + return Err(vec![tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + value.range(), + )] + .into()); + } }; // Per JSON Schema spec: branching is based on assertion result. if is_assertion_success(&if_result) { // `if` matched → apply `then` schema if present - if let Some(then_schema) = &if_then_else_schema.then_schema - && let Ok(Some(then_current_schema)) = tombi_schema_store::resolve_schema_item( + if let Some(then_schema) = &if_then_else_schema.then_schema { + match tombi_schema_store::resolve_schema_item( then_schema, current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) - { - let branch_result = value - .validate(accessors, Some(&then_current_schema), schema_context) - .await; - return merge_if_result(branch_result, if_result); + { + Ok(Some(then_current_schema)) => { + let branch_result = value + .validate(accessors, Some(&then_current_schema), schema_context) + .await; + return merge_if_result(branch_result, if_result); + } + Ok(None) => {} + Err(err) => { + return merge_if_result( + Err(vec![tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + value.range(), + )] + .into()), + if_result, + ); + } + } } return merge_if_result(Ok(crate::EvaluatedLocations::new()), if_result); } else { // `if` did not match → apply `else` schema if present - if let Some(else_schema) = &if_then_else_schema.else_schema - && let Ok(Some(else_current_schema)) = tombi_schema_store::resolve_schema_item( + if let Some(else_schema) = &if_then_else_schema.else_schema { + match tombi_schema_store::resolve_schema_item( else_schema, Cow::Borrowed(current_schema.schema_uri.as_ref()), Cow::Borrowed(current_schema.definitions.as_ref()), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) - { - return value - .validate(accessors, Some(&else_current_schema), schema_context) - .await; + { + Ok(Some(else_current_schema)) => { + return value + .validate(accessors, Some(&else_current_schema), schema_context) + .await; + } + Ok(None) => {} + Err(err) => { + return Err(vec![tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + value.range(), + )] + .into()); + } + } } } diff --git a/crates/tombi-validator/src/validate/one_of.rs b/crates/tombi-validator/src/validate/one_of.rs index 718a7f907..a939340d3 100644 --- a/crates/tombi-validator/src/validate/one_of.rs +++ b/crates/tombi-validator/src/validate/one_of.rs @@ -66,15 +66,16 @@ where let mut valid_count = 0; - let Some(resolved_schemas) = tombi_schema_store::resolve_and_collect_schemas( - &one_of_schema.schemas, - current_schema.schema_uri.clone(), - current_schema.definitions.clone(), - schema_context.store, - &schema_context.schema_visits, - accessors, - ) - .await + let Some((resolved_schemas, resolution_errors)) = + tombi_schema_store::resolve_and_collect_schemas_with_errors( + &one_of_schema.schemas, + current_schema.schema_uri.clone(), + current_schema.definitions.clone(), + schema_context.store, + &schema_context.schema_visits, + accessors, + ) + .await else { if total_diagnostics.is_empty() { return Ok(base_evaluated_locations); @@ -86,16 +87,23 @@ where }); } }; + let has_resolution_errors = !resolution_errors.is_empty(); + total_diagnostics.extend(resolution_errors.into_iter().map(|err| { + tombi_diagnostic::Diagnostic::new_error(err.to_string(), err.code(), value.range()) + })); + let total_count = resolved_schemas.len(); if total_count == 0 { - crate::Diagnostic { - kind: Box::new(crate::DiagnosticKind::OneOfNoMatch { total_count }), - range: value.range(), + if !has_resolution_errors { + crate::Diagnostic { + kind: Box::new(crate::DiagnosticKind::OneOfNoMatch { total_count }), + range: value.range(), + } + .push_diagnostic_with_level( + SeverityLevelDefaultError::default(), + &mut total_diagnostics, + ); } - .push_diagnostic_with_level( - SeverityLevelDefaultError::default(), - &mut total_diagnostics, - ); return Err(crate::Error { score: crate::error::TYPE_MATCHED_SCORE, diagnostics: total_diagnostics, diff --git a/crates/tombi-validator/src/validate/table.rs b/crates/tombi-validator/src/validate/table.rs index 17369fa7f..5d0fcbd46 100644 --- a/crates/tombi-validator/src/validate/table.rs +++ b/crates/tombi-validator/src/validate/table.rs @@ -178,7 +178,7 @@ async fn validate_table( { matched_key = true; - if let Ok(Some(current_schema)) = table_schema + match table_schema .resolve_property_schema( &schema_accessor, current_schema.schema_uri.clone(), @@ -186,17 +186,33 @@ async fn validate_table( schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) - && let Err(crate::Error { - mut diagnostics, .. - }) = value - .validate(&new_accessors, Some(¤t_schema), schema_context) - .await { - convert_deprecated_diagnostics_range(¤t_schema, value, key, &mut diagnostics) - .await; + Ok(Some(current_schema)) => { + if let Err(crate::Error { + mut diagnostics, .. + }) = value + .validate(&new_accessors, Some(¤t_schema), schema_context) + .await + { + convert_deprecated_diagnostics_range( + ¤t_schema, + value, + key, + &mut diagnostics, + ) + .await; - total_diagnostics.extend(diagnostics); + total_diagnostics.extend(diagnostics); + } + } + Ok(None) => {} + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + key.range() + value.range(), + )); + } } } @@ -214,7 +230,7 @@ async fn validate_table( }; if pattern.is_match(accessor_raw_text) { matched_key = true; - if let Ok(Some(current_schema)) = table_schema + match table_schema .resolve_pattern_property_schema( &pattern_key, current_schema.schema_uri.clone(), @@ -222,22 +238,33 @@ async fn validate_table( schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) - && let Err(crate::Error { - mut diagnostics, .. - }) = value - .validate(&new_accessors, Some(¤t_schema), schema_context) - .await { - convert_deprecated_diagnostics_range( - ¤t_schema, - value, - key, - &mut diagnostics, - ) - .await; - - total_diagnostics.extend(diagnostics); + Ok(Some(current_schema)) => { + if let Err(crate::Error { + mut diagnostics, .. + }) = value + .validate(&new_accessors, Some(¤t_schema), schema_context) + .await + { + convert_deprecated_diagnostics_range( + ¤t_schema, + value, + key, + &mut diagnostics, + ) + .await; + + total_diagnostics.extend(diagnostics); + } + } + Ok(None) => {} + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + key.range() + value.range(), + )); + } } } } @@ -284,34 +311,45 @@ async fn validate_table( let mut validated_by_additional_schema = false; if let Some((_, referable_additional_property_schema)) = &table_schema.additional_property_schema - && let Ok(Some(current_schema)) = tombi_schema_store::resolve_schema_item( + { + match tombi_schema_store::resolve_schema_item( referable_additional_property_schema, current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) - { - let deprecation = current_schema.value_schema.deprecation().await; - handle_deprecated_value( - &mut total_diagnostics, - deprecation.as_ref(), - &new_accessors, - value, - Some(¤t_schema), - schema_context, - table_value.comment_directives(), - table_rules.as_ref().map(|rules| &rules.common), - ); - - if let Err(crate::Error { diagnostics, .. }) = value - .validate(&new_accessors, Some(¤t_schema), schema_context) - .await { - total_diagnostics.extend(diagnostics); + Ok(Some(current_schema)) => { + let deprecation = current_schema.value_schema.deprecation().await; + handle_deprecated_value( + &mut total_diagnostics, + deprecation.as_ref(), + &new_accessors, + value, + Some(¤t_schema), + schema_context, + table_value.comment_directives(), + table_rules.as_ref().map(|rules| &rules.common), + ); + + if let Err(crate::Error { diagnostics, .. }) = value + .validate(&new_accessors, Some(¤t_schema), schema_context) + .await + { + total_diagnostics.extend(diagnostics); + } + validated_by_additional_schema = true; + } + Ok(None) => {} + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + key.range() + value.range(), + )); + } } - validated_by_additional_schema = true; } // `additionalProperties` contributes to evaluated properties only when the keyword exists. @@ -322,23 +360,33 @@ async fn validate_table( && !validated_by_additional_schema && !evaluated_by_additional_default { - if let Some(schema_item) = &table_schema.unevaluated_property_schema - && let Ok(Some(unevaluated_schema)) = tombi_schema_store::resolve_schema_item( + if let Some(schema_item) = &table_schema.unevaluated_property_schema { + match tombi_schema_store::resolve_schema_item( schema_item, current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) - { - if let Err(crate::Error { diagnostics, .. }) = value - .validate(&new_accessors, Some(&unevaluated_schema), schema_context) - .await { - total_diagnostics.extend(diagnostics); + Ok(Some(unevaluated_schema)) => { + if let Err(crate::Error { diagnostics, .. }) = value + .validate(&new_accessors, Some(&unevaluated_schema), schema_context) + .await + { + total_diagnostics.extend(diagnostics); + } + continue; + } + Ok(None) => {} + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + key.range() + value.range(), + )); + } } - continue; } if table_schema.unevaluated_properties == Some(false) { @@ -545,37 +593,46 @@ async fn validate_table( } } tombi_schema_store::Dependency::Schema(schema_item) => { - if let Ok(Some(dep_schema)) = tombi_schema_store::resolve_schema_item( + match tombi_schema_store::resolve_schema_item( schema_item, current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) { - // A dependency schema is an additional constraint layered on top of - // the parent table schema. Running strict mode here against the - // partial dependency schema causes false-positive additional key - // diagnostics for valid keys defined by the parent schema. - let dependency_schema_context = tombi_schema_store::SchemaContext { - toml_version: schema_context.toml_version, - root_schema: schema_context.root_schema, - sub_schema_uri_map: schema_context.sub_schema_uri_map, - deprecated_lint_level: schema_context.deprecated_lint_level, - schema_format_rules: schema_context.schema_format_rules, - schema_lint_rules: schema_context.schema_lint_rules, - schema_overrides: schema_context.schema_overrides, - schema_visits: schema_context.schema_visits.clone(), - store: schema_context.store, - strict: Some(false), - }; - - if let Err(crate::Error { diagnostics, .. }) = table_value - .validate(accessors, Some(&dep_schema), &dependency_schema_context) - .await - { - total_diagnostics.extend(diagnostics); + Ok(Some(dep_schema)) => { + // A dependency schema is an additional constraint layered on top of + // the parent table schema. Running strict mode here against the + // partial dependency schema causes false-positive additional key + // diagnostics for valid keys defined by the parent schema. + let dependency_schema_context = tombi_schema_store::SchemaContext { + toml_version: schema_context.toml_version, + root_schema: schema_context.root_schema, + sub_schema_uri_map: schema_context.sub_schema_uri_map, + deprecated_lint_level: schema_context.deprecated_lint_level, + schema_format_rules: schema_context.schema_format_rules, + schema_lint_rules: schema_context.schema_lint_rules, + schema_overrides: schema_context.schema_overrides, + schema_visits: schema_context.schema_visits.clone(), + store: schema_context.store, + strict: Some(false), + }; + + if let Err(crate::Error { diagnostics, .. }) = table_value + .validate(accessors, Some(&dep_schema), &dependency_schema_context) + .await + { + total_diagnostics.extend(diagnostics); + } + } + Ok(None) => {} + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + table_value.range(), + )); } } } @@ -613,34 +670,43 @@ async fn validate_table( continue; } - if let Ok(Some(dep_schema)) = tombi_schema_store::resolve_schema_item( + match tombi_schema_store::resolve_schema_item( schema_item, current_schema.schema_uri.clone(), current_schema.definitions.clone(), schema_context.store, ) .await - .inspect_err(|err| log::warn!("{err}")) { - // See the rationale in the `Dependency::Schema` branch above. - let dependency_schema_context = tombi_schema_store::SchemaContext { - toml_version: schema_context.toml_version, - root_schema: schema_context.root_schema, - sub_schema_uri_map: schema_context.sub_schema_uri_map, - deprecated_lint_level: schema_context.deprecated_lint_level, - schema_format_rules: schema_context.schema_format_rules, - schema_lint_rules: schema_context.schema_lint_rules, - schema_overrides: schema_context.schema_overrides, - schema_visits: schema_context.schema_visits.clone(), - store: schema_context.store, - strict: Some(false), - }; - - if let Err(crate::Error { diagnostics, .. }) = table_value - .validate(accessors, Some(&dep_schema), &dependency_schema_context) - .await - { - total_diagnostics.extend(diagnostics); + Ok(Some(dep_schema)) => { + // See the rationale in the `Dependency::Schema` branch above. + let dependency_schema_context = tombi_schema_store::SchemaContext { + toml_version: schema_context.toml_version, + root_schema: schema_context.root_schema, + sub_schema_uri_map: schema_context.sub_schema_uri_map, + deprecated_lint_level: schema_context.deprecated_lint_level, + schema_format_rules: schema_context.schema_format_rules, + schema_lint_rules: schema_context.schema_lint_rules, + schema_overrides: schema_context.schema_overrides, + schema_visits: schema_context.schema_visits.clone(), + store: schema_context.store, + strict: Some(false), + }; + + if let Err(crate::Error { diagnostics, .. }) = table_value + .validate(accessors, Some(&dep_schema), &dependency_schema_context) + .await + { + total_diagnostics.extend(diagnostics); + } + } + Ok(None) => {} + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + table_value.range(), + )); } } } @@ -716,35 +782,40 @@ async fn validate_table( } } - if let Some(property_name_schema) = &table_schema.property_names - && let Ok(Some(property_name_current_schema)) = tombi_schema_store::resolve_schema_item( - property_name_schema, - current_schema.schema_uri.clone(), - current_schema.definitions.clone(), - schema_context.store, - ) - .await - .inspect_err(|err| log::warn!("{err}")) - { - for key in table_value.keys() { - if let Err(crate::Error { diagnostics, .. }) = key - .validate( - accessors, - Some(&property_name_current_schema), - schema_context, - ) - .await - { - total_diagnostics.extend(diagnostics); - } - } - } else { - for key in table_value.keys() { - if let Err(crate::Error { diagnostics, .. }) = - key.validate(accessors, None, schema_context).await + let property_name_current_schema = + if let Some(property_name_schema) = &table_schema.property_names { + match tombi_schema_store::resolve_schema_item( + property_name_schema, + current_schema.schema_uri.clone(), + current_schema.definitions.clone(), + schema_context.store, + ) + .await { - total_diagnostics.extend(diagnostics); + Ok(property_name_current_schema) => property_name_current_schema, + Err(err) => { + total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( + err.to_string(), + err.code(), + table_value.range(), + )); + None + } } + } else { + None + }; + + for key in table_value.keys() { + if let Err(crate::Error { diagnostics, .. }) = key + .validate( + accessors, + property_name_current_schema.as_ref(), + schema_context, + ) + .await + { + total_diagnostics.extend(diagnostics); } } diff --git a/rust/serde_tombi/src/config.rs b/rust/serde_tombi/src/config.rs index 3bd033eb3..f323e4f36 100644 --- a/rust/serde_tombi/src/config.rs +++ b/rust/serde_tombi/src/config.rs @@ -115,9 +115,9 @@ pub fn load_with_path_and_level( current_dir.join(TOMBI_TOML_FILENAME), current_dir.join(".config").join(TOMBI_TOML_FILENAME), ] { - log::trace!("Checking config file at {:?}", &config_path); + log::trace!("Checking config file at {:?}", config_path); if config_path.is_file() { - log::debug!("Project config found at {:?}", &config_path); + log::debug!("Project config found at {:?}", config_path); let Some(config) = try_from_path(&config_path)? else { unreachable!( @@ -131,7 +131,7 @@ pub fn load_with_path_and_level( } let pyproject_toml_path = current_dir.join(PYPROJECT_TOML_FILENAME); - log::trace!("Checking pyproject.toml file at {:?}", &pyproject_toml_path); + log::trace!("Checking pyproject.toml file at {:?}", pyproject_toml_path); if pyproject_toml_path.exists() { log::debug!( "\"{}\" found at {:?}", @@ -144,12 +144,12 @@ pub fn load_with_path_and_level( return Ok((config, Some(pyproject_toml_path), ConfigLevel::Project)); } Ok(None) => { - log::debug!("No [tool.tombi] found in {:?}", &pyproject_toml_path); + log::debug!("No [tool.tombi] found in {:?}", pyproject_toml_path); } Err(error) => { log::debug!( "Failed to parse pyproject.toml file for config at {:?}: {}", - &pyproject_toml_path, + pyproject_toml_path, error ); } @@ -164,7 +164,7 @@ pub fn load_with_path_and_level( if let Some((user_config_path, config_level)) = get_user_or_system_tombi_config_path_and_level() { - log::debug!("{CONFIG_TOML_FILENAME} found at {:?}", &user_config_path); + log::debug!("{CONFIG_TOML_FILENAME} found at {:?}", user_config_path); let Some(config) = try_from_path(&user_config_path)? else { unreachable!("{CONFIG_TOML_FILENAME} should always be parsed successfully."); }; diff --git a/rust/tombi-cli/src/app/command/format.rs b/rust/tombi-cli/src/app/command/format.rs index 928b13465..e742d3ee7 100644 --- a/rust/tombi-cli/src/app/command/format.rs +++ b/rust/tombi-cli/src/app/command/format.rs @@ -190,7 +190,7 @@ where for file in files { match file { FileSearchEntry::Found(source_path) => { - log::debug!("Formatting... {:?}", &source_path); + log::debug!("Formatting... {:?}", source_path); // Get format options with override support let Some(format_options) = tombi_glob::get_format_options( diff --git a/schemas/schema-resolution-error-test.schema.json b/schemas/schema-resolution-error-test.schema.json new file mode 100644 index 000000000..bacf84b50 --- /dev/null +++ b/schemas/schema-resolution-error-test.schema.json @@ -0,0 +1,144 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "direct": { + "$ref": "#/$defs/missing" + }, + "all-of-error": { + "allOf": [ + { + "$ref": "#/$defs/missing" + } + ] + }, + "any-of-error": { + "anyOf": [ + { + "$ref": "#/$defs/missing" + } + ] + }, + "one-of-error": { + "oneOf": [ + { + "$ref": "#/$defs/missing" + } + ] + }, + "if-error": { + "type": "object", + "if": { + "$ref": "#/$defs/missing" + } + }, + "then-error": { + "type": "object", + "if": { + "type": "object" + }, + "then": { + "$ref": "#/$defs/missing" + } + }, + "else-error": { + "type": "object", + "if": { + "type": "string" + }, + "else": { + "$ref": "#/$defs/missing" + } + }, + "items-error": { + "type": "array", + "items": { + "$ref": "#/$defs/missing" + } + }, + "prefix-items-error": { + "type": "array", + "prefixItems": [ + { + "$ref": "#/$defs/missing" + } + ] + }, + "overflow-items-error": { + "type": "array", + "prefixItems": [ + { + "type": "integer" + } + ], + "items": { + "$ref": "#/$defs/missing" + } + }, + "contains-error": { + "type": "array", + "contains": { + "$ref": "#/$defs/missing" + } + }, + "unevaluated-items-error": { + "type": "array", + "unevaluatedItems": { + "$ref": "#/$defs/missing" + } + }, + "pattern-properties-error": { + "type": "object", + "patternProperties": { + "^pat": { + "$ref": "#/$defs/missing" + } + } + }, + "additional-properties-error": { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/missing" + } + }, + "unevaluated-properties-error": { + "type": "object", + "unevaluatedProperties": { + "$ref": "#/$defs/missing" + } + }, + "property-names-error": { + "type": "object", + "additionalProperties": true, + "propertyNames": { + "$ref": "#/$defs/missing" + } + }, + "dependencies-error": { + "type": "object", + "properties": { + "trigger": { + "type": "string" + } + }, + "dependencies": { + "trigger": { + "$ref": "#/$defs/missing" + } + } + }, + "dependent-schemas-error": { + "type": "object", + "properties": { + "trigger": { + "type": "string" + } + }, + "dependentSchemas": { + "trigger": { + "$ref": "#/$defs/missing" + } + } + } + } +} From f5a06c75965d4d16c81f3be7edf2d108d410ebe1 Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Fri, 17 Jul 2026 00:20:40 +0900 Subject: [PATCH 11/15] fix(glob): remove unused profile import (#2011) --- crates/tombi-glob/src/bin/profile.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/tombi-glob/src/bin/profile.rs b/crates/tombi-glob/src/bin/profile.rs index fb6126b52..d1fc53c84 100644 --- a/crates/tombi-glob/src/bin/profile.rs +++ b/crates/tombi-glob/src/bin/profile.rs @@ -1,6 +1,5 @@ use std::{env, path::PathBuf, time::Instant}; -use tombi_config::FilesOptions; use tombi_glob::{FileSearchEntry, search_pattern_matched_paths}; #[tokio::main] From 866201f89d56159fdc821763c36c2345005e2c70 Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Fri, 17 Jul 2026 00:39:48 +0900 Subject: [PATCH 12/15] test(lsp): silence deprecated fixture warnings (#2012) --- .../dot-config-project-root/.config/tombi.toml | 9 +++++++-- .../cargo-document-link-all-enabled/tombi.toml | 12 ++++++++---- .../tombi.toml | 6 ++++-- .../tombi.toml | 12 ++++++++---- .../tombi.toml | 6 ++++-- .../cargo-document-link-git-disabled/tombi.toml | 6 ++++-- .../cargo-document-link-path-disabled/tombi.toml | 7 ++++++- .../tombi.toml | 9 ++++++--- .../tombi.toml | 9 ++++++--- .../pyproject-document-link-pypi-disabled/tombi.toml | 3 ++- .../tombi.toml | 7 ++++++- .../fixtures/extensions/tombi-disabled/tombi.toml | 9 +++++++-- .../tombi-document-link-all-enabled/tombi.toml | 7 ++++++- 13 files changed, 74 insertions(+), 28 deletions(-) diff --git a/crates/tombi-lsp/tests/fixtures/dot-config-project-root/.config/tombi.toml b/crates/tombi-lsp/tests/fixtures/dot-config-project-root/.config/tombi.toml index 2fbc533eb..96c59ff13 100644 --- a/crates/tombi-lsp/tests/fixtures/dot-config-project-root/.config/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/dot-config-project-root/.config/tombi.toml @@ -9,6 +9,11 @@ include = ["product.toml"] [extensions] "tombi-toml/tombi" = { - lsp.document-link.path.enabled = true, - lsp.goto-definition.path.enabled = true, + lsp = { + document-link = { + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = true }, + }, + goto-definition.path.enabled = true, + }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-all-enabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-all-enabled/tombi.toml index 192741f66..58df84538 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-all-enabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-all-enabled/tombi.toml @@ -1,10 +1,14 @@ [extensions] "tombi-toml/cargo" = { lsp.document-link = { - cargo-toml.enabled = true, + # tombi: lint.rules.deprecated.disabled = true + cargo-toml = { enabled = true }, crates-io.enabled = true, - git.enabled = true, - path.enabled = true, - workspace.enabled = true, + # tombi: lint.rules.deprecated.disabled = true + git = { enabled = true }, + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = true }, + # tombi: lint.rules.deprecated.disabled = true + workspace = { enabled = true }, }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-cargo-toml-disabled-bin/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-cargo-toml-disabled-bin/tombi.toml index ec9f0dfac..26c0b1911 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-cargo-toml-disabled-bin/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-cargo-toml-disabled-bin/tombi.toml @@ -2,8 +2,10 @@ "tombi-toml/cargo" = { lsp = { document-link = { - cargo-toml.enabled = false, - path.enabled = true, + # tombi: lint.rules.deprecated.disabled = true + cargo-toml = { enabled = false }, + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = true }, }, }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-cargo-toml-disabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-cargo-toml-disabled/tombi.toml index 6e9e2626d..26ee7ed41 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-cargo-toml-disabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-cargo-toml-disabled/tombi.toml @@ -2,10 +2,14 @@ "tombi-toml/cargo" = { lsp = { document-link = { - cargo-toml.enabled = false, - git.enabled = true, - path.enabled = true, - workspace.enabled = true, + # tombi: lint.rules.deprecated.disabled = true + cargo-toml = { enabled = false }, + # tombi: lint.rules.deprecated.disabled = true + git = { enabled = true }, + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = true }, + # tombi: lint.rules.deprecated.disabled = true + workspace = { enabled = true }, }, }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-crates-io-disabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-crates-io-disabled/tombi.toml index 94d947a7d..5a3c84943 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-crates-io-disabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-crates-io-disabled/tombi.toml @@ -2,9 +2,11 @@ "tombi-toml/cargo" = { lsp = { document-link = { - cargo-toml.enabled = true, + # tombi: lint.rules.deprecated.disabled = true + cargo-toml = { enabled = true }, crates-io.enabled = false, - path.enabled = true, + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = true }, }, }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-git-disabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-git-disabled/tombi.toml index e3a0c8f31..69febe0cf 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-git-disabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-git-disabled/tombi.toml @@ -2,8 +2,10 @@ "tombi-toml/cargo" = { lsp = { document-link = { - cargo-toml.enabled = true, - git.enabled = false, + # tombi: lint.rules.deprecated.disabled = true + cargo-toml = { enabled = true }, + # tombi: lint.rules.deprecated.disabled = true + git = { enabled = false }, }, }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-path-disabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-path-disabled/tombi.toml index 48b2c5f07..6121819c2 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-path-disabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-path-disabled/tombi.toml @@ -1,2 +1,7 @@ [extensions] -"tombi-toml/cargo" = { lsp.document-link.path.enabled = false } +"tombi-toml/cargo" = { + lsp.document-link = { + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = false }, + }, +} diff --git a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-workspace-disabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-workspace-disabled/tombi.toml index 42fe7cf67..c442f61b1 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-workspace-disabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-workspace-disabled/tombi.toml @@ -2,9 +2,12 @@ "tombi-toml/cargo" = { lsp = { document-link = { - cargo-toml.enabled = true, - path.enabled = false, - workspace.enabled = false, + # tombi: lint.rules.deprecated.disabled = true + cargo-toml = { enabled = true }, + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = false }, + # tombi: lint.rules.deprecated.disabled = true + workspace = { enabled = false }, }, }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-workspace-local-cargo-toml-disabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-workspace-local-cargo-toml-disabled/tombi.toml index 964e56115..56b662ecf 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-workspace-local-cargo-toml-disabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/cargo-document-link-workspace-local-cargo-toml-disabled/tombi.toml @@ -2,9 +2,12 @@ "tombi-toml/cargo" = { lsp = { document-link = { - cargo-toml.enabled = false, - path.enabled = false, - workspace.enabled = true, + # tombi: lint.rules.deprecated.disabled = true + cargo-toml = { enabled = false }, + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = false }, + # tombi: lint.rules.deprecated.disabled = true + workspace = { enabled = true }, }, }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/pyproject-document-link-pypi-disabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/pyproject-document-link-pypi-disabled/tombi.toml index a7ed0a4cb..f449f95aa 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/pyproject-document-link-pypi-disabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/pyproject-document-link-pypi-disabled/tombi.toml @@ -3,7 +3,8 @@ lsp = { document-link = { pypi-org.enabled = false, - pyproject-toml.enabled = true, + # tombi: lint.rules.deprecated.disabled = true + pyproject-toml = { enabled = true }, }, }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/pyproject-document-link-pyproject-disabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/pyproject-document-link-pyproject-disabled/tombi.toml index 9abedf402..586aed0ae 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/pyproject-document-link-pyproject-disabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/pyproject-document-link-pyproject-disabled/tombi.toml @@ -1,2 +1,7 @@ [extensions] -"tombi-toml/pyproject" = { lsp.document-link.pyproject-toml.enabled = false } +"tombi-toml/pyproject" = { + lsp.document-link = { + # tombi: lint.rules.deprecated.disabled = true + pyproject-toml = { enabled = false }, + }, +} diff --git a/crates/tombi-lsp/tests/fixtures/extensions/tombi-disabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/tombi-disabled/tombi.toml index 814230ea6..01cbcd359 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/tombi-disabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/tombi-disabled/tombi.toml @@ -1,5 +1,10 @@ [extensions] "tombi-toml/tombi" = { - lsp.document-link.path.enabled = false, - lsp.goto-definition.path.enabled = false, + lsp = { + document-link = { + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = false }, + }, + goto-definition.path.enabled = false, + }, } diff --git a/crates/tombi-lsp/tests/fixtures/extensions/tombi-document-link-all-enabled/tombi.toml b/crates/tombi-lsp/tests/fixtures/extensions/tombi-document-link-all-enabled/tombi.toml index 4fae39c1e..583f3ba40 100644 --- a/crates/tombi-lsp/tests/fixtures/extensions/tombi-document-link-all-enabled/tombi.toml +++ b/crates/tombi-lsp/tests/fixtures/extensions/tombi-document-link-all-enabled/tombi.toml @@ -1,2 +1,7 @@ [extensions] -"tombi-toml/tombi" = { lsp.document-link.path.enabled = true } +"tombi-toml/tombi" = { + lsp.document-link = { + # tombi: lint.rules.deprecated.disabled = true + path = { enabled = true }, + }, +} From ab31aec58d2d01b60f0305fb3ef099b720a5121d Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Fri, 17 Jul 2026 17:23:13 +0900 Subject: [PATCH 13/15] feat(diagnostic): integrate tombi-diagnostic for error reporting in validator (#2015) * feat(diagnostic): integrate tombi-diagnostic for error reporting in validator * refactor(error): add inline attribute to to_diagnostic method for performance optimization --- Cargo.lock | 1 + crates/tombi-schema-store/Cargo.toml | 1 + crates/tombi-schema-store/src/error.rs | 5 +++ crates/tombi-validator/src/validate/array.rs | 30 +++----------- crates/tombi-validator/src/validate/table.rs | 42 ++++---------------- 5 files changed, 19 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce4214d52..09b9f2942 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3186,6 +3186,7 @@ dependencies = [ "tombi-ast", "tombi-cache", "tombi-config", + "tombi-diagnostic", "tombi-document-tree", "tombi-future", "tombi-hashmap", diff --git a/crates/tombi-schema-store/Cargo.toml b/crates/tombi-schema-store/Cargo.toml index 5e23b8824..c5fba68c6 100644 --- a/crates/tombi-schema-store/Cargo.toml +++ b/crates/tombi-schema-store/Cargo.toml @@ -22,6 +22,7 @@ tombi-accessor.workspace = true tombi-ast.workspace = true tombi-cache.workspace = true tombi-config.workspace = true +tombi-diagnostic.workspace = true tombi-document-tree = { workspace = true, optional = true } tombi-future.workspace = true tombi-hashmap = { workspace = true, features = ["serde"] } diff --git a/crates/tombi-schema-store/src/error.rs b/crates/tombi-schema-store/src/error.rs index 05c4c01e9..9408f4d1c 100644 --- a/crates/tombi-schema-store/src/error.rs +++ b/crates/tombi-schema-store/src/error.rs @@ -140,4 +140,9 @@ impl Error { Self::CacheError(error) => error.code(), } } + + #[inline] + pub fn to_diagnostic(&self, range: tombi_text::Range) -> tombi_diagnostic::Diagnostic { + tombi_diagnostic::Diagnostic::new_error(self.to_string(), self.code(), range) + } } diff --git a/crates/tombi-validator/src/validate/array.rs b/crates/tombi-validator/src/validate/array.rs index 60d76a20d..ff0988ba4 100644 --- a/crates/tombi-validator/src/validate/array.rs +++ b/crates/tombi-validator/src/validate/array.rs @@ -169,11 +169,7 @@ async fn validate_array( { Ok(overflow_schema) => overflow_schema, Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - array_value.range(), - )); + total_diagnostics.push(err.to_diagnostic(array_value.range())); None } } @@ -212,11 +208,7 @@ async fn validate_array( } Ok(None) => {} Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - value.range(), - )); + total_diagnostics.push(err.to_diagnostic(value.range())); } } } else if let Some(overflow) = &overflow_schema { @@ -272,11 +264,7 @@ async fn validate_array( } Ok(None) => {} Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - array_value.range(), - )); + total_diagnostics.push(err.to_diagnostic(array_value.range())); } } } @@ -292,11 +280,7 @@ async fn validate_array( { Ok(contains_schema) => contains_schema, Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - array_value.range(), - )); + total_diagnostics.push(err.to_diagnostic(array_value.range())); None } }, @@ -390,11 +374,7 @@ async fn validate_array( { Ok(unevaluated_schema) => unevaluated_schema, Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - array_value.range(), - )); + total_diagnostics.push(err.to_diagnostic(array_value.range())); None } } diff --git a/crates/tombi-validator/src/validate/table.rs b/crates/tombi-validator/src/validate/table.rs index 5d0fcbd46..397e3b399 100644 --- a/crates/tombi-validator/src/validate/table.rs +++ b/crates/tombi-validator/src/validate/table.rs @@ -207,11 +207,7 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - key.range() + value.range(), - )); + total_diagnostics.push(err.to_diagnostic(key.range() + value.range())); } } } @@ -259,11 +255,7 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - key.range() + value.range(), - )); + total_diagnostics.push(err.to_diagnostic(key.range() + value.range())); } } } @@ -343,11 +335,7 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - key.range() + value.range(), - )); + total_diagnostics.push(err.to_diagnostic(key.range() + value.range())); } } } @@ -380,11 +368,7 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - key.range() + value.range(), - )); + total_diagnostics.push(err.to_diagnostic(key.range() + value.range())); } } } @@ -628,11 +612,7 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - table_value.range(), - )); + total_diagnostics.push(err.to_diagnostic(table_value.range())); } } } @@ -702,11 +682,7 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - table_value.range(), - )); + total_diagnostics.push(err.to_diagnostic(table_value.range())); } } } @@ -794,11 +770,7 @@ async fn validate_table( { Ok(property_name_current_schema) => property_name_current_schema, Err(err) => { - total_diagnostics.push(tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - table_value.range(), - )); + total_diagnostics.push(err.to_diagnostic(table_value.range())); None } } From bad59db0ac94047d48c1bd47ccdad65569dd3f6a Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Fri, 17 Jul 2026 17:36:57 +0900 Subject: [PATCH 14/15] Update error handling (#2016) * feat(diagnostic): integrate tombi-diagnostic for error reporting in validator * refactor(error): add inline attribute to to_diagnostic method for performance optimization * refactor(diagnostic): streamline error handling by using to_diagnostic method across validation modules --- crates/tombi-validator/src/validate/all_of.rs | 8 ++++--- crates/tombi-validator/src/validate/any_of.rs | 8 ++++--- .../src/validate/if_then_else.rs | 21 +++---------------- .../src/validate/not_schema.rs | 7 +------ crates/tombi-validator/src/validate/one_of.rs | 8 ++++--- 5 files changed, 19 insertions(+), 33 deletions(-) diff --git a/crates/tombi-validator/src/validate/all_of.rs b/crates/tombi-validator/src/validate/all_of.rs index 35291be5d..a1d33e7c9 100644 --- a/crates/tombi-validator/src/validate/all_of.rs +++ b/crates/tombi-validator/src/validate/all_of.rs @@ -47,9 +47,11 @@ where return Ok(crate::EvaluatedLocations::new()); }; - total_diagnostics.extend(resolution_errors.into_iter().map(|err| { - tombi_diagnostic::Diagnostic::new_error(err.to_string(), err.code(), value.range()) - })); + total_diagnostics.extend( + resolution_errors + .into_iter() + .map(|err| err.to_diagnostic(value.range())), + ); for resolved_schema in &resolved_schemas { match value diff --git a/crates/tombi-validator/src/validate/any_of.rs b/crates/tombi-validator/src/validate/any_of.rs index f05ac0bf9..a0444d039 100644 --- a/crates/tombi-validator/src/validate/any_of.rs +++ b/crates/tombi-validator/src/validate/any_of.rs @@ -88,9 +88,11 @@ where } }; - total_diagnostics.extend(resolution_errors.into_iter().map(|err| { - tombi_diagnostic::Diagnostic::new_error(err.to_string(), err.code(), value.range()) - })); + total_diagnostics.extend( + resolution_errors + .into_iter() + .map(|err| err.to_diagnostic(value.range())), + ); let mut total_error = crate::Error::new(); let mut matched = false; diff --git a/crates/tombi-validator/src/validate/if_then_else.rs b/crates/tombi-validator/src/validate/if_then_else.rs index 4f7876079..e883aee6a 100644 --- a/crates/tombi-validator/src/validate/if_then_else.rs +++ b/crates/tombi-validator/src/validate/if_then_else.rs @@ -47,12 +47,7 @@ where } Ok(None) => return Ok(crate::EvaluatedLocations::new()), Err(err) => { - return Err(vec![tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - value.range(), - )] - .into()); + return Err(vec![err.to_diagnostic(value.range())].into()); } }; @@ -77,12 +72,7 @@ where Ok(None) => {} Err(err) => { return merge_if_result( - Err(vec![tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - value.range(), - )] - .into()), + Err(vec![err.to_diagnostic(value.range())].into()), if_result, ); } @@ -108,12 +98,7 @@ where } Ok(None) => {} Err(err) => { - return Err(vec![tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - value.range(), - )] - .into()); + return Err(vec![err.to_diagnostic(value.range())].into()); } } } diff --git a/crates/tombi-validator/src/validate/not_schema.rs b/crates/tombi-validator/src/validate/not_schema.rs index f5f8de4ca..b8d8d48b2 100644 --- a/crates/tombi-validator/src/validate/not_schema.rs +++ b/crates/tombi-validator/src/validate/not_schema.rs @@ -35,12 +35,7 @@ where ), Ok(None) => false, Err(err) => { - return Err(vec![tombi_diagnostic::Diagnostic::new_error( - err.to_string(), - err.code(), - value.range(), - )] - .into()); + return Err(vec![err.to_diagnostic(value.range())].into()); } }; diff --git a/crates/tombi-validator/src/validate/one_of.rs b/crates/tombi-validator/src/validate/one_of.rs index a939340d3..7c38644d8 100644 --- a/crates/tombi-validator/src/validate/one_of.rs +++ b/crates/tombi-validator/src/validate/one_of.rs @@ -88,9 +88,11 @@ where } }; let has_resolution_errors = !resolution_errors.is_empty(); - total_diagnostics.extend(resolution_errors.into_iter().map(|err| { - tombi_diagnostic::Diagnostic::new_error(err.to_string(), err.code(), value.range()) - })); + total_diagnostics.extend( + resolution_errors + .into_iter() + .map(|err| err.to_diagnostic(value.range())), + ); let total_count = resolved_schemas.len(); if total_count == 0 { From bc1c04219ae30d6a77ac3f25889d208ad36285c3 Mon Sep 17 00:00:00 2001 From: ya7010 <47286750+ya7010@users.noreply.github.com> Date: Sat, 18 Jul 2026 00:52:31 +0900 Subject: [PATCH 15/15] chore: change schemastore diagnostics level (#2017) * feat(diagnostic): integrate tombi-diagnostic for error reporting in validator * refactor(error): add inline attribute to to_diagnostic method for performance optimization * refactor(diagnostic): streamline error handling by using to_diagnostic method across validation modules * refactor(diagnostic): rename to_diagnostic to to_warning_diagnostic for clarity in error reporting across validation modules * test: expect warning schema resolution diagnostics --- .../tests/integration/not_schema.rs | 4 +-- .../integration/schema_resolution_error.rs | 36 +++++++++---------- crates/tombi-schema-store/src/error.rs | 4 +-- crates/tombi-validator/src/validate/all_of.rs | 2 +- crates/tombi-validator/src/validate/any_of.rs | 2 +- crates/tombi-validator/src/validate/array.rs | 10 +++--- .../src/validate/if_then_else.rs | 6 ++-- .../src/validate/not_schema.rs | 2 +- crates/tombi-validator/src/validate/one_of.rs | 2 +- crates/tombi-validator/src/validate/table.rs | 17 +++++---- 10 files changed, 44 insertions(+), 41 deletions(-) diff --git a/crates/tombi-linter/tests/integration/not_schema.rs b/crates/tombi-linter/tests/integration/not_schema.rs index 91ab7fe57..5eb2efa1a 100644 --- a/crates/tombi-linter/tests/integration/not_schema.rs +++ b/crates/tombi-linter/tests/integration/not_schema.rs @@ -9,13 +9,13 @@ fn schema_path() -> std::path::PathBuf { test_lint! { #[test] - fn test_invalid_ref_reports_error_diagnostic( + fn test_invalid_ref_reports_warning_diagnostic( r#" value = "foo" "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } diff --git a/crates/tombi-linter/tests/integration/schema_resolution_error.rs b/crates/tombi-linter/tests/integration/schema_resolution_error.rs index 52136af04..db4991988 100644 --- a/crates/tombi-linter/tests/integration/schema_resolution_error.rs +++ b/crates/tombi-linter/tests/integration/schema_resolution_error.rs @@ -15,7 +15,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -27,7 +27,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -39,7 +39,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -51,7 +51,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -63,7 +63,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -75,7 +75,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -87,7 +87,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -99,7 +99,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -111,7 +111,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -123,7 +123,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -145,7 +145,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -157,7 +157,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -170,7 +170,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -183,7 +183,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -196,7 +196,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR }, + { code: "invalid-json-pointer", level: Level::WARNING }, { code: "table-strict-additional-keys", level: Level::WARNING } ]) } @@ -210,7 +210,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -223,7 +223,7 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } @@ -236,6 +236,6 @@ test_lint! { "#, SchemaPath(schema_path()), ) -> Diagnostics([ - { code: "invalid-json-pointer", level: Level::ERROR } + { code: "invalid-json-pointer", level: Level::WARNING } ]) } diff --git a/crates/tombi-schema-store/src/error.rs b/crates/tombi-schema-store/src/error.rs index 9408f4d1c..5f129cc9d 100644 --- a/crates/tombi-schema-store/src/error.rs +++ b/crates/tombi-schema-store/src/error.rs @@ -142,7 +142,7 @@ impl Error { } #[inline] - pub fn to_diagnostic(&self, range: tombi_text::Range) -> tombi_diagnostic::Diagnostic { - tombi_diagnostic::Diagnostic::new_error(self.to_string(), self.code(), range) + pub fn to_warning_diagnostic(&self, range: tombi_text::Range) -> tombi_diagnostic::Diagnostic { + tombi_diagnostic::Diagnostic::new_warning(self.to_string(), self.code(), range) } } diff --git a/crates/tombi-validator/src/validate/all_of.rs b/crates/tombi-validator/src/validate/all_of.rs index a1d33e7c9..b26bb35f5 100644 --- a/crates/tombi-validator/src/validate/all_of.rs +++ b/crates/tombi-validator/src/validate/all_of.rs @@ -50,7 +50,7 @@ where total_diagnostics.extend( resolution_errors .into_iter() - .map(|err| err.to_diagnostic(value.range())), + .map(|err| err.to_warning_diagnostic(value.range())), ); for resolved_schema in &resolved_schemas { diff --git a/crates/tombi-validator/src/validate/any_of.rs b/crates/tombi-validator/src/validate/any_of.rs index a0444d039..fc0bdcb5f 100644 --- a/crates/tombi-validator/src/validate/any_of.rs +++ b/crates/tombi-validator/src/validate/any_of.rs @@ -91,7 +91,7 @@ where total_diagnostics.extend( resolution_errors .into_iter() - .map(|err| err.to_diagnostic(value.range())), + .map(|err| err.to_warning_diagnostic(value.range())), ); let mut total_error = crate::Error::new(); diff --git a/crates/tombi-validator/src/validate/array.rs b/crates/tombi-validator/src/validate/array.rs index ff0988ba4..da14d7d22 100644 --- a/crates/tombi-validator/src/validate/array.rs +++ b/crates/tombi-validator/src/validate/array.rs @@ -169,7 +169,7 @@ async fn validate_array( { Ok(overflow_schema) => overflow_schema, Err(err) => { - total_diagnostics.push(err.to_diagnostic(array_value.range())); + total_diagnostics.push(err.to_warning_diagnostic(array_value.range())); None } } @@ -208,7 +208,7 @@ async fn validate_array( } Ok(None) => {} Err(err) => { - total_diagnostics.push(err.to_diagnostic(value.range())); + total_diagnostics.push(err.to_warning_diagnostic(value.range())); } } } else if let Some(overflow) = &overflow_schema { @@ -264,7 +264,7 @@ async fn validate_array( } Ok(None) => {} Err(err) => { - total_diagnostics.push(err.to_diagnostic(array_value.range())); + total_diagnostics.push(err.to_warning_diagnostic(array_value.range())); } } } @@ -280,7 +280,7 @@ async fn validate_array( { Ok(contains_schema) => contains_schema, Err(err) => { - total_diagnostics.push(err.to_diagnostic(array_value.range())); + total_diagnostics.push(err.to_warning_diagnostic(array_value.range())); None } }, @@ -374,7 +374,7 @@ async fn validate_array( { Ok(unevaluated_schema) => unevaluated_schema, Err(err) => { - total_diagnostics.push(err.to_diagnostic(array_value.range())); + total_diagnostics.push(err.to_warning_diagnostic(array_value.range())); None } } diff --git a/crates/tombi-validator/src/validate/if_then_else.rs b/crates/tombi-validator/src/validate/if_then_else.rs index e883aee6a..2c0c827c2 100644 --- a/crates/tombi-validator/src/validate/if_then_else.rs +++ b/crates/tombi-validator/src/validate/if_then_else.rs @@ -47,7 +47,7 @@ where } Ok(None) => return Ok(crate::EvaluatedLocations::new()), Err(err) => { - return Err(vec![err.to_diagnostic(value.range())].into()); + return Err(vec![err.to_warning_diagnostic(value.range())].into()); } }; @@ -72,7 +72,7 @@ where Ok(None) => {} Err(err) => { return merge_if_result( - Err(vec![err.to_diagnostic(value.range())].into()), + Err(vec![err.to_warning_diagnostic(value.range())].into()), if_result, ); } @@ -98,7 +98,7 @@ where } Ok(None) => {} Err(err) => { - return Err(vec![err.to_diagnostic(value.range())].into()); + return Err(vec![err.to_warning_diagnostic(value.range())].into()); } } } diff --git a/crates/tombi-validator/src/validate/not_schema.rs b/crates/tombi-validator/src/validate/not_schema.rs index b8d8d48b2..d058d8c5d 100644 --- a/crates/tombi-validator/src/validate/not_schema.rs +++ b/crates/tombi-validator/src/validate/not_schema.rs @@ -35,7 +35,7 @@ where ), Ok(None) => false, Err(err) => { - return Err(vec![err.to_diagnostic(value.range())].into()); + return Err(vec![err.to_warning_diagnostic(value.range())].into()); } }; diff --git a/crates/tombi-validator/src/validate/one_of.rs b/crates/tombi-validator/src/validate/one_of.rs index 7c38644d8..7ca5fe8bd 100644 --- a/crates/tombi-validator/src/validate/one_of.rs +++ b/crates/tombi-validator/src/validate/one_of.rs @@ -91,7 +91,7 @@ where total_diagnostics.extend( resolution_errors .into_iter() - .map(|err| err.to_diagnostic(value.range())), + .map(|err| err.to_warning_diagnostic(value.range())), ); let total_count = resolved_schemas.len(); diff --git a/crates/tombi-validator/src/validate/table.rs b/crates/tombi-validator/src/validate/table.rs index 397e3b399..5c0b161e6 100644 --- a/crates/tombi-validator/src/validate/table.rs +++ b/crates/tombi-validator/src/validate/table.rs @@ -207,7 +207,7 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(err.to_diagnostic(key.range() + value.range())); + total_diagnostics.push(err.to_warning_diagnostic(key.range() + value.range())); } } } @@ -255,7 +255,8 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(err.to_diagnostic(key.range() + value.range())); + total_diagnostics + .push(err.to_warning_diagnostic(key.range() + value.range())); } } } @@ -335,7 +336,8 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(err.to_diagnostic(key.range() + value.range())); + total_diagnostics + .push(err.to_warning_diagnostic(key.range() + value.range())); } } } @@ -368,7 +370,8 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(err.to_diagnostic(key.range() + value.range())); + total_diagnostics + .push(err.to_warning_diagnostic(key.range() + value.range())); } } } @@ -612,7 +615,7 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(err.to_diagnostic(table_value.range())); + total_diagnostics.push(err.to_warning_diagnostic(table_value.range())); } } } @@ -682,7 +685,7 @@ async fn validate_table( } Ok(None) => {} Err(err) => { - total_diagnostics.push(err.to_diagnostic(table_value.range())); + total_diagnostics.push(err.to_warning_diagnostic(table_value.range())); } } } @@ -770,7 +773,7 @@ async fn validate_table( { Ok(property_name_current_schema) => property_name_current_schema, Err(err) => { - total_diagnostics.push(err.to_diagnostic(table_value.range())); + total_diagnostics.push(err.to_warning_diagnostic(table_value.range())); None } }