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:
|
||||
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.
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<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.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
|
||||
<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.")]
|
||||
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}\".")]
|
||||
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);
|
||||
|
||||
// ReSharper disable ClassWithVirtualMembersNeverInherited.Global, MemberCanBePrivate.Global, MemberCanBeProtected.Global, PropertyCanBeMadeInitOnly.Global
|
||||
public class ProtodecContext
|
||||
public partial class ProtodecContext
|
||||
{
|
||||
private readonly Dictionary<string, TopLevel> _parsed = [];
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ using LibProtodec;
|
|||
using LibProtodec.Loaders;
|
||||
using LibProtodec.Models.Cil;
|
||||
using LibProtodec.Models.Protobuf;
|
||||
using Loretta.CodeAnalysis;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
ConsoleApp.ConsoleAppBuilder app = ConsoleApp.Create();
|
||||
|
@ -47,10 +48,10 @@ internal sealed class Commands
|
|||
using ILoggerFactory loggerFactory = CreateLoggerFactory(logLevel);
|
||||
ILogger logger = CreateProtodecLogger(loggerFactory);
|
||||
|
||||
logger.LogInformation("Loading target assemblies...");
|
||||
logger.LogInformation("Loading CIL assemblies...");
|
||||
using ClrAssemblyLoader loader = new(targetPath, loggerFactory.CreateLogger<ClrAssemblyLoader>());
|
||||
|
||||
Handle(
|
||||
HandleCil(
|
||||
loader,
|
||||
outPath,
|
||||
skipEnums,
|
||||
|
@ -100,10 +101,10 @@ internal sealed class Commands
|
|||
using ILoggerFactory loggerFactory = CreateLoggerFactory(logLevel);
|
||||
ILogger logger = CreateProtodecLogger(loggerFactory);
|
||||
|
||||
logger.LogInformation("Loading target assemblies...");
|
||||
logger.LogInformation("Loading Il2Cpp assembly and metadata...");
|
||||
Il2CppAssemblyLoader loader = new(gameAssembly, globalMetadata, unityVer, loggerFactory);
|
||||
|
||||
Handle(
|
||||
HandleCil(
|
||||
loader,
|
||||
outPath,
|
||||
skipEnums,
|
||||
|
@ -115,7 +116,73 @@ internal sealed class Commands
|
|||
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,
|
||||
string outPath,
|
||||
bool skipEnums,
|
||||
|
|
Loading…
Reference in New Issue