You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
11 KiB
Plaintext
342 lines
11 KiB
Plaintext
<#@ template hostspecific="true" #>
|
|
<#@ assembly name="EnvDTE" #>
|
|
<#@ assembly name="System.Core" #>
|
|
<#@ assembly name="System.Windows.Forms" #>
|
|
<#@ import namespace="System.Collections" #>
|
|
<#@ import namespace="System.Collections.Generic" #>
|
|
<#@ import namespace="System.ComponentModel.Design" #>
|
|
<#@ import namespace="System.IO" #>
|
|
<#@ import namespace="System.Linq" #>
|
|
<#@ import namespace="System.Resources" #>
|
|
<#@ import namespace="System.Text.RegularExpressions" #>
|
|
<#@ import namespace="EnvDTE" #>
|
|
<#
|
|
var model = LoadResources();
|
|
#>
|
|
// <auto-generated />
|
|
|
|
using System;
|
|
using System.Reflection;
|
|
using System.Resources;
|
|
<#
|
|
if (!model.NoDiagnostics)
|
|
{
|
|
#>
|
|
using System.Threading;
|
|
using JetBrains.Annotations;
|
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
using Microsoft.Extensions.Logging;
|
|
<#
|
|
}
|
|
else
|
|
{
|
|
#>
|
|
using JetBrains.Annotations;
|
|
<#
|
|
}
|
|
#>
|
|
|
|
namespace <#= model.Namespace #>
|
|
{
|
|
<#
|
|
if (model.Namespace.EndsWith("Internal")
|
|
|| model.AccessModifier == "internal")
|
|
{
|
|
#>
|
|
/// <summary>
|
|
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
|
|
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
|
|
/// any release. You should only use it directly in your code with extreme caution and knowing that
|
|
/// doing so can result in application failures when updating to a new Entity Framework Core release.
|
|
/// </summary>
|
|
<#
|
|
}
|
|
else
|
|
{
|
|
#>
|
|
/// <summary>
|
|
/// <para>
|
|
/// String resources used in EF exceptions, etc.
|
|
/// </para>
|
|
/// <para>
|
|
/// These strings are exposed publicly for use by database providers and extensions.
|
|
/// It is unusual for application code to need these strings.
|
|
/// </para>
|
|
/// </summary>
|
|
<#
|
|
}
|
|
#>
|
|
<#= model.AccessModifier #> static class <#= model.Class #>
|
|
{
|
|
private static readonly ResourceManager _resourceManager
|
|
= new ResourceManager("<#= model.ResourceName #>", typeof(<#= model.Class #>).GetTypeInfo().Assembly);
|
|
<#
|
|
foreach (var resource in model.Resources)
|
|
{
|
|
if (!resource.ForLogging)
|
|
{
|
|
#>
|
|
|
|
/// <summary>
|
|
<#
|
|
foreach (var line in Lines(resource.Value))
|
|
{
|
|
#>
|
|
/// <#= Xml(line) #>
|
|
<#
|
|
}
|
|
#>
|
|
/// </summary>
|
|
<#
|
|
if (resource.Parameters.Any())
|
|
{
|
|
#>
|
|
public static string <#= resource.Name #>(<#= List("object ", resource.Parameters) #>)
|
|
=> string.Format(
|
|
GetString("<#= resource.Name #>", <#= List("nameof(", resource.Parameters, ")") #>),
|
|
<#= List(resource.Parameters) #>);
|
|
<#
|
|
}
|
|
else
|
|
{
|
|
#>
|
|
public static string <#= resource.Name #>
|
|
=> GetString("<#= resource.Name #>");
|
|
<#
|
|
}
|
|
}
|
|
}
|
|
#>
|
|
|
|
private static string GetString(string name, params string[] formatterNames)
|
|
{
|
|
var value = _resourceManager.GetString(name);
|
|
for (var i = 0; i < formatterNames.Length; i++)
|
|
{
|
|
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
|
|
<#
|
|
if (!model.NoDiagnostics)
|
|
{
|
|
#>
|
|
namespace <#= model.Namespace.EndsWith(".Internal") ? model.Namespace : (model.Namespace + ".Internal") #>
|
|
{
|
|
/// <summary>
|
|
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
|
|
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
|
|
/// any release. You should only use it directly in your code with extreme caution and knowing that
|
|
/// doing so can result in application failures when updating to a new Entity Framework Core release.
|
|
/// </summary>
|
|
<#= model.AccessModifier #> static class <#= model.DiagnosticsClass #>
|
|
{
|
|
private static readonly ResourceManager _resourceManager
|
|
= new ResourceManager("<#= model.ResourceName #>", typeof(<#= model.DiagnosticsClass #>).GetTypeInfo().Assembly);
|
|
<#
|
|
foreach (var resource in model.Resources)
|
|
{
|
|
if (resource.ForLogging)
|
|
{
|
|
#>
|
|
|
|
/// <summary>
|
|
<#
|
|
foreach (var line in Lines(resource.Value))
|
|
{
|
|
#>
|
|
/// <#= Xml(line) #>
|
|
<#
|
|
}
|
|
#>
|
|
/// </summary>
|
|
<#
|
|
if (resource.Types.Count() > 6)
|
|
{
|
|
#>
|
|
public static FallbackEventDefinition <#= resource.Name #>(IDiagnosticsLogger logger)
|
|
{
|
|
var definition = ((<#= model.LoggingDefinitionsClass #>)logger.Definitions).<#= resource.Name #>;
|
|
if (definition == null)
|
|
{
|
|
definition = LazyInitializer.EnsureInitialized<EventDefinitionBase>(
|
|
ref ((<#= model.LoggingDefinitionsClass #>)logger.Definitions).<#= resource.Name #>,
|
|
() => new FallbackEventDefinition(
|
|
logger.Options,
|
|
<#= resource.EventId #>,
|
|
LogLevel.<#= resource.Level #>,
|
|
"<#= resource.EventId #>",
|
|
_resourceManager.GetString("<#= resource.Name #>")));
|
|
}
|
|
|
|
return (FallbackEventDefinition)definition;
|
|
}
|
|
<#
|
|
}
|
|
else
|
|
{
|
|
var genericTypes = resource.Types.Any() ? ("<" + List(resource.Types) + ">") : "";
|
|
if (resource.Obsolete)
|
|
{
|
|
#>
|
|
[Obsolete]
|
|
<#
|
|
}
|
|
#>
|
|
public static EventDefinition<#= genericTypes #> <#= resource.Name #>(IDiagnosticsLogger logger)
|
|
{
|
|
var definition = ((<#= model.LoggingDefinitionsClass #>)logger.Definitions).<#= resource.Name #>;
|
|
if (definition == null)
|
|
{
|
|
definition = LazyInitializer.EnsureInitialized<EventDefinitionBase>(
|
|
ref ((<#= model.LoggingDefinitionsClass #>)logger.Definitions).<#= resource.Name #>,
|
|
() => new EventDefinition<#= genericTypes #>(
|
|
logger.Options,
|
|
<#= resource.EventId #>,
|
|
LogLevel.<#= resource.Level #>,
|
|
"<#= resource.EventId #>",
|
|
level => LoggerMessage.Define<#= genericTypes #>(
|
|
level,
|
|
<#= resource.EventId #>,
|
|
_resourceManager.GetString("<#= resource.Name #>"))));
|
|
}
|
|
|
|
return (EventDefinition<#= genericTypes #>)definition;
|
|
}
|
|
<#
|
|
}
|
|
}
|
|
}
|
|
#>
|
|
}
|
|
}
|
|
<#
|
|
}
|
|
#>
|
|
<#+
|
|
ResourceFile LoadResources()
|
|
{
|
|
var result = new ResourceFile();
|
|
|
|
if (Session.ContainsKey("AccessModifier"))
|
|
{
|
|
result.AccessModifier = (string)Session["AccessModifier"];
|
|
};
|
|
|
|
if (Session.ContainsKey("LoggingDefinitionsClass"))
|
|
{
|
|
result.LoggingDefinitionsClass = (string)Session["LoggingDefinitionsClass"];
|
|
};
|
|
|
|
var services = (IServiceProvider)Host;
|
|
var dte = (DTE)services.GetService(typeof(DTE));
|
|
|
|
if (!Session.TryGetValue("NoDiagnostics", out var noDiagnostics))
|
|
{
|
|
noDiagnostics = false;
|
|
}
|
|
|
|
result.NoDiagnostics = (bool)noDiagnostics;
|
|
|
|
var resourceFile = (string)Session["ResourceFile"];
|
|
if (!Path.IsPathRooted(resourceFile))
|
|
{
|
|
resourceFile = Host.ResolvePath(resourceFile);
|
|
}
|
|
|
|
var resourceProjectItem = dte.Solution.FindProjectItem(resourceFile);
|
|
var templateProjectItem = dte.Solution.FindProjectItem(Host.TemplateFile);
|
|
var project = templateProjectItem.ContainingProject;
|
|
var rootNamespace = (string)project.Properties.Item("RootNamespace").Value;
|
|
var resourceDir = Path.GetDirectoryName(resourceFile);
|
|
var projectDir = (string)project.Properties.Item("FullPath").Value;
|
|
var resourceNamespace = rootNamespace + "." + resourceDir.Substring(projectDir.Length)
|
|
.Replace(Path.DirectorySeparatorChar, '.');
|
|
|
|
result.Namespace = (string)resourceProjectItem.Properties.Item("CustomToolNamespace")?.Value;
|
|
if (string.IsNullOrEmpty(result.Namespace))
|
|
{
|
|
result.Namespace = resourceNamespace;
|
|
}
|
|
|
|
result.Class = Path.GetFileNameWithoutExtension(resourceFile);
|
|
|
|
result.DiagnosticsClass = result.Class.Replace("Strings", "Resources");
|
|
|
|
result.ResourceName = resourceNamespace + "." + result.Class;
|
|
|
|
using (var reader = new ResXResourceReader(resourceFile))
|
|
{
|
|
reader.UseResXDataNodes = true;
|
|
|
|
result.Resources = Enumerable.ToList(
|
|
from DictionaryEntry r in reader
|
|
select new Resource((ResXDataNode)r.Value));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
IEnumerable<string> Lines(string value)
|
|
=> value.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
|
|
|
|
string Xml(string value)
|
|
=> value.Replace("<", "<").Replace(">", ">");
|
|
|
|
string List(IEnumerable<string> items)
|
|
=> List(null, items);
|
|
|
|
string List(string prefix, IEnumerable<string> items, string suffix = null)
|
|
=> string.Join(", ", items.Select(i => prefix + i + suffix));
|
|
|
|
class ResourceFile
|
|
{
|
|
public string Namespace { get; set; }
|
|
public string AccessModifier { get; set; } = "public";
|
|
public string Class { get; set; }
|
|
public string DiagnosticsClass { get; set; }
|
|
public string ResourceName { get; set; }
|
|
public IEnumerable<Resource> Resources { get; set; }
|
|
public bool NoDiagnostics { get; set; }
|
|
public string LoggingDefinitionsClass { get; set; }
|
|
}
|
|
|
|
class Resource
|
|
{
|
|
public Resource(ResXDataNode node)
|
|
{
|
|
Name = node.Name;
|
|
Value = (string)node.GetValue((ITypeResolutionService)null);
|
|
Parameters = Regex.Matches(Value, @"\{(\w+)\}")
|
|
.Cast<Match>()
|
|
.Select(m => m.Groups[1].Value)
|
|
.Distinct()
|
|
.ToList();
|
|
|
|
var eventInfo = node.Comment.Split(' ');
|
|
var argumentsRead = 0;
|
|
if (eventInfo.FirstOrDefault() == "Obsolete")
|
|
{
|
|
Obsolete = true;
|
|
argumentsRead++;
|
|
}
|
|
|
|
Level = eventInfo.Skip(argumentsRead++).FirstOrDefault() ?? "BadLevel";
|
|
EventId = eventInfo.Skip(argumentsRead++).FirstOrDefault() ?? "BadEventId";
|
|
Types = eventInfo.Skip(argumentsRead++).ToList();
|
|
}
|
|
|
|
public string Name { get; }
|
|
public string Value { get; }
|
|
public string EventId { get; }
|
|
public string Level { get; }
|
|
public bool Obsolete { get; }
|
|
public bool ForLogging => Name.StartsWith("Log");
|
|
public IEnumerable<string> Parameters { get; }
|
|
public IEnumerable<string> Types { get; }
|
|
}
|
|
#> |