Skip to content

Commit 3c7eb99

Browse files
committed
fix minor bugs with JsonGrepper, ScintillaGateway
FIX: bug where JsonTools was supposed to send a NULL-terminated string to Notepad++ in the SetText and InsertText methods, but I was not appending the NULL char. By addressing this issue, I removed the necessity for the RemoveTrailingSOH method, which means that JsonTools can output files ending with the SOH character. FIX: Issue with JsonGrepperTests where I was expecting JSON from a weather.gov API that had switched to returning HTML. FIX: Potential race condition with the automatic-parse-after-edit thread during plugin cleanup.
1 parent 9a342bc commit 3c7eb99

8 files changed

Lines changed: 95 additions & 66 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
4848
- GrepperForm loses its JSON permanently when the buffer associated with its treeview is deleted.
4949
- Since v7.0, holding down `Enter` in a multiline textbox (like the [tree viewer query box](/docs/README.md#remespath)) only adds one newline when the key is lifted.
5050
- Maybe use pre-7.1 (dictionary-based rather than indicator-based) [selection remembering](/docs/README.md#working-with-selections) for Notepad++ 8.5.5 and earlier? Indicators are risky with those older NPP's because of the lack of `NPPM_ALLOCATEINDICATOR`.
51+
- Hard-to-reproduce issue where sometimes clicking a treenode in regex search results does not navigate to the correct location in the document (should navigate to the start of the match). Appears to only happen when there is no capture group. It's an all-or-nothing issue; either none of the treenodes navigate to the correct location or all of them do.
52+
53+
## [9.0.0] - (UNRELEASED) YYYY-MM-DD
54+
55+
### Fixed
56+
57+
1. Bug where JsonTools could not set the text of a file to end with the SOH character (ASCII code `\x01`)
58+
2. Bug where some JsonGrepper tests would always fail because they queried an external API that had previously returned JSON but now returns HTML.
5159

5260
## [8.4.0] - 2025-05-04
5361

JsonToolsNppPlugin/Main.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@ static internal void FileRenameCancel(IntPtr bufferRenamedId)
452452

453453
static internal void PluginCleanUp()
454454
{
455+
// turn off auto-validation because we're about to remove jsonFileInfos
456+
settings.auto_validate = false;
455457
if (grepperForm != null && !grepperForm.IsDisposed)
456458
{
457459
grepperForm.Close();

JsonToolsNppPlugin/PluginInfrastructure/ScintillaGateway.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ private unsafe string GetNullStrippedStringFromMessageThatReturnsLength(SciMsg m
4747
}
4848
}
4949

50+
/// <summary>
51+
/// the same byte[] buffer that would be returned by Encoding.UTF8.GetBytes(text),
52+
/// but with +1 length and a NULL byte at the end
53+
/// </summary>
54+
/// <param name="text"></param>
55+
/// <returns></returns>
56+
private byte[] GetNullTerminatedUTF8Bytes(string text)
57+
{
58+
int length = Encoding.UTF8.GetByteCount(text);
59+
byte[] bytes = new byte[length + 1];
60+
int lengthWritten = Encoding.UTF8.GetBytes(text, 0, text.Length, bytes, 0);
61+
//if (lengthWritten != length)
62+
// throw new Exception("not sure what we would do here");
63+
return bytes;
64+
}
65+
5066
public ScintillaGateway(IntPtr scintilla)
5167
{
5268
this.scintilla = scintilla;
@@ -131,7 +147,7 @@ public unsafe void AddStyledText(int length, Cells c)
131147
/// <summary>Insert string at a position. (Scintilla feature 2003)</summary>
132148
public unsafe void InsertText(int pos, string text)
133149
{
134-
fixed (byte* textPtr = Encoding.UTF8.GetBytes(text))
150+
fixed (byte* textPtr = GetNullTerminatedUTF8Bytes(text))
135151
{
136152
Win32.SendMessage(scintilla, SciMsg.SCI_INSERTTEXT, (IntPtr) pos, (IntPtr) textPtr);
137153
}
@@ -1781,12 +1797,7 @@ public void Clear()
17811797
/// <summary>Replace the contents of the document with the argument text. (Scintilla feature 2181)</summary>
17821798
public unsafe void SetText(string text)
17831799
{
1784-
if (text.Length == 0)
1785-
{
1786-
ClearAll();
1787-
return;
1788-
}
1789-
fixed (byte* textPtr = Encoding.UTF8.GetBytes(text))
1800+
fixed (byte* textPtr = GetNullTerminatedUTF8Bytes(text))
17901801
{
17911802
Win32.SendMessage(scintilla, SciMsg.SCI_SETTEXT, (IntPtr) Unused, (IntPtr) textPtr);
17921803
}

JsonToolsNppPlugin/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@
2828
// Build Number
2929
// Revision
3030
//
31-
[assembly: AssemblyVersion("8.4.0.0")]
32-
[assembly: AssemblyFileVersion("8.4.0.0")]
31+
[assembly: AssemblyVersion("8.4.0.1")]
32+
[assembly: AssemblyFileVersion("8.4.0.1")]

JsonToolsNppPlugin/Tests/JsonGrepperTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,10 @@ public static async Task<bool> TestApiRequester()
146146
int ii = 0;
147147
int testsFailed = 0;
148148

149+
string firstUrlStr = "https://api.weather.gov/stations/KCCR";
150+
149151
string[] urls = new string[] {
150-
"https://api.weather.gov",
152+
firstUrlStr,
151153
"https://api.weather.gov/points/37.68333333333334,-121.92500000000001", // Alameda
152154
"https://api.weather.gov/points/37.75833333333334,-122.43333333333334", // San Francisco
153155
};
@@ -156,7 +158,7 @@ public static async Task<bool> TestApiRequester()
156158
ii = testResult[0];
157159
testsFailed = testResult[1];
158160
// test when requesting from only one url
159-
string[] firstUrl = new string[] { "https://api.weather.gov" };
161+
string[] firstUrl = new string[] { firstUrlStr };
160162
testResult = await TestApiRequesterHelper(firstUrl, ii, testsFailed, grepper);
161163
ii = testResult[0];
162164
testsFailed = testResult[1];

JsonToolsNppPlugin/Tests/UserInterfaceTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,9 @@ public static bool Test()
778778
("treenode_click", new object[]{new string[] { "3 : \"{\\\"5\\\": [6]}\"" } }),
779779
("tree_query", new object[]{"@ = ``"}), // test that using RemesPath to clear text of document works
780780
("compare_text", new object[]{""}),
781+
// TEST DOC CAN END WITH SOH CHAR
782+
("tree_query", new object[]{"@ = j`\"foo\\r\\n\\u0001\"`"}),
783+
("compare_text", new object[]{"foo\r\n\x01"}),
781784
// TEST SORT FORM ON JSON LINES
782785
("overwrite", new object[]{"[1,'foo',true]\n[2,'bar',false]"}),
783786
("set_document_type", new object[]{"JSONL"}),

JsonToolsNppPlugin/Utils/Npp.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ public static void CreateConfigSubDirectoryIfNotExists()
235235
/// </summary>
236236
public static void RemoveTrailingSOH()
237237
{
238+
// hopefully using a NULL-terminated string in SetText and AppendText makes this method unnecessary
239+
bool isNecessaryRemoveSOH = false;
240+
if (!isNecessaryRemoveSOH)
241+
return;
238242
if (!TryGetLengthAsInt(out int lastPos, false))
239243
return;
240244
lastPos--;

0 commit comments

Comments
 (0)