From b1f2f3f2045de0a6aaee8826794a1e8fb4ce3f5b Mon Sep 17 00:00:00 2001 From: molsonkiko <46202915+molsonkiko@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:11:34 -0700 Subject: [PATCH] fix error form crash bug; add syntax check command ADDED: 1. "Check JSON syntax now" command. FIXED: 1. Bug where opening error form could sometimes cause Notepad++ to crash if the `auto_validate` setting was true. CHANGED: 1. Made it so that reloading the error form by pressing `Enter` would not cause certain message boxes to appear, to eliminate a potential "infinite" loop where the user would hit `Enter` to close the message box, and that moved focus back to the error form, which then repeated the cycle when they lifted the `Enter` key. --- CHANGELOG.md | 13 +- JsonToolsNppPlugin/Forms/ErrorForm.cs | 8 +- JsonToolsNppPlugin/Main.cs | 116 ++++++++++++------ .../PluginInfrastructure/NotepadPPGateway.cs | 8 +- JsonToolsNppPlugin/Properties/AssemblyInfo.cs | 4 +- docs/README.md | 10 +- most recent errors.txt | 82 ++++++------- 7 files changed, 150 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b26cee..719c719 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,10 +52,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [7.2.0] - (UNRELEASED) YYYY-MM-DD +### Added + +1. [`Check JSON syntax now` command](/docs/README.md#check-json-syntax-now). + +### Changed + +1. Made it so that reloading the [error form](/docs/README.md#error-form-and-status-bar) by pressing `Enter` would not cause certain message boxes to appear, to eliminate a potential "infinite" loop where the user would hit `Enter` to close the message box, and that moved focus back to the error form, which then repeated the cycle when they lifted the `Enter` key. + ### Fixed -1. Minor bug in [PPrint remembering comments](/docs/README.md#remember_comments) algorithm implementation that caused some arrays and objects to be compressed when they should have been pretty-printed. -2. Fix bug where tests could crash under some circumstances due to filesystem weirdness making it impossible to find test files. +1. Bug where opening error form could sometimes cause Notepad++ to crash if the [`auto_validate` setting](/docs/README.md#automatically-check-for-errors-after-editing) was true. +2. Minor bug in [PPrint remembering comments](/docs/README.md#remember_comments) algorithm implementation that caused some arrays and objects to be compressed when they should have been pretty-printed. +3. Fix bug where tests could crash under some circumstances due to filesystem weirdness making it impossible to find test files. ## [7.1.0] - 2024-02-28 diff --git a/JsonToolsNppPlugin/Forms/ErrorForm.cs b/JsonToolsNppPlugin/Forms/ErrorForm.cs index 5f54dc9..86a3e73 100644 --- a/JsonToolsNppPlugin/Forms/ErrorForm.cs +++ b/JsonToolsNppPlugin/Forms/ErrorForm.cs @@ -181,19 +181,25 @@ private void ErrorForm_KeyUp(object sender, KeyEventArgs e) { // refresh error form based on current contents of current file e.Handled = true; + Main.errorFormTriggeredParse = true; // temporarily turn off offer_to_show_lint prompt, because the user obviously wants to see it bool previousOfferToShowLint = Main.settings.offer_to_show_lint; Main.settings.offer_to_show_lint = false; Main.TryParseJson(preferPreviousDocumentType:true); - Main.settings.offer_to_show_lint = previousOfferToShowLint; if (Main.TryGetInfoForFile(Main.activeFname, out JsonFileInfo info) && info.lints != null) { if (info.filenameOfMostRecentValidatingSchema is null) Reload(Main.activeFname, info.lints); else + { Main.ValidateJson(info.filenameOfMostRecentValidatingSchema, false); + if (Main.TryGetInfoForFile(Main.activeFname, out info) && info.lints != null && info.statusBarSection != null && info.statusBarSection.Contains("fatal errors")) + Reload(Main.activeFname, info.lints); + } } + Main.settings.offer_to_show_lint = previousOfferToShowLint; + Main.errorFormTriggeredParse = false; return; } else if (e.KeyCode == Keys.Escape) diff --git a/JsonToolsNppPlugin/Main.cs b/JsonToolsNppPlugin/Main.cs index d6f4d54..a2dbcc3 100644 --- a/JsonToolsNppPlugin/Main.cs +++ b/JsonToolsNppPlugin/Main.cs @@ -48,6 +48,16 @@ class Main public static SortForm sortForm = null; // error form stuff public static ErrorForm errorForm = null; + /// + /// we need this boolean to avoid "infinite" loops as follows:

+ /// 1. The user presses Enter in the error form to parse the document.

+ /// 2. the parse fails

+ /// 3. the user is shown a dialog box warning them that the parse failed.

+ /// 4. the user presses Enter to close the dialog box

+ /// 5. focus returns to the error form

