Browse Source

Allow user to set generator newline output type (#1915)

* Allow user defined `NewLine` sequence

* Auto detect line endings

* Handle exception if `git` is not found
pull/1917/head
Jelle 4 months ago committed by GitHub
parent
commit
0f3badd62b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 12
      src/Generator/Driver.cs
  2. 8
      src/Generator/Generators/CodeGenerator.cs
  3. 11
      src/Generator/Options.cs
  4. 4
      src/Generator/Passes/GetterSetterToPropertyPass.cs
  5. 6
      src/Generator/Utils/BlockGenerator.cs
  6. 76
      src/Generator/Utils/ProcessHelper.cs
  7. 25
      src/Generator/Utils/TextGenerator.cs
  8. 58
      src/Generator/Utils/Utils.cs

12
src/Generator/Driver.cs

@ -45,8 +45,20 @@ namespace CppSharp @@ -45,8 +45,20 @@ namespace CppSharp
}
if (Options.NoGenIncludeDirs != null)
{
foreach (var incDir in Options.NoGenIncludeDirs)
ParserOptions.AddIncludeDirs(incDir);
}
NewLineType newLineType = Options.OutputNewLineType;
if (Options.OutputNewLineType == NewLineType.Auto)
{
var sourceNewLineType = GeneratorHelpers.GetNewLineTypeFromGitConfig(Options.OutputDir);
newLineType = sourceNewLineType ?? NewLineType.Host;
}
TextGenerator.SetLineEndingType(newLineType);
}
public void Setup()

8
src/Generator/Generators/CodeGenerator.cs

