Skip to content

Commit

Permalink
Parse the assets file with System.Text.Json (#5627)
Browse files Browse the repository at this point in the history
Crated a new struct to parse the assets file using System.Text.Json instead of Newtonsoft. It will read the file without loading it completely in memory, reducing memory allocations. 

PRs associated with this:
* Create class for reading Json files in chunks (#5530)
* System.Text.Json Migration - Adding code to parse the PackageSpec using STJ (#5541)
* System.Text.Json Migration - Adding code to parse the Project.Assets.Json file using STJ.  (#5558)
* Create class for reading Json files in chunks (#5530)
  • Loading branch information
jgonz120 authored Feb 12, 2024
1 parent 8b658e2 commit ef5bce3
Show file tree
Hide file tree
Showing 35 changed files with 6,681 additions and 1,791 deletions.
3 changes: 2 additions & 1 deletion src/NuGet.Core/NuGet.ProjectModel/DependencyGraphSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NuGet.Common;
using NuGet.Packaging;

Expand Down Expand Up @@ -253,7 +252,9 @@ public static DependencyGraphSpec Load(string path)
case "projects":
jsonReader.ReadObject(projectsPropertyName =>
{
#pragma warning disable CS0612 // Type or member is obsolete
PackageSpec packageSpec = JsonPackageSpecReader.GetPackageSpec(jsonReader, name: null, path, EnvironmentVariableWrapper.Instance);
#pragma warning restore CS0612 // Type or member is obsolete
dgspec._projects.Add(projectsPropertyName, packageSpec);
});
break;
Expand Down
52 changes: 28 additions & 24 deletions src/NuGet.Core/NuGet.ProjectModel/FileFormatException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ internal static FileFormatException Create(Exception exception, int line, int co
return ex.WithFilePath(path).WithLineInfo(line, column);
}

internal static FileFormatException Create(Exception exception, string path)
{
var message = string.Format(CultureInfo.CurrentCulture,
Strings.Log_ErrorReadingProjectJson,
path,
exception.Message);

var ex = new FileFormatException(message, exception);

return ex.WithFilePath(path);
}

public static FileFormatException Create(string message, JToken value, string path)
{
var lineInfo = (IJsonLineInfo)value;
Expand All @@ -101,32 +113,24 @@ internal static FileFormatException Create(string message, int line, int column,
return ex.WithFilePath(path).WithLineInfo(line, column);
}

internal static FileFormatException Create(Exception exception, string path)
internal static FileFormatException Create(JsonReaderException exception, string path)
{
var jex = exception as JsonReaderException;

string message;
if (jex == null)
{
message = string.Format(CultureInfo.CurrentCulture,
Strings.Log_ErrorReadingProjectJson,
path,
exception.Message);

return new FileFormatException(message, exception).WithFilePath(path);
}
else
{
message = string.Format(CultureInfo.CurrentCulture,
Strings.Log_ErrorReadingProjectJsonWithLocation,
path, jex.LineNumber,
jex.LinePosition,
exception.Message);

return new FileFormatException(message, exception)
.WithFilePath(path)
.WithLineInfo(jex);
}
message = string.Format(CultureInfo.CurrentCulture,
Strings.Log_ErrorReadingProjectJsonWithLocation,
path, exception.LineNumber,
exception.LinePosition,
exception.Message);

return new FileFormatException(message, exception)
.WithFilePath(path)
.WithLineInfo(exception);
}

internal static FileFormatException Create(string message, string path)
{
return new FileFormatException(message)
.WithFilePath(path);
}
}
}
1,825 changes: 1,825 additions & 0 deletions src/NuGet.Core/NuGet.ProjectModel/JsonPackageSpecReader.Utf8JsonStreamReader.cs

Large diffs are not rendered by default.

77 changes: 65 additions & 12 deletions src/NuGet.Core/NuGet.ProjectModel/JsonPackageSpecReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@

namespace NuGet.ProjectModel
{
public static class JsonPackageSpecReader
public static partial class JsonPackageSpecReader
{
private static readonly char[] DelimitedStringSeparators = { ' ', ',' };
private static readonly char[] VersionSeparators = new[] { ';' };

private const char VersionSeparator = ';';
public static readonly string RestoreOptions = "restore";
public static readonly string RestoreSettings = "restoreSettings";
public static readonly string HideWarningsAndErrors = "hideWarningsAndErrors";
Expand All @@ -49,31 +49,52 @@ public static PackageSpec GetPackageSpec(string json, string name, string packag
}
}

public static PackageSpec GetPackageSpec(Stream stream, string name, string packageSpecPath, string snapshotValue)
{
return GetPackageSpec(stream, name, packageSpecPath, snapshotValue, EnvironmentVariableWrapper.Instance);
}

[Obsolete("This method is obsolete and will be removed in a future release.")]
public static PackageSpec GetPackageSpec(JObject json)
{
return GetPackageSpec(json, name: null, packageSpecPath: null, snapshotValue: null);
}

public static PackageSpec GetPackageSpec(Stream stream, string name, string packageSpecPath, string snapshotValue)
[Obsolete("This method is obsolete and will be removed in a future release.")]
public static PackageSpec GetPackageSpec(JObject rawPackageSpec, string name, string packageSpecPath, string snapshotValue)
{
using (var streamReader = new StreamReader(stream))
using (var jsonReader = new JsonTextReader(streamReader))
using (var stringReader = new StringReader(rawPackageSpec.ToString()))
using (var jsonReader = new JsonTextReader(stringReader))
{
return GetPackageSpec(jsonReader, name, packageSpecPath, EnvironmentVariableWrapper.Instance, snapshotValue);
}
}

[Obsolete("This method is obsolete and will be removed in a future release.")]
public static PackageSpec GetPackageSpec(JObject rawPackageSpec, string name, string packageSpecPath, string snapshotValue)
[Obsolete]
internal static PackageSpec GetPackageSpec(JsonTextReader jsonReader, string packageSpecPath)
{
using (var stringReader = new StringReader(rawPackageSpec.ToString()))
using (var jsonReader = new JsonTextReader(stringReader))
return GetPackageSpec(jsonReader, name: null, packageSpecPath, EnvironmentVariableWrapper.Instance);
}

internal static PackageSpec GetPackageSpec(Stream stream, string name, string packageSpecPath, string snapshotValue, IEnvironmentVariableReader environmentVariableReader, bool bypassCache = false)
{
if (!JsonUtility.UseNewtonsoftJsonForParsing(environmentVariableReader, bypassCache))
{
return GetPackageSpec(jsonReader, name, packageSpecPath, EnvironmentVariableWrapper.Instance, snapshotValue);
return GetPackageSpecUtf8JsonStreamReader(stream, name, packageSpecPath, environmentVariableReader, snapshotValue);
}
else
{
using (var textReader = new StreamReader(stream))
using (var jsonReader = new JsonTextReader(textReader))
{
#pragma warning disable CS0612 // Type or member is obsolete
return GetPackageSpec(jsonReader, name, packageSpecPath, environmentVariableReader, snapshotValue);
#pragma warning restore CS0612 // Type or member is obsolete
}
}
}

[Obsolete]
internal static PackageSpec GetPackageSpec(JsonTextReader jsonReader, string name, string packageSpecPath, IEnvironmentVariableReader environmentVariableReader, string snapshotValue = null)
{
var packageSpec = new PackageSpec();
Expand Down Expand Up @@ -232,6 +253,7 @@ internal static PackageSpec GetPackageSpec(JsonTextReader jsonReader, string nam
return packageSpec;
}

[Obsolete]
private static PackageType CreatePackageType(JsonTextReader jsonReader)
{
var name = (string)jsonReader.Value;
Expand All @@ -253,6 +275,7 @@ private static void ReadBuildOptions(JsonTextReader jsonReader, PackageSpec pack
});
}

[Obsolete]
private static void ReadCentralPackageVersions(
JsonTextReader jsonReader,
IDictionary<string, CentralPackageVersion> centralPackageVersions,
Expand Down Expand Up @@ -287,6 +310,7 @@ private static void ReadCentralPackageVersions(
});
}

[Obsolete]
private static CompatibilityProfile ReadCompatibilityProfile(JsonTextReader jsonReader, string profileName)
{
List<FrameworkRuntimePair> sets = null;
Expand All @@ -303,6 +327,7 @@ private static CompatibilityProfile ReadCompatibilityProfile(JsonTextReader json
return new CompatibilityProfile(profileName, sets ?? Enumerable.Empty<FrameworkRuntimePair>());
}

[Obsolete]
private static IEnumerable<FrameworkRuntimePair> ReadCompatibilitySets(JsonTextReader jsonReader, string compatibilitySetName)
{
NuGetFramework framework = NuGetFramework.Parse(compatibilitySetName);
Expand All @@ -315,7 +340,8 @@ private static IEnumerable<FrameworkRuntimePair> ReadCompatibilitySets(JsonTextR
}
}

internal static void ReadDependencies(
[Obsolete]
private static void ReadDependencies(
JsonTextReader jsonReader,
IList<LibraryDependency> results,
string packageSpecPath,
Expand Down Expand Up @@ -509,6 +535,7 @@ internal static void ReadDependencies(
});
}

[Obsolete]
internal static void ReadCentralTransitiveDependencyGroup(
JsonTextReader jsonReader,
IList<LibraryDependency> results,
Expand Down Expand Up @@ -631,6 +658,7 @@ internal static void ReadCentralTransitiveDependencyGroup(
});
}

[Obsolete]
private static void ReadDownloadDependencies(
JsonTextReader jsonReader,
IList<DownloadDependency> downloadDependencies,
Expand Down Expand Up @@ -721,13 +749,15 @@ private static void ReadDownloadDependencies(
}
}

[Obsolete]
private static IReadOnlyList<string> ReadEnumerableOfString(JsonTextReader jsonReader)
{
string value = jsonReader.ReadNextTokenAsString();

return value.Split(DelimitedStringSeparators, StringSplitOptions.RemoveEmptyEntries);
}

[Obsolete]
private static void ReadFrameworkReferences(
JsonTextReader jsonReader,
ISet<FrameworkDependency> frameworkReferences,
Expand Down Expand Up @@ -763,6 +793,7 @@ private static void ReadFrameworkReferences(
});
}

[Obsolete]
private static void ReadFrameworks(JsonTextReader jsonReader, PackageSpec packageSpec)
{
jsonReader.ReadObject(_ =>
Expand All @@ -781,6 +812,7 @@ private static void ReadFrameworks(JsonTextReader jsonReader, PackageSpec packag
});
}

[Obsolete]
private static void ReadImports(PackageSpec packageSpec, JsonTextReader jsonReader, TargetFrameworkInformation targetFrameworkInformation)
{
int lineNumber = jsonReader.LineNumber;
Expand Down Expand Up @@ -812,6 +844,7 @@ private static void ReadImports(PackageSpec packageSpec, JsonTextReader jsonRead
}
}

[Obsolete]
private static void ReadMappings(JsonTextReader jsonReader, string mappingKey, IDictionary<string, IncludeExcludeFiles> mappings)
{
if (jsonReader.ReadNextToken())
Expand Down Expand Up @@ -889,6 +922,7 @@ private static void ReadMappings(JsonTextReader jsonReader, string mappingKey, I
}
}

[Obsolete]
private static void ReadMSBuildMetadata(JsonTextReader jsonReader, PackageSpec packageSpec, IEnvironmentVariableReader environmentVariableReader)
{
var centralPackageVersionsManagementEnabled = false;
Expand Down Expand Up @@ -1233,6 +1267,7 @@ private static bool ReadNextTokenAsBoolOrFalse(JsonTextReader jsonReader, string
return false;
}

[Obsolete]
private static void ReadNuGetLogCodes(JsonTextReader jsonReader, HashSet<NuGetLogCode> hashCodes)
{
if (jsonReader.ReadNextToken() && jsonReader.TokenType == JsonToken.StartArray)
Expand Down Expand Up @@ -1267,6 +1302,7 @@ private static IList<NuGetLogCode> ReadNuGetLogCodesList(JsonTextReader jsonRead
return items ?? Array.Empty<NuGetLogCode>();
}

[Obsolete]
private static void ReadPackageTypes(PackageSpec packageSpec, JsonTextReader jsonReader)
{
var errorLine = 0;
Expand Down Expand Up @@ -1471,7 +1507,8 @@ private static bool ReadPackOptionsFiles(PackageSpec packageSpec, JsonTextReader
return wasMappingsRead;
}

private static RuntimeDependencySet ReadRuntimeDependencySet(JsonTextReader jsonReader, string dependencySetName)
[Obsolete]
static RuntimeDependencySet ReadRuntimeDependencySet(JsonTextReader jsonReader, string dependencySetName)
{
List<RuntimePackageDependency> dependencies = null;

Expand All @@ -1489,6 +1526,7 @@ private static RuntimeDependencySet ReadRuntimeDependencySet(JsonTextReader json
dependencies);
}

[Obsolete]
private static RuntimeDescription ReadRuntimeDescription(JsonTextReader jsonReader, string runtimeName)
{
List<string> inheritedRuntimes = null;
Expand Down Expand Up @@ -1516,6 +1554,7 @@ private static RuntimeDescription ReadRuntimeDescription(JsonTextReader jsonRead
additionalDependencies);
}

[Obsolete]
private static List<RuntimeDescription> ReadRuntimes(JsonTextReader jsonReader)
{
var runtimeDescriptions = new List<RuntimeDescription>();
Expand Down Expand Up @@ -1564,13 +1603,15 @@ private static void ReadScripts(JsonTextReader jsonReader, PackageSpec packageSp
});
}

[Obsolete]
private static string[] ReadStringArray(JsonTextReader jsonReader)
{
List<string> list = jsonReader.ReadStringArrayAsList();

return list?.ToArray();
}

[Obsolete]
private static List<CompatibilityProfile> ReadSupports(JsonTextReader jsonReader)
{
var compatibilityProfiles = new List<CompatibilityProfile>();
Expand All @@ -1585,6 +1626,7 @@ private static List<CompatibilityProfile> ReadSupports(JsonTextReader jsonReader
return compatibilityProfiles;
}

[Obsolete]
private static LibraryDependencyTarget ReadTarget(
JsonTextReader jsonReader,
string packageSpecPath,
Expand Down Expand Up @@ -1615,6 +1657,7 @@ private static LibraryDependencyTarget ReadTarget(
return targetFlagsValue;
}

[Obsolete]
private static List<ProjectRestoreMetadataFrameworkInfo> ReadTargetFrameworks(JsonTextReader jsonReader)
{
var targetFrameworks = new List<ProjectRestoreMetadataFrameworkInfo>();
Expand Down Expand Up @@ -1688,6 +1731,7 @@ private static List<ProjectRestoreMetadataFrameworkInfo> ReadTargetFrameworks(Js
return targetFrameworks;
}

[Obsolete]
private static void ReadTargetFrameworks(PackageSpec packageSpec, JsonTextReader jsonReader, out int frameworkLine, out int frameworkColumn)
{
frameworkLine = 0;
Expand Down Expand Up @@ -1768,6 +1812,12 @@ private static void ReadTargetFrameworks(PackageSpec packageSpec, JsonTextReader
}
}, out frameworkLine, out frameworkColumn);

AddTargetFramework(packageSpec, frameworkName, secondaryFramework, targetFrameworkInformation);
}

[Obsolete]
private static void AddTargetFramework(PackageSpec packageSpec, NuGetFramework frameworkName, NuGetFramework secondaryFramework, TargetFrameworkInformation targetFrameworkInformation)
{
NuGetFramework updatedFramework = frameworkName;

if (targetFrameworkInformation.Imports.Count > 0)
Expand All @@ -1793,6 +1843,8 @@ private static void ReadTargetFrameworks(PackageSpec packageSpec, JsonTextReader
packageSpec.TargetFrameworks.Add(targetFrameworkInformation);
}


[Obsolete]
private static NuGetFramework GetDualCompatibilityFrameworkIfNeeded(NuGetFramework frameworkName, NuGetFramework secondaryFramework)
{
if (secondaryFramework != default)
Expand All @@ -1803,6 +1855,7 @@ private static NuGetFramework GetDualCompatibilityFrameworkIfNeeded(NuGetFramewo
return frameworkName;
}

[Obsolete]
private static bool ValidateDependencyTarget(LibraryDependencyTarget targetValue)
{
var isValid = false;
Expand Down
Loading

0 comments on commit ef5bce3

Please sign in to comment.