203 lines
7.3 KiB
C#
203 lines
7.3 KiB
C#
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
#if DEBUG
|
|
|
|
using System;
|
|
using System.CodeDom;
|
|
using System.CodeDom.Compiler;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
|
using Microsoft.AspNet.Razor.Text;
|
|
|
|
namespace Microsoft.AspNet.Razor
|
|
{
|
|
internal static class RazorDebugHelpers
|
|
{
|
|
private static bool _outputDebuggingEnabled = IsDebuggingEnabled();
|
|
|
|
private static readonly Dictionary<char, string> _printableEscapeChars = new Dictionary<char, string>
|
|
{
|
|
{ '\0', "\\0" },
|
|
{ '\\', "\\\\" },
|
|
{ '\'', "'" },
|
|
{ '\"', "\\\"" },
|
|
{ '\a', "\\a" },
|
|
{ '\b', "\\b" },
|
|
{ '\f', "\\f" },
|
|
{ '\n', "\\n" },
|
|
{ '\r', "\\r" },
|
|
{ '\t', "\\t" },
|
|
{ '\v', "\\v" },
|
|
};
|
|
|
|
internal static bool OutputDebuggingEnabled
|
|
{
|
|
get { return _outputDebuggingEnabled; }
|
|
}
|
|
#if NET45
|
|
// No CodeDOM in CoreCLR
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2141:TransparentMethodsMustNotSatisfyLinkDemandsFxCopRule", Justification = "This is debug only")]
|
|
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "This is debug only")]
|
|
[SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Justification = "This is debug only")]
|
|
internal static void WriteGeneratedCode(string sourceFile, CodeCompileUnit codeCompileUnit)
|
|
{
|
|
if (!OutputDebuggingEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
RunTask(() =>
|
|
{
|
|
string extension = Path.GetExtension(sourceFile);
|
|
RazorCodeLanguage language = RazorCodeLanguage.GetLanguageByExtension(extension);
|
|
CodeDomProvider provider = CodeDomProvider.CreateProvider(language.LanguageName);
|
|
|
|
using (var writer = new StringWriter())
|
|
{
|
|
// Trim the html part of cshtml or vbhtml
|
|
string outputExtension = extension.Substring(0, 3);
|
|
string outputFileName = Normalize(sourceFile) + "_generated" + outputExtension;
|
|
string outputPath = Path.Combine(Path.GetDirectoryName(sourceFile), outputFileName);
|
|
|
|
// REVIEW: Do these options need to be tweaked?
|
|
provider.GenerateCodeFromCompileUnit(codeCompileUnit, writer, new CodeGeneratorOptions());
|
|
File.WriteAllText(outputPath, writer.ToString());
|
|
}
|
|
});
|
|
}
|
|
#endif
|
|
internal static void WriteDebugTree(string sourceFile, Block document, PartialParseResult result, TextChange change, RazorEditorParser parser, bool treeStructureChanged)
|
|
{
|
|
if (!OutputDebuggingEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
RunTask(() =>
|
|
{
|
|
string outputFileName = Normalize(sourceFile) + "_tree";
|
|
string outputPath = Path.Combine(Path.GetDirectoryName(sourceFile), outputFileName);
|
|
|
|
var treeBuilder = new StringBuilder();
|
|
WriteTree(document, treeBuilder);
|
|
treeBuilder.AppendLine();
|
|
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Last Change: {0}", change);
|
|
treeBuilder.AppendLine();
|
|
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Normalized To: {0}", change.Normalize());
|
|
treeBuilder.AppendLine();
|
|
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Partial Parse Result: {0}", result);
|
|
treeBuilder.AppendLine();
|
|
if (result.HasFlag(PartialParseResult.Rejected))
|
|
{
|
|
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Tree Structure Changed: {0}", treeStructureChanged);
|
|
treeBuilder.AppendLine();
|
|
}
|
|
if (result.HasFlag(PartialParseResult.AutoCompleteBlock))
|
|
{
|
|
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Auto Complete Insert String: \"{0}\"", parser.GetAutoCompleteString());
|
|
treeBuilder.AppendLine();
|
|
}
|
|
File.WriteAllText(outputPath, treeBuilder.ToString());
|
|
});
|
|
}
|
|
|
|
private static void WriteTree(SyntaxTreeNode node, StringBuilder treeBuilder, int depth = 0)
|
|
{
|
|
if (node == null)
|
|
{
|
|
return;
|
|
}
|
|
if (depth > 1)
|
|
{
|
|
WriteIndent(treeBuilder, depth);
|
|
}
|
|
|
|
if (depth > 0)
|
|
{
|
|
treeBuilder.Append("|-- ");
|
|
}
|
|
|
|
treeBuilder.AppendLine(ConvertEscapseSequences(node.ToString()));
|
|
if (node.IsBlock)
|
|
{
|
|
foreach (SyntaxTreeNode child in ((Block)node).Children)
|
|
{
|
|
WriteTree(child, treeBuilder, depth + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This is debug only")]
|
|
[SuppressMessage("Microsoft.Web.FxCop", "MW1202:DoNotUseProblematicTaskTypes", Justification = "This rule is not applicable to this assembly.")]
|
|
[SuppressMessage("Microsoft.Web.FxCop", "MW1201:DoNotCallProblematicMethodsOnTask", Justification = "This rule is not applicable to this assembly.")]
|
|
private static void RunTask(Action action)
|
|
{
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
try
|
|
{
|
|
action();
|
|
}
|
|
catch
|
|
{
|
|
// Catch all errors since this is just a debug helper
|
|
}
|
|
});
|
|
}
|
|
|
|
private static void WriteIndent(StringBuilder sb, int depth)
|
|
{
|
|
for (int i = 0; i < (depth - 1) * 4; ++i)
|
|
{
|
|
if (i % 4 == 0)
|
|
{
|
|
sb.Append("|");
|
|
}
|
|
else
|
|
{
|
|
sb.Append(" ");
|
|
}
|
|
}
|
|
}
|
|
|
|
private static string Normalize(string path)
|
|
{
|
|
return Path.GetFileName(path).Replace('.', '_');
|
|
}
|
|
|
|
private static string ConvertEscapseSequences(string value)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
foreach (var ch in value)
|
|
{
|
|
sb.Append(GetCharValue(ch));
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static string GetCharValue(char ch)
|
|
{
|
|
string value;
|
|
if (_printableEscapeChars.TryGetValue(ch, out value))
|
|
{
|
|
return value;
|
|
}
|
|
return ch.ToString();
|
|
}
|
|
|
|
private static bool IsDebuggingEnabled()
|
|
{
|
|
bool enabled;
|
|
return Boolean.TryParse(Environment.GetEnvironmentVariable("RAZOR_DEBUG"), out enabled) && enabled;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|