Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
Fixed some trivia (non-code content like #region/#endregion) not bein…
Browse files Browse the repository at this point in the history
…g added during deployment.
  • Loading branch information
Malware committed Aug 19, 2017
1 parent 9ed0de0 commit 863e328
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 131 deletions.
16 changes: 11 additions & 5 deletions Source/MDK/Build/BuildModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,18 @@ Document CreateProgramDocument(Project project, ProjectContent content)
{
var usings = string.Join(Environment.NewLine, content.UsingDirectives.Select(d => d.ToString()));
var solution = project.Solution;
var programCode = string.Join("", content.Parts.OfType<ProgramScriptPart>().OrderBy(part => part, PartComparer).SelectMany(p => p.ContentNodes()).Select(n => n.ToFullString()));
var programContent = $"public class Program: MyGridProgram {{{Environment.NewLine}{programCode}{Environment.NewLine}}}";

var extensionContent = string.Join("", content.Parts.OfType<ExtensionScriptPart>().OrderBy(part => part, PartComparer).SelectMany(p => p.ContentNodes()).Select(n => n.ToFullString()));

var finalContent = $"{usings}{Environment.NewLine}{programContent}{Environment.NewLine}{extensionContent}";
var buffer = new StringBuilder();
buffer.Append("public class Program: MyGridProgram {");
buffer.Append(string.Join("", content.Parts.OfType<ProgramScriptPart>().OrderBy(part => part, PartComparer).Select(p => p.GenerateContent())));
buffer.Append("}");
var programContent = buffer.ToString();

buffer.Clear();
buffer.Append(string.Join("", content.Parts.OfType<ExtensionScriptPart>().OrderBy(part => part, PartComparer).Select(p => p.GenerateContent())));
var extensionContent = buffer.ToString();

var finalContent = $"{usings}\n{programContent}\n{extensionContent}";

var compilationProject = solution.AddProject("__ScriptCompilationProject", "__ScriptCompilationProject.dll", LanguageNames.CSharp)
.WithCompilationOptions(project.CompilationOptions)
Expand Down
5 changes: 2 additions & 3 deletions Source/MDK/Build/ExtensionScriptPart.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Collections.Generic;
using Microsoft.CodeAnalysis;

namespace MDK.Build
Expand All @@ -17,9 +16,9 @@ public ExtensionScriptPart(Document document, SyntaxNode partRoot) : base(docume
{ }

/// <inheritdoc />
public override IEnumerable<SyntaxNode> ContentNodes()
public override string GenerateContent()
{
yield return PartRoot;
return PartRoot.ToFullString();
}
}
}
28 changes: 16 additions & 12 deletions Source/MDK/Build/Minifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,18 +235,22 @@ public TriviaTrimmer() : base(true)

public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
{
switch (trivia.Kind())
{
case SyntaxKind.SingleLineCommentTrivia:
case SyntaxKind.SingleLineDocumentationCommentTrivia:
case SyntaxKind.MultiLineCommentTrivia:
case SyntaxKind.MultiLineDocumentationCommentTrivia:
case SyntaxKind.WhitespaceTrivia:
case SyntaxKind.EndOfLineTrivia:
return default(SyntaxTrivia);
default:
return base.VisitTrivia(trivia);
}
return default(SyntaxTrivia);
//switch (trivia.Kind())
//{
// case SyntaxKind.direc
// case SyntaxKind.RegionDirectiveTrivia:
// case SyntaxKind.EndRegionDirectiveTrivia:
// case SyntaxKind.SingleLineCommentTrivia:
// case SyntaxKind.SingleLineDocumentationCommentTrivia:
// case SyntaxKind.MultiLineCommentTrivia:
// case SyntaxKind.MultiLineDocumentationCommentTrivia:
// case SyntaxKind.WhitespaceTrivia:
// case SyntaxKind.EndOfLineTrivia:
// return default(SyntaxTrivia);
// default:
// return base.VisitTrivia(trivia);
//}
}
}

