fix(codegen): Fixes codegen on VS2019 (#629)

- [X] Fixes code gen on VS2019
- [X] Fixes schema generator not iterating through all nodes
- [X] Fixes errors with building the actual code gen
This commit is contained in:
Kamron Batman 2021-05-31 16:30:17 -07:00 committed by GitHub
parent b6779a7c09
commit ac3958a0b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 198 additions and 45 deletions

View file

@ -13,9 +13,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
@ -36,8 +36,66 @@ namespace SerializationGenerator
ImmutableArray<INamedTypeSymbol> serializableTypes
)
{
var compilation = context.Compilation;
var version = (int)serializableAttr.ConstructorArguments[0].Value!;
var migrations = context.GetMigrationsByAnalyzerConfig(
classSymbol,
version,
jsonSerializerOptions
);
return context.Compilation.GenerateSerializationPartialClass(
classSymbol,
serializableAttr,
null, // Do not generate schema
null,
migrations.ToImmutableArray(),
fieldsAndProperties,
serializableTypes
);
}
public static string GenerateSerializationPartialClass(
this Compilation compilation,
INamedTypeSymbol classSymbol,
AttributeData serializableAttr,
string? migrationPath,
JsonSerializerOptions? jsonSerializerOptions,
ImmutableArray<ISymbol> fieldsAndProperties,
ImmutableArray<INamedTypeSymbol> serializableTypes
)
{
var version = (int)serializableAttr.ConstructorArguments[0].Value!;
var migrations = SerializableMigrationSchema.GetMigrations(
classSymbol,
version,
migrationPath,
jsonSerializerOptions
);
return compilation.GenerateSerializationPartialClass(
classSymbol,
serializableAttr,
migrationPath,
jsonSerializerOptions,
migrations.ToImmutableArray(),
fieldsAndProperties,
serializableTypes
);
}
public static string GenerateSerializationPartialClass(
this Compilation compilation,
INamedTypeSymbol classSymbol,
AttributeData serializableAttr,
string? migrationPath,
JsonSerializerOptions? jsonSerializerOptions,
ImmutableArray<SerializableMetadata> migrations,
ImmutableArray<ISymbol> fieldsAndProperties,
ImmutableArray<INamedTypeSymbol> serializableTypes
)
{
var serializableFieldAttribute =
compilation.GetTypeByMetadataName(SymbolMetadata.SERIALIZABLE_FIELD_ATTRIBUTE);
var serializableFieldAttrAttribute =
@ -120,7 +178,7 @@ namespace SerializationGenerator
else
{
var attrType = (ITypeSymbol)attrTypeArg.Value;
source.GenerateAttribute(attrType.Name, ctorArgs[1].Values);
source.GenerateAttribute(attrType?.Name, ctorArgs[1].Values);
}
}
@ -172,17 +230,9 @@ namespace SerializationGenerator
source.GenerateSerialCtor(compilation, className, isOverride);
source.AppendLine();
List<SerializableMetadata> migrations = new List<SerializableMetadata>();
if (version > 0)
{
migrations = context.GetMigrationsByAnalyzerConfig(
classSymbol,
version,
jsonSerializerOptions
);
for (var i = 0; i < migrations.Count; i++)
for (var i = 0; i < migrations.Length; i++)
{
var migration = migrations[i];
if (migration.Version < version)
@ -216,7 +266,27 @@ namespace SerializationGenerator
source.GenerateClassEnd();
source.GenerateNamespaceEnd();
if (migrationPath != null)
{
// Write the migration file
var newMigration = new SerializableMetadata
{
Version = version,
Type = classSymbol.ToDisplayString(),
Properties = serializableProperties
};
WriteMigration(migrationPath, newMigration, jsonSerializerOptions);
}
return source.ToString();
}
private static void WriteMigration(string migrationPath, SerializableMetadata metadata, JsonSerializerOptions options)
{
Directory.CreateDirectory(migrationPath);
var filePath = Path.Combine(migrationPath, $"{metadata.Type}.v{metadata.Version}.json");
File.WriteAllText(filePath, JsonSerializer.Serialize(metadata, options));
}
}
}

