mirror of https://github.com/Xpl0itR/protodec.git
Make the necessary infrastructural changes for parsing protos from lua source files
This commit is contained in:
parent
bf2feae2e9
commit
1c1e14c58f
|
@ -22,6 +22,7 @@ Options:
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
il2cpp Use LibCpp2IL backend to directly load Il2Cpp compiled game assembly. EXPERIMENTAL.
|
il2cpp Use LibCpp2IL backend to directly load Il2Cpp compiled game assembly. EXPERIMENTAL.
|
||||||
|
lua Use Lua AST backend to load Lua source files.
|
||||||
```
|
```
|
||||||
See per-command help message for more info.
|
See per-command help message for more info.
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Loretta.CodeAnalysis.Lua" Version="0.2.12" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0-preview.6.24327.7" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0-preview.6.24327.7" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="Samboy063.LibCpp2IL" Version="2022.1.0-development.1027" />
|
<PackageReference Include="Samboy063.LibCpp2IL" Version="2022.1.0-development.1027" />
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright © 2024 Xpl0itR
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Loretta.CodeAnalysis;
|
||||||
|
using Loretta.CodeAnalysis.Lua;
|
||||||
|
using Loretta.CodeAnalysis.Text;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace LibProtodec.Loaders;
|
||||||
|
|
||||||
|
public sealed class LuaSourceLoader
|
||||||
|
{
|
||||||
|
public IReadOnlyList<SyntaxTree> LoadedSyntaxTrees { get; }
|
||||||
|
|
||||||
|
public LuaSourceLoader(string sourcePath, ILogger<LuaSourceLoader>? logger = null)
|
||||||
|
{
|
||||||
|
LoadedSyntaxTrees = File.Exists(sourcePath)
|
||||||
|
? [LoadSyntaxTreeFromSourceFile(sourcePath)]
|
||||||
|
: Directory.EnumerateFiles(sourcePath, searchPattern: "*.lua")
|
||||||
|
.Select(LoadSyntaxTreeFromSourceFile)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
logger?.LogLoadedLuaSyntaxTrees(LoadedSyntaxTrees.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SyntaxTree LoadSyntaxTreeFromSourceFile(string filePath)
|
||||||
|
{
|
||||||
|
using FileStream fileStream = File.OpenRead(filePath);
|
||||||
|
|
||||||
|
return LuaSyntaxTree.ParseText(
|
||||||
|
SourceText.From(fileStream),
|
||||||
|
null, // TODO: maybe expose the options parameter
|
||||||
|
Path.GetFileName(filePath));
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,9 @@ internal static partial class LoggerMessages
|
||||||
[LoggerMessage(Level = LogLevel.Information, Message = "Loaded {typeCount} types from {assemblyCount} assemblies for parsing.")]
|
[LoggerMessage(Level = LogLevel.Information, Message = "Loaded {typeCount} types from {assemblyCount} assemblies for parsing.")]
|
||||||
internal static partial void LogLoadedTypeAndAssemblyCount(this ILogger logger, int typeCount, int assemblyCount);
|
internal static partial void LogLoadedTypeAndAssemblyCount(this ILogger logger, int typeCount, int assemblyCount);
|
||||||
|
|
||||||
|
[LoggerMessage(Level = LogLevel.Information, Message = "Loaded {treeCount} Lua syntax trees for parsing.")]
|
||||||
|
internal static partial void LogLoadedLuaSyntaxTrees(this ILogger logger, int treeCount);
|
||||||
|
|
||||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Parsed as enum \"{name}\".")]
|
[LoggerMessage(Level = LogLevel.Debug, Message = "Parsed as enum \"{name}\".")]
|
||||||
internal static partial void LogParsedEnum(this ILogger logger, string name);
|
internal static partial void LogParsedEnum(this ILogger logger, string name);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright © 2024 Xpl0itR
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Loretta.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace LibProtodec;
|
||||||
|
|
||||||
|
partial class ProtodecContext
|
||||||
|
{
|
||||||
|
public void ParseLuaSyntaxTree(SyntaxTree ast)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ namespace LibProtodec;
|
||||||
public delegate bool NameLookupFunc(string name, [MaybeNullWhen(false)] out string translatedName);
|
public delegate bool NameLookupFunc(string name, [MaybeNullWhen(false)] out string translatedName);
|
||||||
|
|
||||||
// ReSharper disable ClassWithVirtualMembersNeverInherited.Global, MemberCanBePrivate.Global, MemberCanBeProtected.Global, PropertyCanBeMadeInitOnly.Global
|
// ReSharper disable ClassWithVirtualMembersNeverInherited.Global, MemberCanBePrivate.Global, MemberCanBeProtected.Global, PropertyCanBeMadeInitOnly.Global
|
||||||
public class ProtodecContext
|
public partial class ProtodecContext
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, TopLevel> _parsed = [];
|
private readonly Dictionary<string, TopLevel> _parsed = [];
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ using LibProtodec;
|
||||||
using LibProtodec.Loaders;
|
using LibProtodec.Loaders;
|
||||||
using LibProtodec.Models.Cil;
|
using LibProtodec.Models.Cil;
|
||||||
using LibProtodec.Models.Protobuf;
|
using LibProtodec.Models.Protobuf;
|
||||||
|
using Loretta.CodeAnalysis;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
ConsoleApp.ConsoleAppBuilder app = ConsoleApp.Create();
|
ConsoleApp.ConsoleAppBuilder app = ConsoleApp.Create();
|
||||||
|
@ -47,10 +48,10 @@ internal sealed class Commands
|
||||||
using ILoggerFactory loggerFactory = CreateLoggerFactory(logLevel);
|
using ILoggerFactory loggerFactory = CreateLoggerFactory(logLevel);
|
||||||
ILogger logger = CreateProtodecLogger(loggerFactory);
|
ILogger logger = CreateProtodecLogger(loggerFactory);
|
||||||
|
|
||||||
logger.LogInformation("Loading target assemblies...");
|
logger.LogInformation("Loading CIL assemblies...");
|
||||||
using ClrAssemblyLoader loader = new(targetPath, loggerFactory.CreateLogger<ClrAssemblyLoader>());
|
using ClrAssemblyLoader loader = new(targetPath, loggerFactory.CreateLogger<ClrAssemblyLoader>());
|
||||||
|
|
||||||
Handle(
|
HandleCil(
|
||||||
loader,
|
loader,
|
||||||
outPath,
|
outPath,
|
||||||
skipEnums,
|
skipEnums,
|
||||||
|
@ -100,10 +101,10 @@ internal sealed class Commands
|
||||||
using ILoggerFactory loggerFactory = CreateLoggerFactory(logLevel);
|
using ILoggerFactory loggerFactory = CreateLoggerFactory(logLevel);
|
||||||
ILogger logger = CreateProtodecLogger(loggerFactory);
|
ILogger logger = CreateProtodecLogger(loggerFactory);
|
||||||
|
|
||||||
logger.LogInformation("Loading target assemblies...");
|
logger.LogInformation("Loading Il2Cpp assembly and metadata...");
|
||||||
Il2CppAssemblyLoader loader = new(gameAssembly, globalMetadata, unityVer, loggerFactory);
|
Il2CppAssemblyLoader loader = new(gameAssembly, globalMetadata, unityVer, loggerFactory);
|
||||||
|
|
||||||
Handle(
|
HandleCil(
|
||||||
loader,
|
loader,
|
||||||
outPath,
|
outPath,
|
||||||
skipEnums,
|
skipEnums,
|
||||||
|
@ -115,7 +116,73 @@ internal sealed class Commands
|
||||||
logger);
|
logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Handle(
|
/// <summary>
|
||||||
|
/// Use Lua AST backend to load Lua source files.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="targetPath">Either the path to the target lua file or a directory of lua files, all of which be parsed.</param>
|
||||||
|
/// <param name="outPath">An existing directory to output into individual files, otherwise output to a single file.</param>
|
||||||
|
/// <param name="logLevel">Logging severity level.</param>
|
||||||
|
[Command("lua")]
|
||||||
|
public void Lua(
|
||||||
|
[Argument] string targetPath,
|
||||||
|
[Argument] string outPath,
|
||||||
|
LogLevel logLevel = LogLevel.Information)
|
||||||
|
{
|
||||||
|
using ILoggerFactory loggerFactory = CreateLoggerFactory(logLevel);
|
||||||
|
ILogger logger = CreateProtodecLogger(loggerFactory);
|
||||||
|
|
||||||
|
logger.LogInformation("Loading Lua sources...");
|
||||||
|
LuaSourceLoader loader = new(targetPath, loggerFactory.CreateLogger<LuaSourceLoader>());
|
||||||
|
|
||||||
|
ProtodecContext ctx = new()
|
||||||
|
{
|
||||||
|
Logger = loggerFactory.CreateLogger<ProtodecContext>()
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.LogInformation("Parsing Lua syntax trees...");
|
||||||
|
foreach (SyntaxTree ast in loader.LoadedSyntaxTrees)
|
||||||
|
{
|
||||||
|
ctx.ParseLuaSyntaxTree(ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: I'm duplicating this code rather than refactoring because I have a lot of uncommited changes on another computer,
|
||||||
|
// therefore, so as to not give myself brain cancer, I will not touch anything that would cause git conflicts.
|
||||||
|
const string indent = " ";
|
||||||
|
if (Directory.Exists(outPath))
|
||||||
|
{
|
||||||
|
logger.LogInformation("Writing {count} Protobuf files to \"{path}\"...", ctx.Protobufs.Count, outPath);
|
||||||
|
|
||||||
|
HashSet<string> writtenFiles = [];
|
||||||
|
foreach (Protobuf protobuf in ctx.Protobufs)
|
||||||
|
{
|
||||||
|
// This workaround stops files from being overwritten in the case of a naming conflict,
|
||||||
|
// however the actual conflict will still have to be resolved manually
|
||||||
|
string fileName = protobuf.FileName;
|
||||||
|
while (!writtenFiles.Add(fileName))
|
||||||
|
{
|
||||||
|
fileName = '_' + fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
string protobufPath = Path.Join(outPath, fileName);
|
||||||
|
|
||||||
|
using StreamWriter streamWriter = new(protobufPath);
|
||||||
|
using IndentedTextWriter indentWriter = new(streamWriter, indent);
|
||||||
|
|
||||||
|
protobuf.WriteTo(indentWriter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogInformation("Writing Protobufs as a single file to \"{path}\"...", outPath);
|
||||||
|
|
||||||
|
using StreamWriter streamWriter = new(outPath);
|
||||||
|
using IndentedTextWriter indentWriter = new(streamWriter, indent);
|
||||||
|
|
||||||
|
ctx.WriteAllTo(indentWriter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleCil(
|
||||||
CilAssemblyLoader loader,
|
CilAssemblyLoader loader,
|
||||||
string outPath,
|
string outPath,
|
||||||
bool skipEnums,
|
bool skipEnums,
|
||||||
|
|
Loading…
Reference in New Issue