-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Try methods to JsonObject #111229
base: main
Are you sure you want to change the base?
Add Try methods to JsonObject #111229
Conversation
@dotnet-policy-service agree |
@eiriktsarpalis Sorry to trouble you, I would have written some tests, but at the moment I seem not to be able to run any. I followed the testing guide here: docs/workflow/testing/libraries/testing.md Neither |
Don't use the global |
@huoyaoyuan then how can I debug in Visual Studio if I need to use dotnet.cmd? Also, for example, if I needed to execute the tests in |
@Flu You can use the
That should make it possible to run tests from the test explorer as normal. |
@eiriktsarpalis I am now getting this error when trying to run the tests from inside visual studio after I've used your command:
This has nothing to do with my changes, as it's happening on the main branch as well, most recent commit. |
@Flu did you try building the full runtime+libraries first?
|
@eiriktsarpalis Yes. I mean, I am adding test.libs as well:
This is the exact command I've been using. Removing the |
And that step is building successfully? |
Yes |
@ViktorHofer any ideas what might be missing? |
Yes, it looks like APICompat is currently broken on desktop msbuild (which is used inside VS): dotnet/sdk#45004 |
You shouldn't need to disable ApiCompat to get your dev environment set up though. I would recommend stashing your changes, then build the repo, make sure that tests run from the IDE, and finally pop your changes back in. |
I've been having this issue as well. The workaround that I use is to run the tests from VS test explorer but when the build fails and VS shows the failure dialog, select "Yes" to run tests from last successful build. Everything (e.g. debugging, breakpoints, etc.) works as expected since the API compat step of the build (which is component that is failing) seems to be after the product and test binaries are already generated.
You should be able to use |
@PranavSenthilnathan Thank you, it finally worked. Clever solution! |
@eiriktsarpalis I'm ready for a review |
@@ -34,6 +34,43 @@ public void Add(string propertyName, JsonNode? value) | |||
value?.AssignParent(this); | |||
} | |||
|
|||
/// <summary> | |||
/// Adds an element with the provided name and value to the <see cref="JsonObject"/>, if a property named <paramref name="propertyName"/> doesn't already exist.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Adds an element with the provided name and value to the <see cref="JsonObject"/>, if a property named <paramref name="propertyName"/> doesn't already exist.. | |
/// Adds an element with the provided name and value to the <see cref="JsonObject"/>, if a property named <paramref name="propertyName"/> doesn't already exist. |
ThrowHelper.ThrowArgumentNullException(nameof(propertyName)); | ||
} | ||
|
||
var success = Dictionary.TryAdd(propertyName, value, out index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably failing to build in .NET 9 since that version of OrderedDictionary doesn't have the overload that exposes the index. I would recommend emulating the behavior using a second lookup via IndexOf
in .NET 9 targets.
@@ -62,12 +62,16 @@ public bool TryAdd(string propertyName, JsonNode? value, out int index) | |||
ThrowHelper.ThrowArgumentNullException(nameof(propertyName)); | |||
} | |||
|
|||
#if NET10_0_OR_GREATER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only need this for .NET 9. Earlier targets polyfill the current OrderedDictionary implementation.
#if NET10_0_OR_GREATER | |
#if NET9_0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume it becomes this then?
#if NET9_0
var success = Dictionary.TryAdd(propertyName, value);
index = Dictionary.IndexOf(propertyName);
#else
var success = Dictionary.TryAdd(propertyName, value, out index);
#endif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right.
var success = Dictionary.TryAdd(propertyName, value); | ||
index = Dictionary.IndexOf(propertyName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var success = Dictionary.TryAdd(propertyName, value); | |
index = Dictionary.IndexOf(propertyName); | |
var success = Dictionary.TryAdd(propertyName, value); | |
index = success ? Dictionary.Count : Dictionary.IndexOf(propertyName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be Count - 1? Also, this assumes that OD appends new entries at the end, but what if that changes in the future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it should be Count - 1
.
Even though I don't think it's likely for that to change (it's by definition ordered the way elements are added), the fix to not using Count - 1
is to just leave the code like it is now, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that should've been Count - 1
.
Also, this assumes that OD appends new entries at the end, but what if that changes in the future?
Hmm, independent of however it's currently implemented, what invariant is Ordered
supposed to guarantee?
An alternative is to do IndexOf
first and if it doesn't exist then do d.Insert(d.Count, key, value)
(note: not Count - 1
) which would add at the end.
Not optimizing this case is also fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, I don't think that it would ever change; I'm just pointing out that it's depending on an invariant from a separate component.
what invariant is Ordered supposed to guarantee?
It's a dictionary that also implements a deterministic IList with
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what is the consensus here? Do I leave it as it is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine to apply the optimisation provided there is test coverage, e.g. a test that verifies that the returned index is correct in that scenario.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment above the line explaining the arrangement might help as well.
index = Dictionary.IndexOf(propertyName); | ||
return Dictionary.TryGetValue(propertyName, out jsonNode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to above, the TryGetValue
can be skipped if IndexOf
returns false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this one can be improved:
index = Dictionary.IndexOf(propertyName);
if (index == -1)
{
return Dictionary.TryGetValue(propertyName, out jsonNode);
}
jsonNode = null;
return false;
Something like this for the .NET 9 part
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once you have the index you don't need to perform another key-based lookup:
index = Dictionary.IndexOf(propertyName);
if (index < 0)
{
jsonNode = null;
return false;
}
jsonNode = Dictionary.GetAt(index);
return true;
As per the API proposed in #110244, the following functions have been added to
JsonObject
:This resolves #110244