-
-
Notifications
You must be signed in to change notification settings - Fork 722
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reworked code gen server interaction
- Loading branch information
1 parent
708437d
commit bdbbf8e
Showing
12 changed files
with
569 additions
and
146 deletions.
There are no files selected for viewing
10 changes: 10 additions & 0 deletions
10
src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Client/GeneratorSink.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace StrawberryShake.CodeGeneration.CSharp; | ||
|
||
public static class GeneratorSink | ||
{ | ||
public static string Location => Path.Combine(Path.GetTempPath(), "__berry"); | ||
|
||
public static string ErrorLogFileName => Path.Combine(Location, "errors.log"); | ||
|
||
public static string CreateFileName() => Path.Combine(Location, Path.GetRandomFileName()); | ||
} |
27 changes: 27 additions & 0 deletions
27
src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Client/Names.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
namespace StrawberryShake.CodeGeneration.CSharp; | ||
|
||
internal static class Names | ||
{ | ||
public const string GeneratorRequest = nameof(GeneratorRequest); | ||
public const string DocumentFileName = nameof(DocumentFileName); | ||
public const string ConfigFileName = "configFileName"; | ||
public const string RootDirectory = "rootDirectory"; | ||
public const string DefaultNamespace = "defaultNamespace"; | ||
public const string PersistedQueryDirectory = "persistedQueryDirectory"; | ||
public const string Option = "option"; | ||
public const string ErrorLocation = "Location"; | ||
public const string Line = "line"; | ||
public const string Column = "column"; | ||
public const string Error = nameof(Error); | ||
public const string Code = "code"; | ||
public const string FilePath = "filePath"; | ||
public const string Title = "title"; | ||
public const string Message = nameof(Message); | ||
public const string Document = nameof(Document); | ||
public const string Hash = "hash"; | ||
public const string Path = "path"; | ||
public const string Name = "name"; | ||
public const string SourceText = nameof(SourceText); | ||
public const string Kind = "kind"; | ||
public const string GeneratorResponse = nameof(GeneratorResponse); | ||
} |
80 changes: 68 additions & 12 deletions
80
src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Client/RequestFormatter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,84 @@ | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using System.Runtime.Serialization; | ||
using System.Xml.Linq; | ||
using static System.Enum; | ||
using static StrawberryShake.CodeGeneration.CSharp.Names; | ||
using static StrawberryShake.CodeGeneration.CSharp.RequestOptions; | ||
|
||
namespace StrawberryShake.CodeGeneration.CSharp; | ||
|
||
public static class RequestFormatter | ||
{ | ||
private static readonly JsonSerializerOptions _options = new() | ||
{ | ||
Converters = { new JsonStringEnumConverter() }, | ||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase | ||
}; | ||
|
||
public static string Format(GeneratorRequest request) | ||
{ | ||
var temp = Path.Combine(Path.GetTempPath(), "__berry"); | ||
var temp = GeneratorSink.Location; | ||
|
||
if (!Directory.Exists(temp)) | ||
{ | ||
Directory.CreateDirectory(temp); | ||
} | ||
|
||
var fileName = Path.Combine(temp, Path.GetRandomFileName()); | ||
var buffer = JsonSerializer.SerializeToUtf8Bytes(request, _options); | ||
File.WriteAllBytes(fileName, buffer); | ||
var fileName = GeneratorSink.CreateFileName(); | ||
|
||
var root = new XElement(Names.GeneratorRequest); | ||
root.Add(new XAttribute(ConfigFileName, request.ConfigFileName)); | ||
root.Add(new XAttribute(RootDirectory, request.RootDirectory)); | ||
root.Add(new XAttribute(DefaultNamespace, request.DefaultNamespace ?? string.Empty)); | ||
root.Add(new XAttribute(PersistedQueryDirectory, request.PersistedQueryDirectory ?? string.Empty)); | ||
root.Add(new XAttribute(Option, request.Option.ToString())); | ||
|
||
foreach (var file in request.DocumentFileNames) | ||
{ | ||
root.Add(new XElement(DocumentFileName, file)); | ||
} | ||
|
||
using FileStream fileStream = File.Create(fileName); | ||
var document = new XDocument(); | ||
document.Add(root); | ||
document.Save(fileStream, SaveOptions.None); | ||
|
||
return fileName; | ||
} | ||
|
||
public static GeneratorRequest Take(string fileName) | ||
{ | ||
GeneratorRequest request = Parse(fileName); | ||
File.Delete(fileName); | ||
return request; | ||
} | ||
|
||
public static GeneratorRequest Parse(string fileName) | ||
{ | ||
using FileStream fileStream = File.OpenRead(fileName); | ||
var document = XDocument.Load(fileStream); | ||
|
||
if (document.Root is null || !document.Root.Name.LocalName.Equals(Names.GeneratorRequest)) | ||
{ | ||
throw new InvalidDataContractException("Missing the request root element."); | ||
} | ||
|
||
var configFileName = document.Root.Attribute(ConfigFileName)?.Value ?? | ||
throw new InvalidDataContractException("Missing the configFileName attribute."); | ||
var rootDirectory = document.Root.Attribute(RootDirectory)?.Value; | ||
var defaultNamespace = document.Root.Attribute(DefaultNamespace)?.Value; | ||
var persistedQueryDirectory = document.Root.Attribute(PersistedQueryDirectory)?.Value; | ||
var optionString = document.Root.Attribute(Option)?.Value; | ||
|
||
var documentFileNames = new List<string>(); | ||
|
||
foreach (XElement documentFileName in document.Root.Elements(DocumentFileName)) | ||
{ | ||
if (!string.IsNullOrEmpty(documentFileName.Value)) | ||
{ | ||
documentFileNames.Add(documentFileName.Value); | ||
} | ||
} | ||
|
||
return new GeneratorRequest( | ||
configFileName, | ||
documentFileNames, | ||
string.IsNullOrEmpty(rootDirectory) ? null : rootDirectory, | ||
string.IsNullOrEmpty(defaultNamespace) ? null : defaultNamespace, | ||
string.IsNullOrEmpty(persistedQueryDirectory) ? null : persistedQueryDirectory, | ||
string.IsNullOrEmpty(optionString) ? Default : Parse<RequestOptions>(optionString)); | ||
} | ||
} |
184 changes: 184 additions & 0 deletions
184
src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Client/ResponseFormatter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
using System.Runtime.Serialization; | ||
using System.Text.Json; | ||
using System.Xml.Linq; | ||
using static StrawberryShake.CodeGeneration.CSharp.Names; | ||
using Path = System.IO.Path; | ||
|
||
namespace StrawberryShake.CodeGeneration.CSharp; | ||
|
||
public static class ResponseFormatter | ||
{ | ||
public static void Format(GeneratorResponse response, string fileName) | ||
{ | ||
if (File.Exists(fileName)) | ||
{ | ||
File.Delete(fileName); | ||
} | ||
|
||
using FileStream fileStream = File.Create(fileName); | ||
var document = new XDocument(); | ||
SerializeGeneratorResponse(document, response); | ||
document.Save(fileStream, SaveOptions.None); | ||
} | ||
|
||
public static GeneratorResponse Take(string fileName) | ||
{ | ||
GeneratorResponse response = Parse(fileName); | ||
File.Delete(fileName); | ||
return response; | ||
} | ||
|
||
public static GeneratorResponse Parse(string fileName) | ||
{ | ||
using FileStream fileStream = File.OpenRead(fileName); | ||
var document = XDocument.Load(fileStream); | ||
return DeserializeGeneratorResponse(document); | ||
} | ||
|
||
private static GeneratorResponse DeserializeGeneratorResponse(XDocument document) | ||
{ | ||
if (document.Root is null || !document.Root.Name.LocalName.Equals(Names.GeneratorResponse)) | ||
{ | ||
throw new InvalidDataContractException("The generator response has an invalid format."); | ||
} | ||
|
||
var documents = new List<GeneratorDocument>(); | ||
var errors = new List<GeneratorError>(); | ||
|
||
foreach (XElement documentElement in document.Root.Elements(Document)) | ||
{ | ||
documents.Add(DeserializeGeneratorDocument(documentElement)); | ||
} | ||
|
||
foreach (XElement errorElement in document.Root.Elements(Error)) | ||
{ | ||
errors.Add(DeserializeGeneratorError(errorElement)); | ||
} | ||
|
||
return new GeneratorResponse(documents, errors); | ||
} | ||
|
||
private static void SerializeGeneratorResponse(XDocument parent, GeneratorResponse response) | ||
{ | ||
var responseElement = new XElement(Names.GeneratorResponse); | ||
|
||
foreach (GeneratorDocument document in response.Documents) | ||
{ | ||
SerializeGeneratorDocument(responseElement, document); | ||
} | ||
|
||
foreach (GeneratorError error in response.Errors) | ||
{ | ||
SerializeGeneratorError(responseElement, error); | ||
} | ||
|
||
parent.Add(responseElement); | ||
} | ||
|
||
private static GeneratorDocument DeserializeGeneratorDocument(XElement documentElement) | ||
{ | ||
XAttribute? nameAttribute = documentElement.Attribute(Name); | ||
XAttribute? kindAttribute = documentElement.Attribute(Kind); | ||
XElement? sourceTextElement = documentElement.Element(SourceText); | ||
XAttribute? hashAttribute = documentElement.Attribute(Hash); | ||
XAttribute? pathAttribute = documentElement.Attribute(Names.Path); | ||
|
||
if (nameAttribute is null || kindAttribute is null || sourceTextElement is null) | ||
{ | ||
throw new InvalidDataContractException("The document has an invalid format."); | ||
} | ||
|
||
return new GeneratorDocument( | ||
nameAttribute.Value, | ||
sourceTextElement.Value, | ||
Enum.Parse<GeneratorDocumentKind>(kindAttribute.Value), | ||
hashAttribute?.Value, | ||
pathAttribute?.Value); | ||
} | ||
|
||
private static void SerializeGeneratorDocument(XElement parent, GeneratorDocument document) | ||
{ | ||
var documentElement = new XElement(Document); | ||
documentElement.Add(new XAttribute(Name, document.Name)); | ||
documentElement.Add(new XAttribute(Kind, document.Kind.ToString())); | ||
documentElement.Add(new XElement(SourceText, document.SourceText)); | ||
|
||
if (document.Hash is not null) | ||
{ | ||
documentElement.Add(new XAttribute(Hash, document.Hash)); | ||
} | ||
|
||
if (document.Path is not null) | ||
{ | ||
documentElement.Add(new XAttribute(Names.Path, document.Path)); | ||
} | ||
|
||
parent.Add(documentElement); | ||
} | ||
|
||
private static GeneratorError DeserializeGeneratorError(XElement errorElement) | ||
{ | ||
XAttribute? codeAttribute = errorElement.Attribute(Code); | ||
XAttribute? titleAttribute = errorElement.Attribute(Title); | ||
XAttribute? filePathAttribute = errorElement.Attribute(FilePath); | ||
XElement? messageElement = errorElement.Element(Message); | ||
XElement? locationElement = errorElement.Element(ErrorLocation); | ||
|
||
if (messageElement is null || codeAttribute is null || titleAttribute is null) | ||
{ | ||
throw new InvalidDataContractException("The error has an invalid format."); | ||
} | ||
|
||
Location? location = null; | ||
if (locationElement is not null) | ||
{ | ||
location = DeserializeLocation(locationElement); | ||
} | ||
|
||
return new GeneratorError( | ||
codeAttribute.Value, | ||
titleAttribute.Value, | ||
messageElement.Value, | ||
filePathAttribute?.Value, | ||
location); | ||
} | ||
|
||
private static void SerializeGeneratorError(XElement parent, GeneratorError error) | ||
{ | ||
var errorElement = new XElement(Error); | ||
errorElement.Add(new XAttribute(Code, error.Code)); | ||
errorElement.Add(new XAttribute(Title, error.Title)); | ||
|
||
if (!string.IsNullOrEmpty(error.FilePath)) | ||
{ | ||
errorElement.Add(new XAttribute(FilePath, error.FilePath)); | ||
} | ||
|
||
errorElement.Add(new XElement(Message, error.Message)); | ||
|
||
if (error.Location is not null) | ||
{ | ||
SerializeLocation(errorElement, error.Location); | ||
} | ||
|
||
parent.Add(errorElement); | ||
} | ||
|
||
private static Location DeserializeLocation(XElement location) | ||
{ | ||
XAttribute? line = location.Attribute(Line); | ||
XAttribute? column = location.Attribute(Column); | ||
|
||
return new Location( | ||
line is null ? 0 : int.Parse(line.Value), | ||
column is null ? 0 : int.Parse(column.Value)); | ||
} | ||
|
||
private static void SerializeLocation(XElement parent, Location location) | ||
{ | ||
var locationElement = new XElement(ErrorLocation); | ||
locationElement.Add(new XAttribute(Line, location.Line)); | ||
locationElement.Add(new XAttribute(Column, location.Column)); | ||
parent.Add(locationElement); | ||
} | ||
} |
Oops, something went wrong.