View file

@ -13,7 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
@ -32,7 +31,7 @@ namespace SerializationGenerator
bool isOverride,
int version,
bool encodedVersion,
List<SerializableMetadata> migrations,
ImmutableArray<SerializableMetadata> migrations,
ImmutableArray<SerializableProperty> properties
)
{
@ -61,7 +60,7 @@ namespace SerializationGenerator
{
var nextVersion = 0;
for (var i = 0; i < migrations.Count; i++)
for (var i = 0; i < migrations.Length; i++)
{
var migrationVersion = migrations[i].Version;
if (migrationVersion == nextVersion)

View file

@ -70,7 +70,7 @@ namespace SerializableMigration
Array.Copy(ruleArguments, 2, arrayElementRuleArguments, 0, ruleArguments.Length - 2);
var propertyIndex = $"{property.Name}Index";
source.AppendLine($"{indent}{property.Name} = new {ruleArguments[0]}[reader.ReadInt()];");
source.AppendLine($"{indent}{property.Name} = new {ruleArguments[0]}[reader.ReadEncodedInt()];");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; {propertyIndex} < {property.Name}.Length; {propertyIndex}++)");
source.AppendLine($"{indent}{{");
@ -101,11 +101,9 @@ namespace SerializableMigration
var arrayElementRuleArguments = new string[ruleArguments.Length - 2];
Array.Copy(ruleArguments, 2, arrayElementRuleArguments, 0, ruleArguments.Length - 2);
var propertyName = property.Name;
var propertyVarPrefix = $"{char.ToLower(propertyName[0])}{propertyName.Substring(1, propertyName.Length - 1)}";
var propertyIndex = $"{propertyVarPrefix}Index";
source.AppendLine($"{indent}writer.Write({property.Name}.Length);");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; {propertyIndex} < {propertyVarPrefix}.Length; {propertyIndex}++)");
var propertyIndex = $"{property.Name}Index";
source.AppendLine($"{indent}writer.WriteEncodedInt({property.Name}.Length);");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; {propertyIndex} < {property.Name}.Length; {propertyIndex}++)");
source.AppendLine($"{indent}{{");
var serializableArrayElement = new SerializableProperty

View file

@ -77,10 +77,12 @@ namespace SerializableMigration
var propertyVarPrefix = $"{char.ToLower(propertyName[0])}{propertyName.Substring(1, propertyName.Length - 1)}";
var propertyIndex = $"{propertyVarPrefix}Index";
var propertyEntry = $"{propertyVarPrefix}Entry";
var propertyCount = $"{propertyVarPrefix}Count";
source.AppendLine($"{indent}{ruleArguments[0]} {propertyEntry};");
source.AppendLine($"{indent}{propertyName} = new System.Collections.Generic.HashSet<{ruleArguments[0]}>(reader.ReadInt());");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; i < {propertyName}.Count; {propertyIndex}++)");
source.AppendLine($"{indent}var {propertyCount} = reader.ReadEncodedInt();");
source.AppendLine($"{indent}{property.Name} = new System.Collections.Generic.HashSet<{ruleArguments[0]}>({propertyCount});");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; i < {propertyCount}; {propertyIndex}++)");
source.AppendLine($"{indent}{{");
var serializableSetElement = new SerializableProperty
@ -114,7 +116,7 @@ namespace SerializableMigration
var propertyName = property.Name;
var propertyVarPrefix = $"{char.ToLower(propertyName[0])}{propertyName.Substring(1, propertyName.Length - 1)}";
var propertyEntry = $"{propertyVarPrefix}Entry";
source.AppendLine($"{indent}writer.Write({property.Name}.Count);");
source.AppendLine($"{indent}writer.WriteEncodedInt({property.Name}.Count);");
source.AppendLine($"{indent}foreach (var {propertyEntry} in {property.Name});");
source.AppendLine($"{indent}{{");

