Skip to content
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

Source generator tweaks #262

Merged
merged 7 commits into from
Mar 22, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Tools/Schema.NET.Tool/Models/SchemaClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public class SchemaClass : SchemaObject
{
private static readonly Uri EnumerationId = new("https://schema.org/Enumeration");

public SchemaClass(Uri id, string label, string layer)
: base(id, label, layer)
public SchemaClass(string comment, Uri id, string label, string layer)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comment. It would be nice if the order of parameters in these constructos followed the hierarchy of data.

string layer, Uri id, string label, string comment

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to do that. While I know what hierarchy means, I'm not sure exactly how you're deriving it - like these properties exist in the same hierarchy of inheritance. Just want to understand how you want it.

I went alphabetical for this but felt weird to have comment first.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think layer comes first because it groups many types together. The ID for a type makes sense next as it is the unique identifier. After that the label seems to make sense to me, although I can't explain why. After these three, I think going with alphabetical ordering is fine, unless it makes sense to group parameters together somehow.

: base(comment, id, label, layer)
{
}

Expand Down
4 changes: 2 additions & 2 deletions Tools/Schema.NET.Tool/Models/SchemaEnumerationValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace Schema.NET.Tool.Models

public class SchemaEnumerationValue : SchemaObject
{
public SchemaEnumerationValue(Uri id, string label, string layer)
: base(id, label, layer)
public SchemaEnumerationValue(string comment, Uri id, string label, string layer)
: base(comment, id, label, layer)
{
}
}
Expand Down
7 changes: 4 additions & 3 deletions Tools/Schema.NET.Tool/Models/SchemaObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,22 @@ public abstract class SchemaObject
"PronounceableText",
};

public SchemaObject(Uri id, string label, string layer)
public SchemaObject(string comment, Uri id, string label, string layer)
{
this.Comment = comment;
this.Id = id;
this.Label = label;
this.Layer = layer;
}

public string Comment { get; }

public Uri Id { get; }

public string Label { get; }

public string Layer { get; }

public string? Comment { get; set; }

public List<string> Types { get; } = new List<string>();

public virtual bool IsArchived => string.Equals(this.Layer, LayerName.Archived, StringComparison.OrdinalIgnoreCase);
Expand Down
4 changes: 2 additions & 2 deletions Tools/Schema.NET.Tool/Models/SchemaProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace Schema.NET.Tool.Models