@ -140,11 +140,13 @@ namespace CppSharp.Generators @@ -140,11 +140,13 @@ namespace CppSharp.Generators
var lines = new List<string>();
if (comment.BriefText.Contains("\n"))
if (comment.BriefText.Contains('\n'))
{
var commentLines = HtmlEncoder.HtmlEncode(comment.BriefText)
.Split('\n', '\r');
lines.Add("<summary>");
foreach (string line in HtmlEncoder.HtmlEncode(comment.BriefText).Split(
Environment.NewLine.ToCharArray()))
foreach (string line in commentLines)
{
if (string.IsNullOrWhiteSpace(line))
continue;

11
src/Generator/Options.cs

@ -15,6 +15,15 @@ namespace CppSharp @@ -15,6 +15,15 @@ namespace CppSharp
FilePerUnit
}
public enum NewLineType
{
Auto, // Attempt to auto-detect the new line type using git repository settings of the output directory
Host, // Same as Environment.NewLine on the source generator host
LF,
CR,
CRLF,
}
public class DriverOptions
{
public DriverOptions()
@ -84,6 +93,8 @@ namespace CppSharp @@ -84,6 +93,8 @@ namespace CppSharp
public string OutputDir;
public NewLineType OutputNewLineType = NewLineType.Auto;
public bool OutputInteropIncludes;
public bool GenerateFunctionTemplates;
/// <summary>

4
src/Generator/Passes/GetterSetterToPropertyPass.cs

@ -334,8 +334,8 @@ namespace CppSharp.Passes @@ -334,8 +334,8 @@ namespace CppSharp.Passes
Method setter = property.SetMethod;
if (getter != setter && setter?.Comment != null)
{
comment.BriefText += Environment.NewLine + setter.Comment.BriefText;
comment.Text += Environment.NewLine + setter.Comment.Text;
comment.BriefText += TextGenerator.NewLineChar + setter.Comment.BriefText;
comment.Text += TextGenerator.NewLineChar + setter.Comment.Text;
comment.FullComment.Blocks.AddRange(setter.Comment.FullComment.Blocks);
}
}

6
src/Generator/Utils/BlockGenerator.cs

@ -135,12 +135,12 @@ namespace CppSharp @@ -135,12 +135,12 @@ namespace CppSharp
if (previousBlock != null &&
(previousBlock.NewLineKind == NewLineKind.BeforeNextBlock ||
(previousBlock.NewLineKind == NewLineKind.IfNotEmpty && !previousBlockEmpty)))
builder.AppendLine();
builder.Append(TextGenerator.NewLineChar);
builder.Append(childText);
if (childBlock.NewLineKind == NewLineKind.Always)
builder.AppendLine();
builder.Append(TextGenerator.NewLineChar);
previousBlock = childBlock;
previousBlockEmpty = childText.Length == 0;
@ -318,7 +318,7 @@ namespace CppSharp @@ -318,7 +318,7 @@ namespace CppSharp
private readonly BlockGenerator generator;
private readonly NewLineKind next;
public PushedBlock(BlockGenerator generator, NewLineKind next)
public PushedBlock(BlockGenerator generator, NewLineKind next)
{
this.generator = generator;
this.next = next;

76
src/Generator/Utils/ProcessHelper.cs

@ -7,46 +7,50 @@ namespace CppSharp.Utils @@ -7,46 +7,50 @@ namespace CppSharp.Utils
{
public static string Run(string path, string args, out int error, out string errorMessage)
{
using (var process = new Process())
return RunFrom(null, path, args, out error, out errorMessage);
}
public static string RunFrom(string workingDir, string path, string args, out int error, out string errorMessage)
{
using var process = new Process();
process.StartInfo.WorkingDirectory = workingDir;
process.StartInfo.FileName = path;
process.StartInfo.Arguments = args;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
var reterror = new StringBuilder();
var retout = new StringBuilder();
process.OutputDataReceived += (sender, outargs) =>
{
if (string.IsNullOrEmpty(outargs.Data))
return;
if (retout.Length > 0)
retout.AppendLine();
retout.Append(outargs.Data);
};
process.ErrorDataReceived += (sender, errargs) =>
{
process.StartInfo.FileName = path;
process.StartInfo.Arguments = args;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
if (string.IsNullOrEmpty(errargs.Data))
return;
var reterror = new StringBuilder();
var retout = new StringBuilder();
process.OutputDataReceived += (sender, outargs) =>
{
if (!string.IsNullOrEmpty(outargs.Data))
{
if (retout.Length > 0)
retout.AppendLine();
retout.Append(outargs.Data);
}
};
process.ErrorDataReceived += (sender, errargs) =>
{
if (!string.IsNullOrEmpty(errargs.Data))
{
if (reterror.Length > 0)
reterror.AppendLine();
reterror.Append(errargs.Data);
}
};
if (reterror.Length > 0)
reterror.AppendLine();
reterror.Append(errargs.Data);
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
process.CancelOutputRead();
process.CancelErrorRead();
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
process.CancelOutputRead();
process.CancelErrorRead();
error = process.ExitCode;
errorMessage = reterror.ToString();
return retout.ToString();
}
error = process.ExitCode;
errorMessage = reterror.ToString();
return retout.ToString();
}
}
}

25
src/Generator/Utils/TextGenerator.cs

@ -21,9 +21,11 @@ namespace CppSharp @@ -21,9 +21,11 @@ namespace CppSharp
public class TextGenerator : ITextGenerator
{
public static string NewLineChar;
public const uint DefaultIndentation = 4;
public StringBuilder StringBuilder = new StringBuilder();
public StringBuilder StringBuilder = new();
public bool IsStartOfLine { get; set; }
public bool NeedsNewLine { get; set; }
public uint CurrentIndentation { get; set; }
@ -45,6 +47,19 @@ namespace CppSharp @@ -45,6 +47,19 @@ namespace CppSharp
return new TextGenerator(this);
}
public static void SetLineEndingType(NewLineType newLineType)
{
NewLineChar = newLineType switch
{
NewLineType.Host => Environment.NewLine,
NewLineType.CR => "\r",
NewLineType.LF => "\n",
NewLineType.CRLF => "\r\n",
NewLineType.Auto => throw new ArgumentException("Don't use Auto here.", nameof(newLineType)),
_ => throw new ArgumentOutOfRangeException(nameof(newLineType))
};
}
public void Write(string msg, params object[] args)
{
if (string.IsNullOrEmpty(msg))
@ -54,11 +69,9 @@ namespace CppSharp @@ -54,11 +69,9 @@ namespace CppSharp
msg = string.Format(msg, args);
if (IsStartOfLine && !string.IsNullOrWhiteSpace(msg))
StringBuilder.Append(new string(' ',
(int)(CurrentIndentation * DefaultIndentation)));
StringBuilder.Append(new string(' ', (int)(CurrentIndentation * DefaultIndentation)));
if (msg.Length > 0)
IsStartOfLine = msg.EndsWith(Environment.NewLine);
IsStartOfLine = msg.Length > 0 && msg.EndsWith(NewLineChar);
StringBuilder.Append(msg);
}
@ -90,7 +103,7 @@ namespace CppSharp @@ -90,7 +103,7 @@ namespace CppSharp
public void NewLine()
{
StringBuilder.AppendLine(string.Empty);
StringBuilder.Append(NewLineChar);
IsStartOfLine = true;
}

58
src/Generator/Utils/Utils.cs

@ -4,6 +4,7 @@ using System.Linq; @@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using CppSharp.Utils;
namespace CppSharp
{
@ -83,7 +84,7 @@ namespace CppSharp @@ -83,7 +84,7 @@ namespace CppSharp
{
while (stringBuilder.Length > 0 && stringBuilder[0] == '_')
stringBuilder.Remove(0, 1);
while (stringBuilder.Length > 0 && stringBuilder[stringBuilder.Length - 1] == '_')
while (stringBuilder.Length > 0 && stringBuilder[^1] == '_')
stringBuilder.Remove(stringBuilder.Length - 1, 1);
}
}
@ -130,4 +131,59 @@ namespace CppSharp @@ -130,4 +131,59 @@ namespace CppSharp
return uri1.MakeRelativeUri(uri2).ToString();
}
}
public static class GeneratorHelpers
{
public static NewLineType? GetNewLineTypeFromGitConfig(string outputDir)
{
try
{
if (!bool.TryParse(
ProcessHelper.RunFrom(outputDir,
"git", "rev-parse --is-inside-work-tree",
out _, out _
),
out bool isInsideWorkTree))
{
return null;
}
if (!isInsideWorkTree)
return null;
// Check git config core.eol setting
var eolConfig = ProcessHelper.RunFrom(outputDir,
"git", "config --get core.eol",
out _, out _)
.Trim().ToLowerInvariant();
switch (eolConfig)
{
case "lf":
return NewLineType.LF;
case "crlf":
return NewLineType.CRLF;
}
// Otherwise check git config core.autocrlf setting
var autoCrLf = ProcessHelper.RunFrom(outputDir,
"git", "config --get core.autocrlf",
out _, out _)
.Trim().ToLowerInvariant();
return autoCrLf switch
{
"input" => NewLineType.LF,
"true" => NewLineType.CRLF,
"false" => NewLineType.Host,
_ => null
};
}
catch (Exception)
{
return null;
}
}
}
}

Loading…
Cancel
Save