first commit
This commit is contained in:
@@ -0,0 +1,456 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ExportCommands.Properties;
|
||||
|
||||
// ReSharper disable LocalizableElement
|
||||
|
||||
namespace ExportCommands
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
private static readonly string[] _locales = { "en-US", "it-IT", "pl-PL", "ko-KR" };
|
||||
|
||||
private static void Main( string[] args )
|
||||
{
|
||||
if ( args.Length == 0 )
|
||||
{
|
||||
Console.WriteLine( "No file specified..." );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !File.Exists( args[0] ) )
|
||||
{
|
||||
throw new FileNotFoundException( "File specified does not exist.", args[0] );
|
||||
}
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
|
||||
|
||||
string originalDirectory = Environment.CurrentDirectory;
|
||||
|
||||
Environment.CurrentDirectory = Path.GetDirectoryName( args[0] ) ?? throw new InvalidOperationException();
|
||||
|
||||
string docPath = Path.Combine( originalDirectory, "Docs" );
|
||||
|
||||
if ( !Directory.Exists( docPath ) )
|
||||
{
|
||||
Directory.CreateDirectory( docPath );
|
||||
}
|
||||
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
foreach ( string locale in _locales )
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo( locale );
|
||||
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo( locale );
|
||||
|
||||
Assembly assembly;
|
||||
|
||||
try
|
||||
{
|
||||
assembly = Assembly.LoadFile( args[0] );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
Console.WriteLine( $"Failed to load assembly: {e}" );
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine( "Generating Macro documentation..." );
|
||||
Console.WriteLine( $"Loading {args[0]}" );
|
||||
|
||||
IEnumerable<Type> types = assembly.GetTypes().Where( t =>
|
||||
t.Namespace != null && t.Namespace.StartsWith( "ClassicAssist.Data.Macros.Commands" ) );
|
||||
|
||||
Type cda = assembly.GetType( "ClassicAssist.Data.Macros.CommandsDisplayAttribute" );
|
||||
Type cdsaa = assembly.GetType( "ClassicAssist.Data.Macros.CommandsDisplayStringSeeAlsoAttribute" );
|
||||
|
||||
List<Commands> commands = new List<Commands>();
|
||||
List<Type> seeAlsoTypes = new List<Type>();
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
foreach ( Type type in types )
|
||||
{
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
foreach ( MemberInfo memberInfo in type.GetMembers( BindingFlags.Public | BindingFlags.Static ) )
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
|
||||
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
|
||||
|
||||
Attribute attrCDLN = memberInfo.GetCustomAttribute( cda );
|
||||
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo( locale );
|
||||
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo( locale );
|
||||
|
||||
Attribute attrCD = memberInfo.GetCustomAttribute( cda );
|
||||
Attribute attrCDSA = memberInfo.GetCustomAttribute( cdsaa );
|
||||
|
||||
if ( attrCDSA != null )
|
||||
{
|
||||
}
|
||||
|
||||
if ( attrCD == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
List<Parameter> param = new List<Parameter>();
|
||||
|
||||
dynamic attrParams = ( (dynamic) attrCD ).Parameters;
|
||||
dynamic attr2Params = null;
|
||||
|
||||
if ( attrCDSA != null )
|
||||
{
|
||||
attr2Params = ( (dynamic) attrCDSA ).Enums;
|
||||
}
|
||||
|
||||
if ( memberInfo.MemberType == MemberTypes.Method && attrParams != null )
|
||||
{
|
||||
MethodInfo methodInfo = memberInfo as MethodInfo;
|
||||
ParameterInfo[] parameters = methodInfo?.GetParameters();
|
||||
|
||||
int i = 0;
|
||||
|
||||
if ( parameters != null )
|
||||
{
|
||||
foreach ( ParameterInfo parameterInfo in parameters )
|
||||
{
|
||||
Parameter parameter = new Parameter();
|
||||
|
||||
object defaultValue = parameterInfo.RawDefaultValue;
|
||||
|
||||
if ( i + 1 > attrParams.Length )
|
||||
{
|
||||
parameter.Name = parameterInfo.Name.ToLower();
|
||||
parameter.Optional =
|
||||
defaultValue == null || defaultValue.GetType() != typeof( DBNull );
|
||||
parameter.Description = Resources.ResourceManager.GetString(
|
||||
"PARAMETER_DESCRIPTION_UNKNOWN" );
|
||||
param.Add( parameter );
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dynamic attrParam = attrParams[i];
|
||||
|
||||
if ( attrParam == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
parameter.Name = parameterInfo.Name.ToLower();
|
||||
parameter.Optional =
|
||||
defaultValue == null || defaultValue.GetType() != typeof( DBNull );
|
||||
|
||||
string resourceName = $"PARAMETER_DESCRIPTION_{attrParam.ToUpper()}";
|
||||
|
||||
string resourceValue = Resources.ResourceManager.GetString( resourceName );
|
||||
|
||||
if ( string.IsNullOrEmpty( resourceValue ) )
|
||||
{
|
||||
throw new InvalidOperationException( resourceName );
|
||||
}
|
||||
|
||||
parameter.Description = !string.IsNullOrEmpty( resourceValue )
|
||||
? resourceValue
|
||||
: Resources.Unknown;
|
||||
|
||||
if ( attr2Params != null && attr2Params?.Length >= i + 1 &&
|
||||
attr2Params?[i] != null )
|
||||
{
|
||||
dynamic typeSA = FindEnumType( attr2Params?[i], assembly );
|
||||
parameter.SeeAlso = typeSA;
|
||||
|
||||
if ( typeSA != null && !seeAlsoTypes.Contains( typeSA ) )
|
||||
{
|
||||
seeAlsoTypes.Add( typeSA );
|
||||
}
|
||||
}
|
||||
|
||||
param.Add( parameter );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
commands.Add( new Commands
|
||||
{
|
||||
Category = ( (dynamic) attrCD ).Category,
|
||||
CategoryLN = ( (dynamic) attrCDLN ).Category,
|
||||
Description = ( (dynamic) attrCD ).Description,
|
||||
Example = ( (dynamic) attrCD ).Example,
|
||||
InsertText = ( (dynamic) attrCD ).InsertText,
|
||||
Signature = memberInfo.ToString(),
|
||||
Name = memberInfo.Name,
|
||||
Parameters = param
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
commands.Sort( new CommandComparer() );
|
||||
|
||||
// Localized, Language Neutral Category
|
||||
IEnumerable<(string L, string LN)> categories = commands.Select( c => (c.Category, c.CategoryLN) ).Distinct();
|
||||
|
||||
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo( assembly.Location );
|
||||
|
||||
string markDown =
|
||||
$"# {Resources.ClassicAssist_Macro_Commands} \n{Resources.Generated_on} {DateTime.UtcNow} \n{Resources.Version}: {fvi.ProductVersion} \n \n";
|
||||
|
||||
if ( !string.IsNullOrEmpty( Resources.TRANSLATE_CREDIT ) )
|
||||
{
|
||||
markDown =
|
||||
$"# {Resources.ClassicAssist_Macro_Commands} \n{Resources.Generated_on} {DateTime.UtcNow} \n{Resources.Version}: {fvi.ProductVersion} \n{Resources.TRANSLATE_CREDIT} \n \n";
|
||||
}
|
||||
|
||||
foreach ( var category in categories )
|
||||
{
|
||||
IEnumerable<Commands> categoryCommands =
|
||||
commands.Where( c => c.Category == category.L ).OrderBy( c => c.Name );
|
||||
|
||||
GenerateCategory( assembly, category.L, category.LN, categoryCommands, seeAlsoTypes, locale );
|
||||
|
||||
string categoryFileName = $"{RemoveAccents( category.LN )}-{locale}.md".Replace( ' ', '-' );
|
||||
|
||||
if ( locale.Equals( "en-US" ) )
|
||||
{
|
||||
categoryFileName = $"{category.LN}.md";
|
||||
}
|
||||
|
||||
markDown += $"## [{category.L}]({Path.GetFileNameWithoutExtension( categoryFileName )}) \n";
|
||||
|
||||
foreach ( Commands categoryCommand in categoryCommands )
|
||||
{
|
||||
markDown +=
|
||||
$"[{categoryCommand.Name}]({Path.GetFileNameWithoutExtension( categoryFileName )}#{categoryCommand.Name}) \n";
|
||||
}
|
||||
}
|
||||
|
||||
//markDown += $"## {Resources.Types} \n";
|
||||
|
||||
//seeAlsoTypes = seeAlsoTypes.OrderBy( t => t.Name ).ToList();
|
||||
|
||||
//foreach ( Type seeAlsoType in seeAlsoTypes )
|
||||
//{
|
||||
// markDown += $"### {seeAlsoType.Name} \n";
|
||||
|
||||
// string[] enumNames = seeAlsoType.GetEnumNames();
|
||||
|
||||
// if ( enumNames == null )
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// markDown = enumNames.Aggregate( markDown, ( current, enumName ) => current + $"* {enumName} \n" );
|
||||
|
||||
// markDown += " \n";
|
||||
//}
|
||||
|
||||
string fileName = $"Macro-Commands ({locale}).md";
|
||||
|
||||
if ( locale.Equals( "en-US" ) )
|
||||
{
|
||||
fileName = "Macro-Commands.md";
|
||||
}
|
||||
|
||||
File.WriteAllText( Path.Combine( originalDirectory, "Docs", fileName ), markDown );
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
Console.WriteLine( $"Finished in {sw.Elapsed}" );
|
||||
}
|
||||
|
||||
private static void GenerateCategory( Assembly assembly, string category, string categoryLN,
|
||||
IEnumerable<Commands> categoryCommands, List<Type> seeAlsoTypes, string locale )
|
||||
{
|
||||
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo( assembly.Location );
|
||||
|
||||
string markDown =
|
||||
$"# {Resources.ClassicAssist_Macro_Commands} \n{Resources.Generated_on} {DateTime.UtcNow} \n{Resources.Version}: {fvi.ProductVersion} \n \n";
|
||||
|
||||
if ( !string.IsNullOrEmpty( Resources.TRANSLATE_CREDIT ) )
|
||||
{
|
||||
markDown =
|
||||
$"# {Resources.ClassicAssist_Macro_Commands} \n{Resources.Generated_on} {DateTime.UtcNow} \n{Resources.Version}: {fvi.ProductVersion} \n{Resources.TRANSLATE_CREDIT} \n \n";
|
||||
}
|
||||
|
||||
markDown += $"## {category} \n";
|
||||
|
||||
List<string> seeAlsoNames = new List<string>();
|
||||
|
||||
foreach ( Commands command in categoryCommands )
|
||||
{
|
||||
string example = command.InsertText;
|
||||
|
||||
if ( !string.IsNullOrEmpty( command.Example ) )
|
||||
{
|
||||
example = command.Example;
|
||||
}
|
||||
|
||||
markDown += $"### {command.Name} \n \n";
|
||||
markDown += $"{Resources.Method_Signature}: \n \n**{command.Signature}** \n \n";
|
||||
|
||||
if ( command.Parameters.Any() )
|
||||
{
|
||||
markDown += $"#### {Resources.Parameters} \n";
|
||||
|
||||
foreach ( Parameter parameter in command.Parameters )
|
||||
{
|
||||
markDown +=
|
||||
$"* {parameter.Name}: {parameter.Description}.{( parameter.Optional ? $" ({Resources.Optional})" : "" )}";
|
||||
|
||||
if ( parameter.SeeAlso != null )
|
||||
{
|
||||
if ( !seeAlsoNames.Contains( parameter.SeeAlso.Name ) )
|
||||
{
|
||||
seeAlsoNames.Add( parameter.SeeAlso.Name );
|
||||
}
|
||||
|
||||
markDown += string.Format( $" {Resources.See_Also___0_} \n",
|
||||
$"[{parameter.SeeAlso.Name}](#{parameter.SeeAlso.Name})" );
|
||||
}
|
||||
else
|
||||
{
|
||||
markDown += " \n";
|
||||
}
|
||||
}
|
||||
|
||||
markDown += " \n";
|
||||
}
|
||||
|
||||
markDown += $"{Resources.Description}: \n \n**{command.Description}** \n \n";
|
||||
markDown += $"{Resources.Example}: \n \n```python \n{example} \n``` \n \n";
|
||||
}
|
||||
|
||||
markDown += "\n\n\n";
|
||||
|
||||
IOrderedEnumerable<Type> includedSeeAlso =
|
||||
seeAlsoTypes.Where( i => seeAlsoNames.Contains( i.Name ) ).OrderBy( i => i.Name );
|
||||
|
||||
if ( includedSeeAlso.Any() )
|
||||
{
|
||||
markDown += $"## {Resources.Types} \n";
|
||||
|
||||
foreach ( Type seeAlsoType in includedSeeAlso )
|
||||
{
|
||||
markDown += $"### {seeAlsoType.Name} \n";
|
||||
|
||||
string[] enumNames = seeAlsoType.GetEnumNames();
|
||||
|
||||
if ( enumNames == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
markDown = enumNames.Aggregate( markDown, ( current, enumName ) => current + $"* {enumName} \n" );
|
||||
|
||||
markDown += " \n";
|
||||
}
|
||||
}
|
||||
|
||||
string fileName = $"{RemoveAccents( categoryLN )}-{locale}.md".Replace( ' ', '-' );
|
||||
|
||||
if ( locale.Equals( "en-US" ) )
|
||||
{
|
||||
fileName = $"{categoryLN}.md";
|
||||
}
|
||||
|
||||
File.WriteAllText( Path.Combine( Environment.CurrentDirectory, "Docs", fileName ), markDown );
|
||||
}
|
||||
|
||||
private static Type FindEnumType( string shortName, Assembly assembly )
|
||||
{
|
||||
Type matchingType = assembly.GetTypes().FirstOrDefault( t => t.Name == shortName );
|
||||
|
||||
return matchingType;
|
||||
}
|
||||
|
||||
private static Assembly OnAssemblyResolve( object sender, ResolveEventArgs args )
|
||||
{
|
||||
string assemblyname = new AssemblyName( args.Name ).Name;
|
||||
|
||||
string[] searchPaths = { Environment.CurrentDirectory, RuntimeEnvironment.GetRuntimeDirectory() };
|
||||
|
||||
if ( assemblyname.Contains( "Colletions" ) )
|
||||
{
|
||||
assemblyname = "System.Collections";
|
||||
}
|
||||
|
||||
foreach ( string searchPath in searchPaths )
|
||||
{
|
||||
string fullPath = Path.Combine( searchPath, assemblyname + ".dll" );
|
||||
|
||||
string culture = new AssemblyName( args.Name ).CultureName;
|
||||
|
||||
if ( !File.Exists( fullPath ) )
|
||||
{
|
||||
string culturePath = Path.Combine( searchPath, culture, assemblyname + ".dll" );
|
||||
|
||||
if ( File.Exists( culturePath ) )
|
||||
{
|
||||
fullPath = culturePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Assembly assembly = Assembly.LoadFrom( fullPath );
|
||||
Console.WriteLine( $"Loading {fullPath}" );
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
Console.WriteLine( $"Couldn't locate {assemblyname}..." );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string RemoveAccents( string input )
|
||||
{
|
||||
byte[] tempBytes = Encoding.GetEncoding( "ISO-8859-8" ).GetBytes( input );
|
||||
return Encoding.UTF8.GetString( tempBytes );
|
||||
}
|
||||
}
|
||||
|
||||
internal class CommandComparer : IComparer<Commands>
|
||||
{
|
||||
public int Compare( Commands x, Commands y )
|
||||
{
|
||||
int result = string.Compare( x?.Category, y?.Category, StringComparison.InvariantCultureIgnoreCase );
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Parameter
|
||||
{
|
||||
public string Description { get; set; } = "Unknown";
|
||||
public string Name { get; set; } = "Unknown";
|
||||
public bool Optional { get; set; }
|
||||
public Type SeeAlso { get; set; }
|
||||
}
|
||||
|
||||
internal class Commands
|
||||
{
|
||||
public string Category { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Example { get; set; }
|
||||
public string InsertText { get; set; }
|
||||
public string Name { get; set; }
|
||||
public List<Parameter> Parameters { get; set; }
|
||||
public string Signature { get; set; }
|
||||
public string CategoryLN { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user