Expand Down
30 changes: 27 additions & 3 deletions Source/MDK/Build/ProgramScriptPart.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace MDK.Build
{
Expand All @@ -14,12 +18,22 @@ public class ProgramScriptPart : ScriptPart
/// </summary>
/// <param name="document"></param>
/// <param name="partRoot"></param>
public ProgramScriptPart(Document document, SyntaxNode partRoot) : base(document, partRoot)
public ProgramScriptPart(Document document, ClassDeclarationSyntax partRoot) : base(document, partRoot)
{ }

/// <inheritdoc />
public override IEnumerable<SyntaxNode> ContentNodes()
public override string GenerateContent()
{
var classDeclaration = (ClassDeclarationSyntax)PartRoot;
var buffer = new StringBuilder();
// Write opening brace trailing trivia
if (classDeclaration.OpenBraceToken.HasTrailingTrivia)
{
foreach (var trivia in classDeclaration.OpenBraceToken.TrailingTrivia)
buffer.Append(trivia.ToFullString());
}

// Write general content
foreach (var node in PartRoot.ChildNodes())
{
switch (node.Kind())
Expand All @@ -39,10 +53,20 @@ public override IEnumerable<SyntaxNode> ContentNodes()
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.EventDeclaration:
case SyntaxKind.IndexerDeclaration:
yield return node;
buffer.Append(node.ToFullString());
break;
}
}

// Write closing brace opening trivia
// Write opening brace trailing trivia
if (classDeclaration.CloseBraceToken.HasLeadingTrivia)
{
foreach (var trivia in classDeclaration.CloseBraceToken.LeadingTrivia)
buffer.Append(trivia.ToFullString());
}

return buffer.ToString();
}
}
}
170 changes: 64 additions & 106 deletions Source/MDK/Build/ScriptGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace MDK.Build
{
Expand All @@ -24,37 +23,73 @@ public class ScriptGenerator
/// <returns></returns>
public async Task<string> Generate(Document document)
{
var root = await document.GetSyntaxRootAsync().ConfigureAwait(false);
var trimmer = new SyntaxTrimmer();
trimmer.Visit(root);

string script;
var programPartLines = string.Join("\n\n", trimmer.ProgramNodes.Select(GenerateFinalCode)).Split(NewLines, StringSplitOptions.None);
var programPart = DeIndent(programPartLines);
var extensionPartLines = string.Join(" ", trimmer.ExtensionNodes.Select(GenerateFinalCode)).Split(NewLines, StringSplitOptions.None);
var extensionPart = DeIndent(extensionPartLines);
if (extensionPart.EndsWith("}"))
script = $"{programPart}\n\n}}\n\n{extensionPart.Substring(0, extensionPart.Length - 1)}";
else
script = programPart;
var analyzer = new DocumentAnalyzer();
var result = await analyzer.Analyze(document);
var buffer = new StringBuilder();

var programContent =
DeIndent(
string.Join("\n", result.Parts.OfType<ProgramScriptPart>().Select(p => p.GenerateContent()))
.Split(NewLines, StringSplitOptions.None)
).Trim();
buffer.Append(programContent);
buffer.Append("\n");

var extensionContent =
DeIndent(
string.Join("\n", result.Parts.OfType<ExtensionScriptPart>().Select(p => p.GenerateContent()))
.Split(NewLines, StringSplitOptions.None)
).Trim();

if (!string.IsNullOrWhiteSpace(extensionContent))
{
// Extension classes are made possible by forcefully ending Space Engineer's wrapping Program class
// and removing the final ending brace of the last extension class to let Space Engineers close it
// for itself.

// Close off the Program class
buffer.Append("}\n");
buffer.Append(extensionContent);
// Remove the ending brace of the last extension class
var index = FindEndBrace(buffer);
if (index >= 0)
buffer.Length = index;
}

return script;
return buffer.ToString();
}

string GenerateFinalCode(SyntaxNode n)
int FindEndBrace(StringBuilder buffer)
{
return n.ToFullString().Trim();
for (var i = buffer.Length - 1; i >= 0; i--)
{
var ch = buffer[i];
if (char.IsWhiteSpace(ch) || ch != '}')
continue;
return i;
}
return -1;
}

string DeIndent(string[] programPartLines)
{
var lines = programPartLines.ToList();
// Remove trailing empty lines
while (lines.Count > 0 && string.IsNullOrWhiteSpace(lines[lines.Count - 1]))
lines.RemoveAt(lines.Count - 1);

// Remove leading empty lines
while (lines.Count > 0 && string.IsNullOrWhiteSpace(lines[0]))
lines.RemoveAt(0);

// Detect indentation
var indent = int.MaxValue;
for (var i = 0; i < programPartLines.Length; i++)
for (var i = 0; i < lines.Count; i++)
{
var line = programPartLines[i];
var line = lines[i];
if (string.IsNullOrWhiteSpace(line))
{
programPartLines[i] = "";
lines[i] = "";
continue;
}

Expand All @@ -68,11 +103,13 @@ string DeIndent(string[] programPartLines)
}
if (indent == int.MaxValue)
{
return string.Join("\r\n", programPartLines);
return string.Join("\r\n", lines);
}
for (var i = 0; i < programPartLines.Length; i++)

// Remove indentation
for (var i = 0; i < lines.Count; i++)
{
var line = programPartLines[i];
var line = lines[i];
if (line.Length == 0)
continue;
var tabs = 0;
Expand All @@ -89,101 +126,22 @@ string DeIndent(string[] programPartLines)
}
else
{
programPartLines[i] = line.TrimStart();
lines[i] = line.TrimStart();
break;
}
if (tabs >= indent)
{
programPartLines[i] = line.Substring(j + 1);
lines[i] = line.Substring(j + 1);
break;
}
}
}
return string.Join("\r\n", programPartLines);
return string.Join("\r\n", lines);
}