+ /// 6. the user releases the Enter key, triggering the ErrorForm_KeyUp event again and returning to step 1. + ///
+ public static bool errorFormTriggeredParse = false; // regex search to json stuff public static RegexSearchForm regexSearchForm = null; // schema auto-validation stuff @@ -108,32 +118,33 @@ static internal void CommandMenuInit() PluginBase.SetCommand(2, "&Compress current JSON file", CompressJson, new ShortcutKey(true, true, true, Keys.C)); compressId = 2; PluginBase.SetCommand(3, "Path to current p&osition", CopyPathToCurrentPosition, new ShortcutKey(true, true, true, Keys.L)); pathToPositionId = 3; PluginBase.SetCommand(4, "Select every val&id JSON in selection", SelectEveryValidJson); + PluginBase.SetCommand(5, "Chec&k JSON syntax now", CheckJsonSyntaxNow); // Here you insert a separator - PluginBase.SetCommand(5, "---", null); - PluginBase.SetCommand(6, "Open &JSON tree viewer", () => OpenJsonTree(), new ShortcutKey(true, true, true, Keys.J)); jsonTreeId = 6; - PluginBase.SetCommand(7, "&Get JSON from files and APIs", OpenGrepperForm, new ShortcutKey(true, true, true, Keys.G)); grepperFormId = 7; - PluginBase.SetCommand(8, "Sort arra&ys", OpenSortForm); sortFormId = 8; - PluginBase.SetCommand(9, "&Settings", OpenSettings, new ShortcutKey(true, true, true, Keys.S)); - PluginBase.SetCommand(10, "---", null); - PluginBase.SetCommand(11, "&Validate JSON against JSON schema", () => ValidateJson()); - PluginBase.SetCommand(12, "Choose schemas to automatically validate &filename patterns", MapSchemasToFnamePatterns); - PluginBase.SetCommand(13, "Generate sc&hema from JSON", GenerateJsonSchema); - PluginBase.SetCommand(14, "Generate &random JSON from schema", GenerateRandomJson); - PluginBase.SetCommand(15, "---", null); - PluginBase.SetCommand(16, "Run &tests", async () => await TestRunner.RunAll()); - PluginBase.SetCommand(17, "A&bout", ShowAboutForm); AboutFormId = 17; - PluginBase.SetCommand(18, "See most recent syntax &errors in this file", () => OpenErrorForm(activeFname, false)); errorFormId = 18; - PluginBase.SetCommand(19, "JSON to YAML", DumpYaml); - PluginBase.SetCommand(20, "---", null); - PluginBase.SetCommand(21, "Parse JSON Li&nes document", () => OpenJsonTree(DocumentType.JSONL)); - PluginBase.SetCommand(22, "&Array to JSON Lines", DumpJsonLines); - PluginBase.SetCommand(23, "---", null); - PluginBase.SetCommand(24, "D&ump selected text as JSON string(s)", DumpSelectedTextAsJsonString); - PluginBase.SetCommand(25, "Dump JSON string(s) as ra&w text", DumpSelectedJsonStringsAsText); - PluginBase.SetCommand(26, "---", null); - PluginBase.SetCommand(27, "Open tree for &INI file", () => OpenJsonTree(DocumentType.INI)); - PluginBase.SetCommand(28, "---", null); - PluginBase.SetCommand(29, "Rege&x search to JSON", RegexSearchToJson); + PluginBase.SetCommand(6, "---", null); + PluginBase.SetCommand(7, "Open &JSON tree viewer", () => OpenJsonTree(), new ShortcutKey(true, true, true, Keys.J)); jsonTreeId = 7; + PluginBase.SetCommand(8, "&Get JSON from files and APIs", OpenGrepperForm, new ShortcutKey(true, true, true, Keys.G)); grepperFormId = 8; + PluginBase.SetCommand(9, "Sort arra&ys", OpenSortForm); sortFormId = 9; + PluginBase.SetCommand(10, "&Settings", OpenSettings, new ShortcutKey(true, true, true, Keys.S)); + PluginBase.SetCommand(11, "---", null); + PluginBase.SetCommand(12, "&Validate JSON against JSON schema", () => ValidateJson()); + PluginBase.SetCommand(13, "Choose schemas to automatically validate &filename patterns", MapSchemasToFnamePatterns); + PluginBase.SetCommand(14, "Generate sc&hema from JSON", GenerateJsonSchema); + PluginBase.SetCommand(15, "Generate &random JSON from schema", GenerateRandomJson); + PluginBase.SetCommand(16, "---", null); + PluginBase.SetCommand(17, "Run &tests", async () => await TestRunner.RunAll()); + PluginBase.SetCommand(18, "A&bout", ShowAboutForm); AboutFormId = 18; + PluginBase.SetCommand(19, "See most recent syntax &errors in this file", () => OpenErrorForm(activeFname, false)); errorFormId = 19; + PluginBase.SetCommand(20, "JSON to YAML", DumpYaml); + PluginBase.SetCommand(21, "---", null); + PluginBase.SetCommand(22, "Parse JSON Li&nes document", () => OpenJsonTree(DocumentType.JSONL)); + PluginBase.SetCommand(23, "&Array to JSON Lines", DumpJsonLines); + PluginBase.SetCommand(24, "---", null); + PluginBase.SetCommand(25, "D&ump selected text as JSON string(s)", DumpSelectedTextAsJsonString); + PluginBase.SetCommand(26, "Dump JSON string(s) as ra&w text", DumpSelectedJsonStringsAsText); + PluginBase.SetCommand(27, "---", null); + PluginBase.SetCommand(28, "Open tree for &INI file", () => OpenJsonTree(DocumentType.INI)); + PluginBase.SetCommand(29, "---", null); + PluginBase.SetCommand(30, "Rege&x search to JSON", RegexSearchToJson); // write the schema to fname patterns file if it doesn't exist, then parse it SetSchemasToFnamePatternsFname(); @@ -660,7 +671,9 @@ public static (ParserState parserState, JNode node, bool usesSelections, Documen else info.usesSelections |= !noTextSelected; info.lints = lints; - if (lintCount > 0 && settings.offer_to_show_lint) + ParserState parserStateToSet = fatal ? ParserState.FATAL : jsonParser.state; + SetStatusBarSection(parserStateToSet, fname, info, documentType, lintCount); + if (lintCount > 0 && settings.offer_to_show_lint && !wasAutotriggered) { string msg = $"There were {lintCount} syntax errors in the document. Would you like to see them?\r\n(You can turn off these prompts in the settings (offer_to_show_lint setting))"; if (MessageBox.Show(msg, "View syntax errors in document?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) @@ -677,13 +690,12 @@ public static (ParserState parserState, JNode node, bool usesSelections, Documen if (lintCount > 0 && noTextSelected && !wasAutotriggered) Npp.editor.GoToLegalPos(lints[lintCount - 1].pos); // unacceptable error, show message box - MessageBox.Show($"Could not parse the document because of error\n{errorMessage}", - $"Error while trying to parse {Npp.DocumentTypeSuperTypeName(documentType)}", - MessageBoxButtons.OK, - MessageBoxIcon.Error); + if (!errorFormTriggeredParse) + MessageBox.Show($"Could not parse the document because of error\n{errorMessage}", + $"Error while trying to parse {Npp.DocumentTypeSuperTypeName(documentType)}", + MessageBoxButtons.OK, + MessageBoxIcon.Error); } - ParserState parserStateToSet = fatal ? ParserState.FATAL : jsonParser.state; - SetStatusBarSection(parserStateToSet, fname, info, documentType, lintCount); if (info.tv != null) { info.tv.Invoke(new Action(() => @@ -981,6 +993,14 @@ public static JNode RenameAll(Dictionary keyChanges, JO return obj; } + public static void CheckJsonSyntaxNow() + { + string curFname = Npp.notepad.GetCurrentFilePath(); + (ParserState parserState, _, _, _) = TryParseJson(Npp.FileExtension(curFname) == "jsonl" ? DocumentType.JSONL : DocumentType.JSON); + if (parserState == ParserState.FATAL) + RefreshErrorFormInOwnThread(curFname); + } + /// /// if there are one or more selections, dump each selection as a JSON string on a separate line.

