From 1c107cd913b696ed2933c8b34a3f6dbf38e189a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Fernandes?= Date: Fri, 18 Oct 2024 15:59:15 +0200 Subject: [PATCH] Add onlyIssues validation option (#205) --- docs/config-example.yaml | 4 ++++ lib/cmd_line.dart | 18 ++++++++++++++++++ lib/src/context.dart | 14 +++++++++++++- node/README.md | 1 + node/gltf_validator.dart | 26 ++++++++++++++++++++++++++ node/index.js | 1 + node/module.mjs | 1 + 7 files changed, 64 insertions(+), 1 deletion(-) diff --git a/docs/config-example.yaml b/docs/config-example.yaml index be5393ec..da4d7d55 100644 --- a/docs/config-example.yaml +++ b/docs/config-example.yaml @@ -5,6 +5,10 @@ max-issues: 10 ignore: - UNEXPECTED_PROPERTY +# List of only issues to consider. Cannot be used along with 'ignore'. +only: + - ACCESSOR_INVALID_FLOAT + # Map of overridden severities. 0 - Error, 1 - Warning, 2 - Info, 3 - Hint override: ACCESSOR_INDEX_TRIANGLE_DEGENERATE: 0 \ No newline at end of file diff --git a/lib/cmd_line.dart b/lib/cmd_line.dart index f2bba817..252f8e5d 100644 --- a/lib/cmd_line.dart +++ b/lib/cmd_line.dart @@ -86,6 +86,7 @@ class ValidationTask { ValidationOptions _getValidationOptionsFromYaml(String fileName) { const kMaxIssues = 'max-issues'; const kIgnore = 'ignore'; + const kOnly = 'only'; const kOverride = 'override'; void abort(Object e) { @@ -111,6 +112,7 @@ ValidationOptions _getValidationOptionsFromYaml(String fileName) { var maxIssues = 0; List ignoredIssues; + List onlyIssues; Map severityOverrides; if (yaml is Map) { @@ -136,6 +138,21 @@ ValidationOptions _getValidationOptionsFromYaml(String fileName) { abort("$kYamlError 'ignored' must be a sequence."); } + final Object yamlOnlyIssues = yaml[kOnly]; + if (yamlOnlyIssues is List) { + onlyIssues = List.generate(yamlOnlyIssues.length, (i) { + final Object entry = yamlOnlyIssues[i]; + if (entry is String) { + return entry; + } else { + abort("$kYamlError each entry in '$kOnly' must be a string."); + return null; + } + }, growable: false); + } else if (yamlOnlyIssues != null) { + abort("$kYamlError 'only' must be a sequence."); + } + final Object yamlSeveritiesMap = yaml[kOverride]; if (yamlSeveritiesMap is Map) { severityOverrides = {}; @@ -156,6 +173,7 @@ ValidationOptions _getValidationOptionsFromYaml(String fileName) { return ValidationOptions( maxIssues: maxIssues, ignoredIssues: ignoredIssues, + onlyIssues: onlyIssues, severityOverrides: severityOverrides); } else { abort('$kYamlError document must be a map.'); diff --git a/lib/src/context.dart b/lib/src/context.dart index 10eb3e50..56576d6b 100644 --- a/lib/src/context.dart +++ b/lib/src/context.dart @@ -25,14 +25,21 @@ import 'package:gltf/src/gl.dart' as gl; class ValidationOptions { final int maxIssues; final Set ignoredIssues = {}; + final Set onlyIssues = {}; final Map severityOverrides; ValidationOptions( - {int maxIssues, List ignoredIssues, this.severityOverrides}) + {int maxIssues, + List ignoredIssues, + List onlyIssues, + this.severityOverrides}) : maxIssues = maxIssues ?? 0 { if (ignoredIssues != null) { this.ignoredIssues.addAll(ignoredIssues); } + if (onlyIssues != null) { + this.onlyIssues.addAll(onlyIssues); + } } } @@ -220,6 +227,11 @@ class Context { return; } + if (options.onlyIssues.isNotEmpty && + !options.onlyIssues.contains(issueType.code)) { + return; + } + if (options.maxIssues > 0 && _issues.length == options.maxIssues) { _isTruncated = true; throw const IssuesLimitExceededException(); diff --git a/node/README.md b/node/README.md index 7310cf86..8504c610 100644 --- a/node/README.md +++ b/node/README.md @@ -51,6 +51,7 @@ validator.validateBytes(new Uint8Array(asset), { format: 'gltf', // skip auto-detection and parse the input as glTF JSON maxIssues: 10, // limit max number of output issues to 10 ignoredIssues: ['UNSUPPORTED_EXTENSION'], // mute UNSUPPORTED_EXTENSION issue + onlyIssues: ['ACCESSOR_INVALID_FLOAT'], // only consider ACCESSOR_INVALID_FLOAT an issue. Cannot be used along with ignoredIssues. severityOverrides: { 'ACCESSOR_INDEX_TRIANGLE_DEGENERATE': 0 }, // treat degenerate triangles as errors externalResourceFunction: (uri) => new Promise((resolve, reject) => { diff --git a/node/gltf_validator.dart b/node/gltf_validator.dart index f38d4c45..b6a5cc4a 100644 --- a/node/gltf_validator.dart +++ b/node/gltf_validator.dart @@ -73,6 +73,8 @@ abstract class _JSValidationOptions { external List get ignoredIssues; + external List get onlyIssues; + external Object get severityOverrides; } @@ -213,6 +215,7 @@ Context _getContextFromOptions(_JSValidationOptions options) { ValidationOptions validationOptions; Map severityOverrides; List ignoredIssues; + List onlyIssues; if (options != null) { if (options.format != null && options.format is! String) { @@ -225,6 +228,28 @@ Context _getContextFromOptions(_JSValidationOptions options) { 'options.maxIssues: Value must be a non-negative integer.'); } + if (options.onlyIssues != null && options.ignoredIssues != null) { + throw ArgumentError( + 'options.onlyIssues cannot be used along with options.ignoredIssues.'); + } + + if (options.onlyIssues != null) { + if (options.onlyIssues is! List) { + throw ArgumentError('options.onlyIssues: Value must be an array.'); + } + + onlyIssues = []; + for (var i = 0; i < options.onlyIssues.length; ++i) { + final Object entry = options.onlyIssues[i]; + if (entry is String && entry.isNotEmpty) { + onlyIssues.add(entry); + } else { + throw ArgumentError( + 'options.onlyIssues[$i]: Value must be a non-empty String.'); + } + } + } + if (options.ignoredIssues != null) { if (options.ignoredIssues is! List) { throw ArgumentError('options.ignoredIssues: Value must be an array.'); @@ -267,6 +292,7 @@ Context _getContextFromOptions(_JSValidationOptions options) { validationOptions = ValidationOptions( maxIssues: options.maxIssues, ignoredIssues: ignoredIssues, + onlyIssues: onlyIssues, severityOverrides: severityOverrides); } diff --git a/node/index.js b/node/index.js index 50acf605..8e51775c 100644 --- a/node/index.js +++ b/node/index.js @@ -52,6 +52,7 @@ exports.validateString = (json, options) => validator.validateString(json, optio @property {boolean} writeTimestamp - Set to `false` to omit timestamp from the validation report. Default is `true`. @property {number} maxIssues - Max number of reported issues. Use `0` for unlimited output. @property {string[]} ignoredIssues - Array of ignored issue codes. + @property {string[]} onlyIssues - Array of only issues to consider. Cannot be used along with ignoredIssues. @property {Object} severityOverrides - Object with overridden severities for issue codes. */ diff --git a/node/module.mjs b/node/module.mjs index a084c03b..d9d5f4c8 100644 --- a/node/module.mjs +++ b/node/module.mjs @@ -52,6 +52,7 @@ export const validateString = (json, options) => v.default.validateString(json, @property {boolean} writeTimestamp - Set to `false` to omit timestamp from the validation report. @property {number} maxIssues - Max number of reported issues. Use `0` for unlimited output. @property {string[]} ignoredIssues - Array of ignored issue codes. + @property {string[]} onlyIssues - Array of only issues to consider. Cannot be used along with ignoredIssues. @property {Object} severityOverrides - Object with overridden severities for issue codes. */