int TabLengthOfValue(string value)
{
return value.Select(c => c == '\t' ? 4 : 1).Sum();
}

class SyntaxTrimmer : CSharpSyntaxWalker
{
List<SyntaxNode> _programNodes = new List<SyntaxNode>();
List<SyntaxNode> _extensionNodes = new List<SyntaxNode>();
List<SyntaxNode> _rootNodes;

public SyntaxTrimmer()
{
_rootNodes = _extensionNodes;
}

public IEnumerable<SyntaxNode> ProgramNodes => _programNodes;
public IEnumerable<SyntaxNode> ExtensionNodes => _extensionNodes;

public override void VisitClassDeclaration(ClassDeclarationSyntax node)
{
if (node.GetFullName(DeclarationFullNameFlags.WithoutNamespaceName) == "Program")
{
_rootNodes = _programNodes;
try
{
base.VisitClassDeclaration(node);
}
finally
{
_rootNodes = _extensionNodes;
}
return;
}
_rootNodes.Add(node);
}

public override void VisitStructDeclaration(StructDeclarationSyntax node)
{
_rootNodes.Add(node);
}


public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node)
{
_rootNodes.Add(node);
}

public override void VisitEventFieldDeclaration(EventFieldDeclarationSyntax node)
{
_rootNodes.Add(node);
}

public override void VisitEventDeclaration(EventDeclarationSyntax node)
{
_rootNodes.Add(node);
}

public override void VisitFieldDeclaration(FieldDeclarationSyntax node)
{
_rootNodes.Add(node);
}

public override void VisitDelegateDeclaration(DelegateDeclarationSyntax node)
{
_rootNodes.Add(node);
}

public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
{
_rootNodes.Add(node);
}

public override void VisitEnumDeclaration(EnumDeclarationSyntax node)
{
_rootNodes.Add(node);
}

public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
{
_rootNodes.Add(node);
}
}
}
}
4 changes: 2 additions & 2 deletions Source/MDK/Build/ScriptPart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ protected ScriptPart(Document document, SyntaxNode partRoot)
public SyntaxNode PartRoot { get; }

/// <summary>
/// Syntax nodes that makes up this part
/// Generates the script content that makes up this part
/// </summary>
/// <returns></returns>
public abstract IEnumerable<SyntaxNode> ContentNodes();
public abstract string GenerateContent();
}
}

0 comments on commit 863e328

Please sign in to comment.