/// Otherwise just dump the whole document on the same line. @@ -1251,6 +1271,19 @@ private static void DisplayErrorForm(ErrorForm form) Npp.notepad.ShowDockingForm(form); } + private static void RefreshErrorFormInOwnThread(string fname) + { + if (errorForm == null) + return; + errorForm.Invoke(new Action(() => + { + if (errorForm.IsDisposed || !TryGetInfoForFile(fname, out JsonFileInfo info) || info.lints == null) + return; + errorForm.Reload(fname, info.lints); + Npp.editor.GrabFocus(); + })); + } + public static void CopyPathToCurrentPosition() { int pos = Npp.editor.GetCurrentPos(); @@ -1515,12 +1548,15 @@ static void ShowAboutForm() /// or if it failed, where the first error was.

/// If ignoreSelections, always validate the entire file even the selected text is valid JSON. ///
- public static void ValidateJson(string schemaPath = null, bool messageOnSuccess = true, bool ignoreSelections = false) + public static void ValidateJson(string schemaPath = null, bool messageOnSuccess = true, bool ignoreSelections = false, bool wasAutotriggered = false) { - (ParserState parserState, JNode json, _, DocumentType documentType) = TryParseJson(preferPreviousDocumentType:true, ignoreSelections: ignoreSelections); + (ParserState parserState, JNode json, _, DocumentType documentType) = TryParseJson(wasAutotriggered: wasAutotriggered, preferPreviousDocumentType:true, ignoreSelections: ignoreSelections); + string curFname = Npp.notepad.GetCurrentFilePath(); if (parserState == ParserState.FATAL || json == null) + { + RefreshErrorFormInOwnThread(curFname); return; - string curFname = Npp.notepad.GetCurrentFilePath(); + } if (schemaPath == null) { FileDialog openFileDialog = new OpenFileDialog(); @@ -1551,8 +1587,7 @@ public static void ValidateJson(string schemaPath = null, bool messageOnSuccess info.filenameOfMostRecentValidatingSchema = schemaPath; info.lints = info.lints is null ? problems : info.lints.Concat(problems).ToList(); int lintCount = info.lints.Count; - if (errorForm != null && !errorForm.IsDisposed) - errorForm.Invoke(new Action(() => errorForm.Reload(curFname, info.lints))); + RefreshErrorFormInOwnThread(curFname); SetStatusBarSection(parserState, curFname, info, documentType, lintCount); if (!validates && problems.Count > 0) { @@ -1753,7 +1788,7 @@ static void SetSchemasToFnamePatternsFname() /// if the filename doesn't match, return false. /// /// - static bool ValidateIfFilenameMatches(string fname, bool wasAutotriggered = false, bool wasTriggeredByParseTimer = false) + static bool ValidateIfFilenameMatches(string fname, bool wasAutotriggered = false) { if (wasAutotriggered && Npp.editor.GetLength() > Main.settings.max_file_size_MB_slow_actions * 1e6) return false; @@ -1765,7 +1800,7 @@ static bool ValidateIfFilenameMatches(string fname, bool wasAutotriggered = fals var regex = ((JRegex)pat).regex; if (!regex.IsMatch(fname)) continue; // the filename matches a pattern for this schema, so we'll try to validate it. - ValidateJson(schemaFname, false, true); + ValidateJson(schemaFname, false, true, wasAutotriggered); return true; } } @@ -1918,11 +1953,12 @@ private static void DelayedParseAfterEditing(object s) if ((TryGetInfoForFile(fname, out JsonFileInfo info) && (info.documentType == DocumentType.INI || info.documentType == DocumentType.REGEX // file is already being parsed as regex or ini, so stop || info.usesSelections)) // file uses selections, so stop (because that could change the user's selections unexpectedly) - || ValidateIfFilenameMatches(fname, wasTriggeredByParseTimer: true) // if filename is associated with a schema, it will be parsed during the schema validation, so stop + || ValidateIfFilenameMatches(fname, true) // if filename is associated with a schema, it will be parsed during the schema validation, so stop || !fileExtensionsToAutoParse.Contains(ext)) // extension is not marked for auto-parsing, so stop return; // filename matches but it's not associated with a schema or being parsed as non-JSON/JSONL, so just parse normally TryParseJson(ext == "jsonl" ? DocumentType.JSONL : DocumentType.JSON, true, ignoreSelections:true); + RefreshErrorFormInOwnThread(fname); } #endregion } diff --git a/JsonToolsNppPlugin/PluginInfrastructure/NotepadPPGateway.cs b/JsonToolsNppPlugin/PluginInfrastructure/NotepadPPGateway.cs index 01569ba..108f470 100644 --- a/JsonToolsNppPlugin/PluginInfrastructure/NotepadPPGateway.cs +++ b/JsonToolsNppPlugin/PluginInfrastructure/NotepadPPGateway.cs @@ -170,16 +170,16 @@ public bool SaveCurrentFile() public void HideDockingForm(System.Windows.Forms.Form form) { - Win32.SendMessage(PluginBase.nppData._nppHandle, + form.Invoke(new Action(() => Win32.SendMessage(PluginBase.nppData._nppHandle, (uint)(NppMsg.NPPM_DMMHIDE), - 0, form.Handle); + 0, form.Handle))); } public void ShowDockingForm(System.Windows.Forms.Form form) { - Win32.SendMessage(PluginBase.nppData._nppHandle, + form.Invoke(new Action(() => Win32.SendMessage(PluginBase.nppData._nppHandle, (uint)(NppMsg.NPPM_DMMSHOW), - 0, form.Handle); + 0, form.Handle))); } public Color GetDefaultForegroundColor() diff --git a/JsonToolsNppPlugin/Properties/AssemblyInfo.cs b/JsonToolsNppPlugin/Properties/AssemblyInfo.cs index aeef1a0..ddc5924 100644 --- a/JsonToolsNppPlugin/Properties/AssemblyInfo.cs +++ b/JsonToolsNppPlugin/Properties/AssemblyInfo.cs @@ -28,5 +28,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("7.1.0.2")] -[assembly: AssemblyFileVersion("7.1.0.2")] +[assembly: AssemblyVersion("7.1.0.3")] +[assembly: AssemblyFileVersion("7.1.0.3")] diff --git a/docs/README.md b/docs/README.md index 85a1ccf..b805cc5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -248,7 +248,7 @@ The `linting` attribute in Settings enables the built-in linter for the JSON par About 2 seconds after a not-very-large file (default less than 4 megabytes, configurable in settings) is opened, and after 2 seconds of inactivity following any modification of the file or styling, the plugin can parse the document and performs [JSON Schema validation](#validating-json-against-json-schema) on the document. The user is notified of any errors when this happens, and no further notifications are sent until the user next modifies or re-styles the document. -This is off by default. If desired, this feature can be turned on in the settings. When turned on, it only applies to files with `json`, `jsonc`, `jsonl`, and `json5` extensions, or files configured for [automatic JSON schema validation](#automatic-validation-of-json-against-json-schema). +This is off by default. If desired, this feature can be turned on in the settings (`auto_validate` setting). When turned on, it only applies to files with `json`, `jsonc`, `jsonl`, and `json5` extensions, or files configured for [automatic JSON schema validation](#automatic-validation-of-json-against-json-schema). Prior to [v6.1](/CHANGELOG.md#610---2023-12-28), this automatic validation forced the file to be parsed as JSON. As of v6.1, the document will be parsed as [JSON Lines](#json-lines-documents) if the file extension is `jsonl` and as JSON otherwise. In addition, if the document is already in [regex mode](#regex-search-form) or [ini file mode](#parsing-ini-files), automatic validation is suspended. @@ -927,6 +927,14 @@ The `toolbar_icons` option in settings lets you customize which toolbar icons sh Thus, `cot` would give the icon sequence `(compress, path to current position, tree view)`, `P` would give only the pretty-print icon, and `A` would give no icons at all. +## Check JSON syntax now ## + +*Added in version [7.2](/CHANGELOG.md#720---unreleased-yyyy-mm-dd).* + +This command checks JSON syntax and updates the [error form and status bar](/docs/README.md#error-form-and-status-bar). It *will not* validate using JSON schema. If there are any [remembered selections](#working-with-selections), it will only parse those selections. + +This command will *always* attempt to parse the document as JSON, unless the file extension is `.jsonl`, in which case it will attempt to parse the document as [JSON Lines](#json-lines-documents). This will override [regex mode](#regex-search-form) and [INI mode](#parsing-ini-files). + ## DSON ## JSON is not sufficiently [Doge-friendly](https://dogeon.xyz/index.html). This plugin aims to help correct that. diff --git a/most recent errors.txt b/most recent errors.txt index 3e8c76e..df27695 100644 --- a/most recent errors.txt +++ b/most recent errors.txt @@ -1,4 +1,4 @@ -Test results for JsonTools v7.1.0.2 on Notepad++ 8.6.4 64bit +Test results for JsonTools v7.1.0.3 on Notepad++ 8.6.4 64bit NOTE: Ctrl-F (regular expressions *on*) for "Failed [1-9]\d*" to find all failed tests Tests failed: YAML dumper ========================= @@ -201,33 +201,33 @@ Testing JsonParser performance Preview of json: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c" ... -To convert JSON string of size 89556 into JNode took 3.819 +/- 4.363 ms over 32 trials -Load times (ms): 2, 3, 3, 3, 4, 27, 2, 2, 5, 2, 2, 2, 3, 1, 1, 5, 2, 2, 2, 3, 2, 2, 6, 2, 2, 2, 3, 1, 1, 5, 2, 1 +To convert JSON string of size 89556 into JNode took 3.582 +/- 3.187 ms over 32 trials +Load times (ms): 5, 19, 2, 5, 5, 1, 2, 7, 2, 1, 1, 2, 1, 1, 4, 1, 1, 1, 3, 4, 3, 3, 1, 2, 2, 3, 2, 3, 3, 1, 2, 3 ========================= Performance tests for RemesPath (float arithmetic) ========================= -Compiling query "@[@[:].a * @[:].t < @[:].e]" took 0.086 ms the first time, including approximately 0.097 ms to tokenize the query. Subsequent executions are effectively free due to caching. -To run pre-compiled query "@[@[:].a * @[:].t < @[:].e]" on JNode from JSON of size 89556 into took 0.058 +/- 0.032 ms over 40 trials -Query times (ms): 0.12, 0.077, 0.042, 0.042, 0.041, 0.039, 0.04, 0.057, 0.066, 0.053, 0.054, 0.06, 0.052, 0.071, 0.05, 0.056, 0.048, 0.05, 0.049, 0.127, 0.056, 0.095, 0.108, 0.198, 0.062, 0.042, 0.035, 0.03, 0.032, 0.052, 0.034, 0.048, 0.041, 0.031, 0.035, 0.033, 0.073, 0.048, 0.038, 0.03 +Compiling query "@[@[:].a * @[:].t < @[:].e]" took 0.092 ms the first time, including approximately 0.056 ms to tokenize the query. Subsequent executions are effectively free due to caching. +To run pre-compiled query "@[@[:].a * @[:].t < @[:].e]" on JNode from JSON of size 89556 into took 0.078 +/- 0.303 ms over 40 trials +Query times (ms): 0.066, 0.034, 0.023, 0.023, 1.969, 0.026, 0.024, 0.026, 0.024, 0.023, 0.023, 0.022, 0.022, 0.024, 0.074, 0.027, 0.023, 0.023, 0.028, 0.029, 0.023, 0.067, 0.037, 0.023, 0.024, 0.029, 0.034, 0.056, 0.032, 0.023, 0.023, 0.029, 0.023, 0.022, 0.022, 0.022, 0.022, 0.023, 0.022, 0.022 Preview of result: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c" ... ========================= Performance tests for RemesPath (string operations) ========================= -Compiling query "@[@[:].z =~ `(?i)[a-z]{5}`]" took 0.066 ms the first time, including approximately 0.074 ms to tokenize the query. Subsequent executions are effectively free due to caching. -To run pre-compiled query "@[@[:].z =~ `(?i)[a-z]{5}`]" on JNode from JSON of size 89556 into took 0.083 +/- 0.073 ms over 40 trials -Query times (ms): 0.472, 0.256, 0.178, 0.112, 0.131, 0.055, 0.064, 0.057, 0.055, 0.056, 0.055, 0.055, 0.08, 0.061, 0.061, 0.058, 0.057, 0.056, 0.104, 0.112, 0.079, 0.055, 0.054, 0.053, 0.054, 0.054, 0.062, 0.07, 0.057, 0.067, 0.056, 0.057, 0.055, 0.056, 0.065, 0.071, 0.056, 0.058, 0.056, 0.055 +Compiling query "@[@[:].z =~ `(?i)[a-z]{5}`]" took 0.047 ms the first time, including approximately 0.042 ms to tokenize the query. Subsequent executions are effectively free due to caching. +To run pre-compiled query "@[@[:].z =~ `(?i)[a-z]{5}`]" on JNode from JSON of size 89556 into took 0.077 +/- 0.113 ms over 40 trials +Query times (ms): 0.112, 0.063, 0.067, 0.056, 0.055, 0.057, 0.054, 0.779, 0.078, 0.055, 0.056, 0.055, 0.066, 0.072, 0.055, 0.054, 0.08, 0.055, 0.054, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.056, 0.056, 0.055, 0.055, 0.069, 0.055, 0.055, 0.054, 0.056, 0.055, 0.056, 0.055, 0.054, 0.056, 0.055 Preview of result: [{"A": "\n]o1VQ5t6g", "a": 4710024278, "b": 3268860721, "B": "g4Y7+ew^.v", "C": "NK nmax_notq, `when q=true, nmax = ` + str(nmax_q), `when q=false, nmax= ` + str(nmax_notq))" took 0.238 ms the first time, including approximately 0.36 ms to tokenize the query. Subsequent executions are effectively free due to caching. +ifelse(nmax_q > nmax_notq, `when q=true, nmax = ` + str(nmax_q), `when q=false, nmax= ` + str(nmax_notq))" took 0.134 ms the first time, including approximately 0.12 ms to tokenize the query. Subsequent executions are effectively free due to caching. To run pre-compiled query "var qmask = @[:].q; var nmax_q = max(@[qmask].n); var nmax_notq = max(@[not qmask].n); -ifelse(nmax_q > nmax_notq, `when q=true, nmax = ` + str(nmax_q), `when q=false, nmax= ` + str(nmax_notq))" on JNode from JSON of size 89556 into took 0.035 +/- 0.026 ms over 40 trials -Query times (ms): 0.152, 0.039, 0.126, 0.066, 0.028, 0.029, 0.027, 0.032, 0.03, 0.035, 0.03, 0.034, 0.031, 0.035, 0.046, 0.022, 0.03, 0.03, 0.03, 0.034, 0.032, 0.034, 0.028, 0.018, 0.023, 0.026, 0.02, 0.02, 0.016, 0.016, 0.018, 0.019, 0.019, 0.021, 0.033, 0.031, 0.032, 0.031, 0.038, 0.034 +ifelse(nmax_q > nmax_notq, `when q=true, nmax = ` + str(nmax_q), `when q=false, nmax= ` + str(nmax_notq))" on JNode from JSON of size 89556 into took 0.025 +/- 0.054 ms over 40 trials +Query times (ms): 0.068, 0.018, 0.017, 0.016, 0.016, 0.016, 0.016, 0.016, 0.015, 0.015, 0.015, 0.016, 0.015, 0.015, 0.016, 0.015, 0.015, 0.015, 0.015, 0.357, 0.016, 0.015, 0.015, 0.016, 0.015, 0.016, 0.015, 0.016, 0.015, 0.015, 0.016, 0.015, 0.015, 0.015, 0.016, 0.015, 0.015, 0.015, 0.016, 0.015 Preview of result: "when q=false, nmax= 9830935647.0" ... ========================= @@ -266,11 +266,11 @@ Performance tests for RemesPath (references to compile-time constant variables) Compiling query "var X = X; var onetwo = j`[1, 2]`; -@[:]->at(@, X)->at(@, onetwo)" took 0.163 ms the first time, including approximately 0.126 ms to tokenize the query. Subsequent executions are effectively free due to caching. +@[:]->at(@, X)->at(@, onetwo)" took 0.076 ms the first time, including approximately 0.078 ms to tokenize the query. Subsequent executions are effectively free due to caching. To run pre-compiled query "var X = X; var onetwo = j`[1, 2]`; -@[:]->at(@, X)->at(@, onetwo)" on JNode from JSON of size 89556 into took 0.146 +/- 0.613 ms over 40 trials -Query times (ms): 0.074, 0.027, 0.013, 0.014, 0.014, 0.013, 0.028, 0.032, 3.941, 0.025, 0.027, 0.169, 0.051, 0.037, 0.024, 0.041, 0.026, 0.026, 0.028, 0.033, 0.027, 0.033, 0.043, 0.031, 0.063, 0.03, 0.025, 0.025, 0.034, 0.079, 0.069, 0.026, 0.026, 0.034, 0.027, 0.542, 0.046, 0.02, 0.013, 0.013 +@[:]->at(@, X)->at(@, onetwo)" on JNode from JSON of size 89556 into took 0.014 +/- 0.007 ms over 40 trials +Query times (ms): 0.06, 0.012, 0.013, 0.013, 0.012, 0.012, 0.012, 0.013, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.015, 0.019, 0.017, 0.012, 0.012, 0.013, 0.012, 0.012 Preview of result: [[1695727848, 0.287562638736685], [2126430375, 0.00767794129708177], [5310550656, 0.380769772645687], [2519183283, 0.153176220930558], [6610062385, 0.662996225870666], [987168256, 0.924410189999928], [6615003609, 0.917112691225947], [4465232046, 0.684311931851536], [8654414565, 0.631485392105992], [ ... ========================= @@ -279,29 +279,29 @@ Performance tests for RemesPath (references to variables that are not compile-ti Compiling query "var X = @->`X`; var onetwo = @{1, 2}; -@[:]->at(@, X)->at(@, onetwo)" took 0.185 ms the first time, including approximately 0.146 ms to tokenize the query. Subsequent executions are effectively free due to caching. +@[:]->at(@, X)->at(@, onetwo)" took 0.082 ms the first time, including approximately 0.078 ms to tokenize the query. Subsequent executions are effectively free due to caching. To run pre-compiled query "var X = @->`X`; var onetwo = @{1, 2}; -@[:]->at(@, X)->at(@, onetwo)" on JNode from JSON of size 89556 into took 0.035 +/- 0.013 ms over 40 trials -Query times (ms): 0.108, 0.035, 0.036, 0.035, 0.049, 0.032, 0.058, 0.032, 0.032, 0.03, 0.031, 0.032, 0.032, 0.032, 0.03, 0.037, 0.03, 0.031, 0.031, 0.041, 0.032, 0.03, 0.029, 0.032, 0.032, 0.035, 0.034, 0.035, 0.032, 0.035, 0.033, 0.032, 0.034, 0.033, 0.031, 0.033, 0.032, 0.031, 0.032, 0.032 +@[:]->at(@, X)->at(@, onetwo)" on JNode from JSON of size 89556 into took 0.017 +/- 0.006 ms over 40 trials +Query times (ms): 0.054, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.017, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.015, 0.016, 0.016, 0.016, 0.017, 0.016, 0.016, 0.016, 0.016, 0.015, 0.016, 0.017, 0.016, 0.016, 0.017, 0.016, 0.016, 0.016 Preview of result: [[1695727848, 0.287562638736685], [2126430375, 0.00767794129708177], [5310550656, 0.380769772645687], [2519183283, 0.153176220930558], [6610062385, 0.662996225870666], [987168256, 0.924410189999928], [6615003609, 0.917112691225947], [4465232046, 0.684311931851536], [8654414565, 0.631485392105992], [ ... ========================= Performance tests for RemesPath (simple string mutations) ========================= -Compiling query "@[:].z = s_sub(@, g, B)" took 0.088 ms the first time, including approximately 0.093 ms to tokenize the query. Subsequent executions are effectively free due to caching. -To run pre-compiled query "@[:].z = s_sub(@, g, B)" on JNode from JSON of size 89556 into took 0.028 +/- 0.012 ms over 40 trials -Query times (ms): 0.05, 0.044, 0.044, 0.034, 0.026, 0.027, 0.03, 0.042, 0.031, 0.032, 0.037, 0.036, 0.033, 0.04, 0.034, 0.036, 0.04, 0.031, 0.013, 0.028, 0.016, 0.059, 0.053, 0.021, 0.015, 0.017, 0.013, 0.014, 0.012, 0.027, 0.016, 0.017, 0.026, 0.016, 0.013, 0.014, 0.011, 0.03, 0.029, 0.016 +Compiling query "@[:].z = s_sub(@, g, B)" took 0.058 ms the first time, including approximately 0.054 ms to tokenize the query. Subsequent executions are effectively free due to caching. +To run pre-compiled query "@[:].z = s_sub(@, g, B)" on JNode from JSON of size 89556 into took 0.02 +/- 0.009 ms over 40 trials +Query times (ms): 0.022, 0.014, 0.011, 0.01, 0.011, 0.016, 0.01, 0.01, 0.018, 0.015, 0.013, 0.012, 0.028, 0.03, 0.014, 0.013, 0.016, 0.032, 0.013, 0.011, 0.01, 0.011, 0.042, 0.028, 0.021, 0.015, 0.017, 0.029, 0.021, 0.019, 0.016, 0.036, 0.026, 0.027, 0.026, 0.039, 0.026, 0.029, 0.025, 0.027 Preview of result: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c" ... ========================= Performance tests for RemesPath (simple number mutations) ========================= -Compiling query "@[:].x = ifelse(@ < 0.5, @ + 3, @ - 3)" took 0.078 ms the first time, including approximately 0.124 ms to tokenize the query. Subsequent executions are effectively free due to caching. -To run pre-compiled query "@[:].x = ifelse(@ < 0.5, @ + 3, @ - 3)" on JNode from JSON of size 89556 into took 0.039 +/- 0.008 ms over 40 trials -Query times (ms): 0.042, 0.064, 0.034, 0.035, 0.036, 0.039, 0.034, 0.041, 0.045, 0.035, 0.039, 0.039, 0.032, 0.051, 0.048, 0.051, 0.034, 0.036, 0.033, 0.041, 0.036, 0.032, 0.039, 0.035, 0.034, 0.03, 0.057, 0.065, 0.038, 0.036, 0.024, 0.041, 0.036, 0.034, 0.039, 0.04, 0.035, 0.038, 0.038, 0.041 +Compiling query "@[:].x = ifelse(@ < 0.5, @ + 3, @ - 3)" took 0.07 ms the first time, including approximately 0.075 ms to tokenize the query. Subsequent executions are effectively free due to caching. +To run pre-compiled query "@[:].x = ifelse(@ < 0.5, @ + 3, @ - 3)" on JNode from JSON of size 89556 into took 0.023 +/- 0.007 ms over 40 trials +Query times (ms): 0.046, 0.019, 0.018, 0.02, 0.018, 0.023, 0.024, 0.029, 0.02, 0.018, 0.016, 0.021, 0.017, 0.018, 0.029, 0.02, 0.018, 0.017, 0.037, 0.028, 0.034, 0.025, 0.019, 0.018, 0.019, 0.019, 0.019, 0.018, 0.018, 0.021, 0.018, 0.043, 0.032, 0.034, 0.027, 0.02, 0.018, 0.018, 0.019, 0.029 Preview of result: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c" ... ========================= @@ -311,12 +311,12 @@ Performance tests for RemesPath (mutations with a for loop) Compiling query "var xhalf = @[:].x < 0.5; for lx = zip(@[:].l, xhalf); lx[0] = ifelse(lx[1], foo, bar); -end for;" took 0.237 ms the first time, including approximately 0.199 ms to tokenize the query. Subsequent executions are effectively free due to caching. +end for;" took 0.121 ms the first time, including approximately 0.114 ms to tokenize the query. Subsequent executions are effectively free due to caching. To run pre-compiled query "var xhalf = @[:].x < 0.5; for lx = zip(@[:].l, xhalf); lx[0] = ifelse(lx[1], foo, bar); -end for;" on JNode from JSON of size 89556 into took 0.076 +/- 0.019 ms over 40 trials -Query times (ms): 0.107, 0.083, 0.086, 0.073, 0.093, 0.076, 0.076, 0.08, 0.078, 0.072, 0.091, 0.101, 0.107, 0.09, 0.111, 0.097, 0.084, 0.091, 0.065, 0.109, 0.094, 0.08, 0.064, 0.067, 0.061, 0.063, 0.067, 0.073, 0.076, 0.073, 0.075, 0.071, 0.073, 0.073, 0.056, 0.041, 0.039, 0.041, 0.048, 0.039 +end for;" on JNode from JSON of size 89556 into took 0.042 +/- 0.013 ms over 40 trials +Query times (ms): 0.101, 0.04, 0.038, 0.052, 0.051, 0.067, 0.085, 0.041, 0.042, 0.038, 0.046, 0.036, 0.036, 0.047, 0.048, 0.037, 0.037, 0.036, 0.041, 0.035, 0.034, 0.036, 0.044, 0.036, 0.035, 0.035, 0.036, 0.039, 0.034, 0.033, 0.035, 0.038, 0.034, 0.043, 0.033, 0.044, 0.035, 0.036, 0.036, 0.05 Preview of result: [["bar", false], ["bar", false], ["foo", true], ["foo", true], ["foo", true], ["foo", true], ["foo", true], ["bar", false], ["bar", false], ["bar", false], ["foo", true], ["foo", true], ["bar", false], ["bar", false], ["foo", true], ["bar", false], ["bar", false], ["bar", false], ["foo", true], ["ba ... ========================= @@ -325,18 +325,18 @@ Testing performance of JSON compression and pretty-printing Preview of json: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c" ... -To compress JNode from JSON string of 89556 took 4.158 +/- 0.978 ms over 64 trials (minimal whitespace, sortKeys=TRUE) -To compress JNode from JSON string of 89556 took 2.006 +/- 0.268 ms over 64 trials (minimal whitespace, sortKeys=FALSE) -To Google-style pretty-print JNode from JSON string of 89556 took 4.772 +/- 1.072 ms over 64 trials (sortKeys=true, indent=4) -To Whitesmith-style pretty-print JNode from JSON string of 89556 took 4.743 +/- 0.944 ms over 64 trials (sortKeys=true, indent=4) -To PPrint-style pretty-print JNode from JSON string of 89556 took 6.002 +/- 0.285 ms over 64 trials (sortKeys=true, indent=4) +To compress JNode from JSON string of 89556 took 3.792 +/- 0.297 ms over 64 trials (minimal whitespace, sortKeys=TRUE) +To compress JNode from JSON string of 89556 took 2.113 +/- 0.4 ms over 64 trials (minimal whitespace, sortKeys=FALSE) +To Google-style pretty-print JNode from JSON string of 89556 took 4.931 +/- 0.761 ms over 64 trials (sortKeys=true, indent=4) +To Whitesmith-style pretty-print JNode from JSON string of 89556 took 4.862 +/- 0.613 ms over 64 trials (sortKeys=true, indent=4) +To PPrint-style pretty-print JNode from JSON string of 89556 took 7.011 +/- 0.999 ms over 64 trials (sortKeys=true, indent=4) ========================= Testing performance of JsonSchemaValidator and random JSON creation ========================= -To create a random set of tweet JSON of size 167038 (15 tweets) based on the matching schema took 7.05 +/- 3.737 ms over 64 trials -To compile the tweet schema to a validation function took 0.375 +/- 0.633 ms over 64 trials -To validate tweet JSON of size 167038 (15 tweets) based on the compiled schema took 1.16 +/- 0.564 ms over 64 trials +To create a random set of tweet JSON of size 171921 (15 tweets) based on the matching schema took 6.427 +/- 2.904 ms over 64 trials +To compile the tweet schema to a validation function took 0.263 +/- 0.416 ms over 64 trials +To validate tweet JSON of size 171921 (15 tweets) based on the compiled schema took 1.019 +/- 0.216 ms over 64 trials ========================= Testing JSON grepper's API request tool =========================