View file

@ -77,10 +77,12 @@ namespace SerializableMigration
var propertyVarPrefix = $"{char.ToLower(propertyName[0])}{propertyName.Substring(1, propertyName.Length - 1)}";
var propertyIndex = $"{propertyVarPrefix}Index";
var propertyEntry = $"{propertyVarPrefix}Entry";
var propertyCount = $"{propertyVarPrefix}Count";
source.AppendLine($"{indent}{ruleArguments[0]} {propertyEntry};");
source.AppendLine($"{indent}{propertyName} = new System.Collections.Generic.List<{ruleArguments[0]}>(reader.ReadInt());");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; {propertyIndex} < {propertyName}.Count; {propertyIndex}++)");
source.AppendLine($"{indent}var {propertyCount} = reader.ReadEncodedInt();");
source.AppendLine($"{indent}{propertyName} = new System.Collections.Generic.List<{ruleArguments[0]}>({propertyCount});");
source.AppendLine($"{indent}for (var {propertyIndex} = 0; {propertyIndex} < {propertyCount}; {propertyIndex}++)");
source.AppendLine($"{indent}{{");
var serializableListElement = new SerializableProperty
@ -113,7 +115,7 @@ namespace SerializableMigration
var propertyName = property.Name;
var propertyEntry = $"{char.ToLower(propertyName[0])}{propertyName.Substring(1, propertyName.Length - 1)}Entry";
source.AppendLine($"{indent}writer.Write({propertyName}.Count);");
source.AppendLine($"{indent}writer.WriteEncodedInt({propertyName}.Count);");
source.AppendLine($"{indent}foreach (var {propertyEntry} in {propertyName})");
source.AppendLine($"{indent}{{");

View file

@ -13,9 +13,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using Microsoft.CodeAnalysis;
@ -35,7 +37,37 @@ namespace SerializableMigration
private static Dictionary<string, SerializableMetadata> _cache = new();
private static Regex _fileRegex = new(@"\S+\.v\d+\.json$");
private static readonly Regex _fileRegex = new(@"\S+\.v\d+\.json$");
public static List<SerializableMetadata> GetMigrations(
INamedTypeSymbol typeSymbol,
int version,
string migrationPath,
JsonSerializerOptions options
)
{
var typeName = typeSymbol.ToDisplayString();
var migrations = new SortedSet<SerializableMetadata>(new SerializableMetadataComparer());
var migrationFiles = Directory.GetFiles(migrationPath, $"{typeName}.v*.json");
foreach (var file in migrationFiles)
{
var fi = new FileInfo(file);
if (!_cache.TryGetValue(fi.Name, out var migration))
{
var text = File.ReadAllText(file, Encoding.UTF8);
migration = JsonSerializer.Deserialize<SerializableMetadata>(text, options);
}
if (typeName == migration!.Type && version > migration.Version)
{
migrations.Add(migration);
}
}
return migrations.ToList();
}
public static List<SerializableMetadata> GetMigrationsByAnalyzerConfig(
this GeneratorExecutionContext context,

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>preview</LangVersion>
@ -10,6 +10,7 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.9.0" />
<PackageReference Include="Humanizer.Core" Version="2.10.1" GeneratePathProperty="true" PrivateAssets="all" />
<PackageReference Include="System.Text.Json" Version="5.0.0" GeneratePathProperty="true" PrivateAssets="all" />
<PackageReference Include="System.Text.Encodings.Web" Version="5.0.0" GeneratePathProperty="true" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup>
@ -20,6 +21,7 @@
<ItemGroup>
<TargetPathWithTargetPlatformMoniker Include="$(PKGHumanizer_Core)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Json)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Encodings_Web)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
</ItemGroup>
</Target>
</Project>

View file

@ -13,9 +13,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using SourceGeneration;