public class SchemaProperty : SchemaObject
{
public SchemaProperty(Uri id, string label, string layer)
: base(id, label, layer)
public SchemaProperty(string comment, Uri id, string label, string layer)
: base(comment, id, label, layer)
{
}

Expand Down
34 changes: 15 additions & 19 deletions Tools/Schema.NET.Tool/Repositories/SchemaPropertyJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,17 @@ public override void Write(Utf8JsonWriter writer, List<SchemaObject> value, Json
var id = SchemaOrgUrl(idToken.GetString()!);
var types = GetTokenValues(token, "@type").ToArray();

string? comment;
string comment;
if (commentToken.ValueKind == JsonValueKind.Object && commentToken.TryGetProperty("@value", out var commentValueToken))
{
comment = commentValueToken.GetString();
comment = commentValueToken.GetString()!;
}
else
{
comment = commentToken.GetString();
comment = commentToken.GetString()!;
}

var label = GetLabel(token);
var domainIncludes = GetTokenValues(token, "schema:domainIncludes", "@id").Select(SchemaOrgUrl).ToArray();
var rangeIncludes = GetTokenValues(token, "schema:rangeIncludes", "@id").Select(SchemaOrgUrl).ToArray();
var subClassOf = GetTokenValues(token, "rdfs:subClassOf", "@id").Select(SchemaOrgUrl).ToArray();
var isPartOf = GetTokenValues(token, "schema:isPartOf", "@id").Select(s => new Uri(s)).FirstOrDefault();

var layer = LayerName.Core;
Expand All @@ -75,32 +72,31 @@ public override void Write(Utf8JsonWriter writer, List<SchemaObject> value, Json

if (types.Any(type => string.Equals(type, "rdfs:Class", StringComparison.Ordinal)))
{
var schemaClass = new SchemaClass(id, label, layer)
{
Comment = comment,
};
var schemaClass = new SchemaClass(comment, id, label, layer);

var subClassOf = GetTokenValues(token, "rdfs:subClassOf", "@id").Select(SchemaOrgUrl);
schemaClass.SubClassOfIds.AddRange(subClassOf);

schemaClass.Types.AddRange(types);
return schemaClass;
}
else if (types.Any(type => string.Equals(type, "rdf:Property", StringComparison.Ordinal)))
{
var schemaProperty = new SchemaProperty(id, label, layer)
{
Comment = comment,
};
var schemaProperty = new SchemaProperty(comment, id, label, layer);

var domainIncludes = GetTokenValues(token, "schema:domainIncludes", "@id").Select(SchemaOrgUrl);
schemaProperty.DomainIncludes.AddRange(domainIncludes);

var rangeIncludes = GetTokenValues(token, "schema:rangeIncludes", "@id").Select(SchemaOrgUrl);
schemaProperty.RangeIncludes.AddRange(rangeIncludes);

schemaProperty.Types.AddRange(types);
return schemaProperty;
}
else
{
var schemaEnumerationValue = new SchemaEnumerationValue(id, label, layer)
{
Comment = comment,
};
schemaEnumerationValue.Types.AddRange(types.Select(SchemaOrgUrl).Select(u => u.ToString()).ToArray());
var schemaEnumerationValue = new SchemaEnumerationValue(comment, id, label, layer);
schemaEnumerationValue.Types.AddRange(types.Select(SchemaOrgUrl).Select(u => u.ToString()));
return schemaEnumerationValue;
}
}
Expand Down
11 changes: 6 additions & 5 deletions Tools/Schema.NET.Tool/Repositories/SchemaRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace Schema.NET.Tool.Repositories
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
Expand Down Expand Up @@ -35,23 +36,23 @@ public class SchemaRepository : ISchemaRepository
public async Task<IEnumerable<SchemaObject>?> GetSchemaObjectsAsync()
{
using (var response = await this.httpClient
.GetAsync(new Uri("/version/latest/schemaorg-all-https.jsonld", UriKind.Relative))
.GetAsync(new Uri("/version/latest/schemaorg-all-https.jsonld", UriKind.Relative), HttpCompletionOption.ResponseHeadersRead)
.ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return Deserialize<List<SchemaObject>>(json, new SchemaPropertyJsonConverter());
var jsonStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return await DeserializeAsync<List<SchemaObject>>(jsonStream, new SchemaPropertyJsonConverter()).ConfigureAwait(false);
}
}

private static T? Deserialize<T>(string json, JsonConverter converter)
private static async Task<T?> DeserializeAsync<T>(Stream jsonStream, JsonConverter converter)
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
options.Converters.Add(converter);
return JsonSerializer.Deserialize<T>(json, options);
return await JsonSerializer.DeserializeAsync<T>(jsonStream, options).ConfigureAwait(false);
}
}
}
51 changes: 28 additions & 23 deletions Tools/Schema.NET.Tool/SchemaSourceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ namespace Schema.NET.Tool
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Schema.NET.Tool.CustomOverrides;
using Schema.NET.Tool.GeneratorModels;
Expand All @@ -14,41 +13,47 @@ namespace Schema.NET.Tool
[Generator]
public class SchemaSourceGenerator : ISourceGenerator
{
private IEnumerable<GeneratorSchemaObject>? SchemaObjects { get; set; }
private static readonly object SchemaLock = new();

private static IEnumerable<GeneratorSchemaObject>? SchemaObjects { get; set; }

public void Initialize(GeneratorInitializationContext context)
{
#pragma warning disable IDE0022 // Use expression body for methods
Task.Run(async () =>
var schemaRepository = new SchemaRepository(new HttpClient()
{
BaseAddress = new Uri("https://schema.org"),
});
var schemaService = new SchemaService(
new IClassOverride[]
{
new AddQueryInputPropertyToSearchAction(),
new AddTextTypeToActionTarget(),
new AddNumberTypeToMediaObjectHeightAndWidth(),
new RenameEventProperty(),
},
Array.Empty<IEnumerationOverride>(),
schemaRepository,
false);

if (SchemaObjects is null)
{
var schemaRepository = new SchemaRepository(new HttpClient()
lock (SchemaLock)
{
BaseAddress = new Uri("https://schema.org"),
});
var schemaService = new SchemaService(
new IClassOverride[]
if (SchemaObjects is null)
{
new AddQueryInputPropertyToSearchAction(),
new AddTextTypeToActionTarget(),
new AddNumberTypeToMediaObjectHeightAndWidth(),
new RenameEventProperty(),
},
Array.Empty<IEnumerationOverride>(),
schemaRepository,
false);

this.SchemaObjects = await schemaService.GetObjectsAsync().ConfigureAwait(false);
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
}).GetAwaiter().GetResult();
#pragma warning restore IDE0022 // Use expression body for methods
SchemaObjects = schemaService.GetObjectsAsync().GetAwaiter().GetResult();
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
}
}
}
}

public void Execute(GeneratorExecutionContext context)
{
if (this.SchemaObjects is not null)
if (SchemaObjects is not null)
{
foreach (var schemaObject in this.SchemaObjects)
foreach (var schemaObject in SchemaObjects)
{
var source = string.Empty;
if (schemaObject is GeneratorSchemaClass schemaClass)
Expand Down