From 885808fb66233caf3057f0baa6368f4763a8eade Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 8 Aug 2021 00:21:28 -0400 Subject: move assembly resolver setup into Constants to centralize hardcoded logic --- src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 2b71038a..86b43990 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -59,9 +59,7 @@ namespace StardewModdingAPI.Framework.ModLoading // init resolver this.AssemblyDefinitionResolver = this.TrackForDisposal(new AssemblyDefinitionResolver()); - this.AssemblyDefinitionResolver.AddSearchDirectory(Constants.ExecutionPath); - this.AssemblyDefinitionResolver.AddSearchDirectory(Constants.InternalFilesPath); - this.AssemblyDefinitionResolver.Add(AssemblyDefinition.ReadAssembly(typeof(SGame).Assembly.Location)); // for some reason Mono.Cecil can't resolve SMAPI in very specific cases involving unofficial 64-bit Stardew Valley when launched through Steam (for some players only) + Constants.ConfigureAssemblyResolver(this.AssemblyDefinitionResolver); // generate type => assembly lookup for types which should be rewritten this.TypeAssemblies = new Dictionary(); -- cgit From 976c66537c9f4493ce859c574675bb8651b5323f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 8 Aug 2021 00:24:20 -0400 Subject: fix edge case where Netcode references aren't rewritten correctly --- .../Framework/ModLoading/AssemblyDefinitionResolver.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs b/src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs index aefb0126..b3415609 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs @@ -21,11 +21,17 @@ namespace StardewModdingAPI.Framework.ModLoading public void Add(params AssemblyDefinition[] assemblies) { foreach (AssemblyDefinition assembly in assemblies) - { - this.RegisterAssembly(assembly); - this.Lookup[assembly.Name.Name] = assembly; - this.Lookup[assembly.Name.FullName] = assembly; - } + this.Add(assembly, assembly.Name.Name, assembly.Name.FullName); + } + + /// Add known assemblies to the resolver. + /// The assembly to add. + /// The assembly names for which it should be returned. + public void Add(AssemblyDefinition assembly, params string[] names) + { + this.RegisterAssembly(assembly); + foreach (string name in names) + this.Lookup[name] = assembly; } /// Resolve an assembly reference. -- cgit From 6cf7c49f34eac8edd18012d41d1f49a149fb1f5a Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 15 Aug 2021 01:25:56 -0400 Subject: add GetInAllLocales to translation API --- .../Framework/ModHelpers/TranslationHelper.cs | 6 ++ src/SMAPI/Framework/Translator.cs | 65 ++++++++++++++++++---- 2 files changed, 60 insertions(+), 11 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModHelpers/TranslationHelper.cs b/src/SMAPI/Framework/ModHelpers/TranslationHelper.cs index a88ca9c9..869664fe 100644 --- a/src/SMAPI/Framework/ModHelpers/TranslationHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/TranslationHelper.cs @@ -55,6 +55,12 @@ namespace StardewModdingAPI.Framework.ModHelpers return this.Translator.Get(key, tokens); } + /// + public IDictionary GetInAllLocales(string key, bool withFallback = false) + { + return this.Translator.GetInAllLocales(key, withFallback); + } + /// Set the translations to use. /// The translations to use. internal TranslationHelper SetTranslations(IDictionary> translations) diff --git a/src/SMAPI/Framework/Translator.cs b/src/SMAPI/Framework/Translator.cs index 11ec983b..4492b17f 100644 --- a/src/SMAPI/Framework/Translator.cs +++ b/src/SMAPI/Framework/Translator.cs @@ -46,18 +46,10 @@ namespace StardewModdingAPI.Framework this.LocaleEnum = localeEnum; this.ForLocale = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (string next in this.GetRelevantLocales(this.Locale)) + foreach (string key in this.GetAllKeysRaw()) { - // skip if locale not defined - if (!this.All.TryGetValue(next, out IDictionary translations)) - continue; - - // add missing translations - foreach (var pair in translations) - { - if (!this.ForLocale.ContainsKey(pair.Key)) - this.ForLocale.Add(pair.Key, new Translation(this.Locale, pair.Key, pair.Value)); - } + string text = this.GetRaw(key, locale, withFallback: true); + this.ForLocale.Add(key, new Translation(this.Locale, key, text)); } } @@ -83,6 +75,25 @@ namespace StardewModdingAPI.Framework return this.Get(key).Tokens(tokens); } + /// Get a translation in every locale for which it's defined. + /// The translation key. + /// Whether to add duplicate translations for locale fallback. For example, if a translation is defined in default.json but not fr.json, setting this to true will add a fr entry which duplicates the default text. + public IDictionary GetInAllLocales(string key, bool withFallback) + { + IDictionary translations = new Dictionary(); + + foreach (var localeSet in this.All) + { + string locale = localeSet.Key; + string text = this.GetRaw(key, locale, withFallback); + + if (text != null) + translations[locale] = new Translation(locale, key, text); + } + + return translations; + } + /// Set the translations to use. /// The translations to use. internal Translator SetTranslations(IDictionary> translations) @@ -102,6 +113,38 @@ namespace StardewModdingAPI.Framework /********* ** Private methods *********/ + /// Get all translation keys in the underlying translation data, ignoring the cache. + private IEnumerable GetAllKeysRaw() + { + return new HashSet( + this.All.SelectMany(p => p.Value.Keys), + StringComparer.OrdinalIgnoreCase + ); + } + + /// Get a translation from the underlying translation data, ignoring the cache. + /// The translation key. + /// The locale to get. + /// Whether to add duplicate translations for locale fallback. For example, if a translation is defined in default.json but not fr.json, setting this to true will add a fr entry which duplicates the default text. + private string GetRaw(string key, string locale, bool withFallback) + { + foreach (string next in this.GetRelevantLocales(locale)) + { + string translation = null; + bool hasTranslation = + this.All.TryGetValue(next, out IDictionary translations) + && translations.TryGetValue(key, out translation); + + if (hasTranslation) + return translation; + + if (!withFallback) + break; + } + + return null; + } + /// Get the locales which can provide translations for the given locale, in precedence order. /// The locale for which to find valid locales. private IEnumerable GetRelevantLocales(string locale) -- cgit From 68e629f17c349b685ef3c4836552adcbed0c4976 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 16 Aug 2021 17:22:44 -0400 Subject: fix data helper's WriteJsonFile not deleting file if data is null (#799) --- src/SMAPI/Framework/ModHelpers/DataHelper.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModHelpers/DataHelper.cs b/src/SMAPI/Framework/ModHelpers/DataHelper.cs index 0fe3209f..4cbfd73f 100644 --- a/src/SMAPI/Framework/ModHelpers/DataHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/DataHelper.cs @@ -58,7 +58,11 @@ namespace StardewModdingAPI.Framework.ModHelpers throw new InvalidOperationException($"You must call {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.WriteJsonFile)} with a relative path (without directory climbing)."); path = Path.Combine(this.ModFolderPath, PathUtilities.NormalizePath(path)); - this.JsonHelper.WriteJsonFile(path, data); + + if (data != null) + this.JsonHelper.WriteJsonFile(path, data); + else + File.Delete(path); } /**** -- cgit From 596a4616b343bc527c0a90df0f0be0ece970c3c7 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 18 Aug 2021 23:38:23 -0400 Subject: no longer abort input thread when exiting `thread.Abort` is unimplemented in .NET 5, but it's not needed anyway since all threads will be aborted when the game exits. --- src/SMAPI/Framework/Logging/LogManager.cs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs index a3d4f23d..7f1b76e7 100644 --- a/src/SMAPI/Framework/Logging/LogManager.cs +++ b/src/SMAPI/Framework/Logging/LogManager.cs @@ -162,8 +162,6 @@ namespace StardewModdingAPI.Framework.Logging // keep console thread alive while the game is running while (continueWhile()) Thread.Sleep(1000 / 10); - if (inputThread.ThreadState == ThreadState.Running) - inputThread.Abort(); } /// Show a 'press any key to exit' message, and exit when they press a key. -- cgit From f8c76bde39ba2afb11540c9af5d88aad4c73f789 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 24 Aug 2021 21:59:52 -0400 Subject: add 64-bit compatibility check before loading mods That reduces time spent trying to rewrite them (which won't work anyway), and shows a more informative message than the default 'DLL couldn't be loaded' error. --- src/SMAPI/Framework/SCore.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 5fb4aa03..dff0fc55 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1704,12 +1704,21 @@ namespace StardewModdingAPI.Framework // load as mod else { + // get mod info IManifest manifest = mod.Manifest; + string assemblyPath = Path.Combine(mod.DirectoryPath, manifest.EntryDll); + + // assert 64-bit +#if SMAPI_FOR_WINDOWS_64BIT_HACK + if (!EnvironmentUtility.Is64BitAssembly(assemblyPath)) + { + errorReasonPhrase = "it needs to be updated for 64-bit mode."; + failReason = ModFailReason.LoadFailed; + return false; + } +#endif // load mod - string assemblyPath = manifest?.EntryDll != null - ? Path.Combine(mod.DirectoryPath, manifest.EntryDll) - : null; Assembly modAssembly; try { -- cgit From 911843e1beb72a3fc0337a697f732215b66304c0 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 25 Aug 2021 18:26:02 -0400 Subject: fix console encoding issues (#798) --- src/SMAPI/Framework/Logging/LogManager.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs index 7f1b76e7..c6faa90d 100644 --- a/src/SMAPI/Framework/Logging/LogManager.cs +++ b/src/SMAPI/Framework/Logging/LogManager.cs @@ -109,9 +109,12 @@ namespace StardewModdingAPI.Framework.Logging output.OnMessageIntercepted += message => this.HandleConsoleMessage(this.MonitorForGame, message); Console.SetOut(output); - // enable Unicode handling + // enable Unicode handling on Windows + // (the terminal defaults to UTF-8 on Linux/macOS) +#if SMAPI_FOR_WINDOWS Console.InputEncoding = Encoding.Unicode; Console.OutputEncoding = Encoding.Unicode; +#endif } /// Get a monitor instance derived from SMAPI's current settings. -- cgit From c5c7201151709bed374931268b9c592ca526bfc9 Mon Sep 17 00:00:00 2001 From: Chase Warrington Date: Thu, 19 Aug 2021 17:19:42 -0400 Subject: Fix assembly rewriting causing VS to error/crash when debugging --- src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 31 ++++++++++-------- .../Framework/ModLoading/SymbolReaderProvider.cs | 37 ++++++++++++++++++++++ .../Framework/ModLoading/SymbolWriterProvider.cs | 25 +++++++++++++++ 3 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs create mode 100644 src/SMAPI/Framework/ModLoading/SymbolWriterProvider.cs (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 86b43990..98154b53 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -34,6 +34,9 @@ namespace StardewModdingAPI.Framework.ModLoading /// A minimal assembly definition resolver which resolves references to known loaded assemblies. private readonly AssemblyDefinitionResolver AssemblyDefinitionResolver; + private readonly SymbolReaderProvider SymbolReaderProvider; + private readonly SymbolWriterProvider SymbolWriterProvider; + /// The objects to dispose as part of this instance. private readonly HashSet Disposables = new HashSet(); @@ -61,6 +64,9 @@ namespace StardewModdingAPI.Framework.ModLoading this.AssemblyDefinitionResolver = this.TrackForDisposal(new AssemblyDefinitionResolver()); Constants.ConfigureAssemblyResolver(this.AssemblyDefinitionResolver); + this.SymbolReaderProvider = new SymbolReaderProvider(); + this.SymbolWriterProvider = new SymbolWriterProvider(); + // generate type => assembly lookup for types which should be rewritten this.TypeAssemblies = new Dictionary(); foreach (Assembly assembly in this.AssemblyMap.Targets) @@ -114,7 +120,7 @@ namespace StardewModdingAPI.Framework.ModLoading // rewrite assembly bool changed = this.RewriteAssembly(mod, assembly.Definition, loggedMessages, logPrefix: " "); - + // detect broken assembly reference foreach (AssemblyNameReference reference in assembly.Definition.MainModule.AssemblyReferences) { @@ -134,20 +140,12 @@ namespace StardewModdingAPI.Framework.ModLoading if (!oneAssembly) this.Monitor.Log($" Loading {assembly.File.Name} (rewritten)...", LogLevel.Trace); - // load PDB file if present - byte[] symbols; - { - string symbolsPath = Path.Combine(Path.GetDirectoryName(assemblyPath), Path.GetFileNameWithoutExtension(assemblyPath)) + ".pdb"; - symbols = File.Exists(symbolsPath) - ? File.ReadAllBytes(symbolsPath) - : null; - } - // load assembly using MemoryStream outStream = new MemoryStream(); - assembly.Definition.Write(outStream); + using MemoryStream outSymbolStream = new MemoryStream(); + assembly.Definition.Write(outStream, new WriterParameters() { WriteSymbols = true, SymbolStream = outSymbolStream, SymbolWriterProvider = this.SymbolWriterProvider } ); byte[] bytes = outStream.ToArray(); - lastAssembly = Assembly.Load(bytes, symbols); + lastAssembly = Assembly.Load(bytes, outSymbolStream.ToArray()); } else { @@ -234,10 +232,15 @@ namespace StardewModdingAPI.Framework.ModLoading if (!file.Exists) yield break; // not a local assembly - // read assembly + // read assembly and PDB (if present) byte[] assemblyBytes = File.ReadAllBytes(file.FullName); Stream readStream = this.TrackForDisposal(new MemoryStream(assemblyBytes)); - AssemblyDefinition assembly = this.TrackForDisposal(AssemblyDefinition.ReadAssembly(readStream, new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = assemblyResolver, InMemory = true })); + { + string symbolsPath = Path.Combine(Path.GetDirectoryName(file.FullName), Path.GetFileNameWithoutExtension(file.FullName)) + ".pdb"; + if ( File.Exists( symbolsPath ) ) + this.SymbolReaderProvider.AddSymbolMapping( Path.GetFileName( file.FullName ), this.TrackForDisposal( new MemoryStream( File.ReadAllBytes( symbolsPath ) ) ) ); + } + AssemblyDefinition assembly = this.TrackForDisposal(AssemblyDefinition.ReadAssembly(readStream, new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = assemblyResolver, InMemory = true, ReadSymbols = true, SymbolReaderProvider = this.SymbolReaderProvider })); // skip if already visited if (visitedAssemblyNames.Contains(assembly.Name.Name)) diff --git a/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs b/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs new file mode 100644 index 00000000..a651c167 --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Cecil.Pdb; + +namespace StardewModdingAPI.Framework.ModLoading +{ + internal class SymbolReaderProvider : ISymbolReaderProvider + { + private readonly ISymbolReaderProvider BaseProvider = new DefaultSymbolReaderProvider(); + + private readonly Dictionary SymbolMapping = new Dictionary(); + + public void AddSymbolMapping( string dllName, Stream symbolStream ) + { + this.SymbolMapping.Add( dllName, symbolStream ); + } + + public ISymbolReader GetSymbolReader( ModuleDefinition module, string fileName ) + { + if ( this.SymbolMapping.ContainsKey( module.Name ) ) + return new NativePdbReaderProvider().GetSymbolReader( module, this.SymbolMapping[ module.Name ] ); + + return this.BaseProvider.GetSymbolReader( module, fileName ); + } + + public ISymbolReader GetSymbolReader( ModuleDefinition module, Stream symbolStream ) + { + if ( this.SymbolMapping.ContainsKey( module.Name ) ) + return new PortablePdbReaderProvider().GetSymbolReader( module, this.SymbolMapping[ module.Name ] ); + + return this.BaseProvider.GetSymbolReader( module, symbolStream ); + } + } +} diff --git a/src/SMAPI/Framework/ModLoading/SymbolWriterProvider.cs b/src/SMAPI/Framework/ModLoading/SymbolWriterProvider.cs new file mode 100644 index 00000000..116e341a --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/SymbolWriterProvider.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Cecil.Pdb; + +namespace StardewModdingAPI.Framework.ModLoading +{ + internal class SymbolWriterProvider : ISymbolWriterProvider + { + private readonly ISymbolWriterProvider BaseProvider = new DefaultSymbolWriterProvider(); + + public ISymbolWriter GetSymbolWriter( ModuleDefinition module, string fileName ) + { + return this.BaseProvider.GetSymbolWriter( module, fileName ); + } + + public ISymbolWriter GetSymbolWriter( ModuleDefinition module, Stream symbolStream ) + { + // Not implemented in default native pdb writer, so fallback to portable + return new PortablePdbWriterProvider().GetSymbolWriter( module, symbolStream ); + } + } +} -- cgit From 5030e965dcfa4b8d9c6ed2285ceed5f7cdc472a9 Mon Sep 17 00:00:00 2001 From: Chase Warrington Date: Fri, 20 Aug 2021 01:25:52 -0400 Subject: Fix for loading both types of PDBs --- src/SMAPI/Framework/ModLoading/MySymbolReader.cs | 55 ++++++++++++++++++++++ .../Framework/ModLoading/SymbolReaderProvider.cs | 4 +- 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/SMAPI/Framework/ModLoading/MySymbolReader.cs (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/MySymbolReader.cs b/src/SMAPI/Framework/ModLoading/MySymbolReader.cs new file mode 100644 index 00000000..215631c6 --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/MySymbolReader.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Cecil.Pdb; + +namespace StardewModdingAPI.Framework.ModLoading +{ + internal class MySymbolReader : ISymbolReader + { + private ModuleDefinition Module; + private Stream Stream; + private ISymbolReader Using; + + public MySymbolReader( ModuleDefinition module, Stream stream ) + { + this.Module = module; + this.Stream = stream; + this.Using = new NativePdbReaderProvider().GetSymbolReader( module, stream ); + } + + public void Dispose() + { + this.Using.Dispose(); + } + + public ISymbolWriterProvider GetWriterProvider() + { + return new PortablePdbWriterProvider(); + } + + public bool ProcessDebugHeader( ImageDebugHeader header ) + { + try + { + return this.Using.ProcessDebugHeader( header ); + } + catch (Exception e) + { + this.Using.Dispose(); + this.Using = new PortablePdbReaderProvider().GetSymbolReader( this.Module, this.Stream ); + return this.Using.ProcessDebugHeader( header ); + } + } + + public MethodDebugInformation Read( MethodDefinition method ) + { + return Using.Read( method ); + } + } +} diff --git a/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs b/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs index a651c167..c92e1e4d 100644 --- a/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs +++ b/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs @@ -21,7 +21,7 @@ namespace StardewModdingAPI.Framework.ModLoading public ISymbolReader GetSymbolReader( ModuleDefinition module, string fileName ) { if ( this.SymbolMapping.ContainsKey( module.Name ) ) - return new NativePdbReaderProvider().GetSymbolReader( module, this.SymbolMapping[ module.Name ] ); + return new MySymbolReader( module, this.SymbolMapping[ module.Name ] ); return this.BaseProvider.GetSymbolReader( module, fileName ); } @@ -29,7 +29,7 @@ namespace StardewModdingAPI.Framework.ModLoading public ISymbolReader GetSymbolReader( ModuleDefinition module, Stream symbolStream ) { if ( this.SymbolMapping.ContainsKey( module.Name ) ) - return new PortablePdbReaderProvider().GetSymbolReader( module, this.SymbolMapping[ module.Name ] ); + return new MySymbolReader( module, this.SymbolMapping[ module.Name ] ); return this.BaseProvider.GetSymbolReader( module, symbolStream ); } -- cgit From e3b38a70f8d710af07732b325a6013ed18aa0fb0 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 25 Aug 2021 19:17:29 -0400 Subject: reorganize new classes --- src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 1 + src/SMAPI/Framework/ModLoading/MySymbolReader.cs | 55 ---------------------- .../Framework/ModLoading/SymbolReaderProvider.cs | 37 --------------- .../Framework/ModLoading/SymbolWriterProvider.cs | 25 ---------- .../Framework/ModLoading/Symbols/SymbolReader.cs | 51 ++++++++++++++++++++ .../ModLoading/Symbols/SymbolReaderProvider.cs | 35 ++++++++++++++ .../ModLoading/Symbols/SymbolWriterProvider.cs | 22 +++++++++ 7 files changed, 109 insertions(+), 117 deletions(-) delete mode 100644 src/SMAPI/Framework/ModLoading/MySymbolReader.cs delete mode 100644 src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs delete mode 100644 src/SMAPI/Framework/ModLoading/SymbolWriterProvider.cs create mode 100644 src/SMAPI/Framework/ModLoading/Symbols/SymbolReader.cs create mode 100644 src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs create mode 100644 src/SMAPI/Framework/ModLoading/Symbols/SymbolWriterProvider.cs (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 98154b53..72cfd119 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -7,6 +7,7 @@ using Mono.Cecil; using Mono.Cecil.Cil; using StardewModdingAPI.Framework.Exceptions; using StardewModdingAPI.Framework.ModLoading.Framework; +using StardewModdingAPI.Framework.ModLoading.Symbols; using StardewModdingAPI.Metadata; using StardewModdingAPI.Toolkit.Framework.ModData; using StardewModdingAPI.Toolkit.Utilities; diff --git a/src/SMAPI/Framework/ModLoading/MySymbolReader.cs b/src/SMAPI/Framework/ModLoading/MySymbolReader.cs deleted file mode 100644 index 215631c6..00000000 --- a/src/SMAPI/Framework/ModLoading/MySymbolReader.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Cecil.Pdb; - -namespace StardewModdingAPI.Framework.ModLoading -{ - internal class MySymbolReader : ISymbolReader - { - private ModuleDefinition Module; - private Stream Stream; - private ISymbolReader Using; - - public MySymbolReader( ModuleDefinition module, Stream stream ) - { - this.Module = module; - this.Stream = stream; - this.Using = new NativePdbReaderProvider().GetSymbolReader( module, stream ); - } - - public void Dispose() - { - this.Using.Dispose(); - } - - public ISymbolWriterProvider GetWriterProvider() - { - return new PortablePdbWriterProvider(); - } - - public bool ProcessDebugHeader( ImageDebugHeader header ) - { - try - { - return this.Using.ProcessDebugHeader( header ); - } - catch (Exception e) - { - this.Using.Dispose(); - this.Using = new PortablePdbReaderProvider().GetSymbolReader( this.Module, this.Stream ); - return this.Using.ProcessDebugHeader( header ); - } - } - - public MethodDebugInformation Read( MethodDefinition method ) - { - return Using.Read( method ); - } - } -} diff --git a/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs b/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs deleted file mode 100644 index c92e1e4d..00000000 --- a/src/SMAPI/Framework/ModLoading/SymbolReaderProvider.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Cecil.Pdb; - -namespace StardewModdingAPI.Framework.ModLoading -{ - internal class SymbolReaderProvider : ISymbolReaderProvider - { - private readonly ISymbolReaderProvider BaseProvider = new DefaultSymbolReaderProvider(); - - private readonly Dictionary SymbolMapping = new Dictionary(); - - public void AddSymbolMapping( string dllName, Stream symbolStream ) - { - this.SymbolMapping.Add( dllName, symbolStream ); - } - - public ISymbolReader GetSymbolReader( ModuleDefinition module, string fileName ) - { - if ( this.SymbolMapping.ContainsKey( module.Name ) ) - return new MySymbolReader( module, this.SymbolMapping[ module.Name ] ); - - return this.BaseProvider.GetSymbolReader( module, fileName ); - } - - public ISymbolReader GetSymbolReader( ModuleDefinition module, Stream symbolStream ) - { - if ( this.SymbolMapping.ContainsKey( module.Name ) ) - return new MySymbolReader( module, this.SymbolMapping[ module.Name ] ); - - return this.BaseProvider.GetSymbolReader( module, symbolStream ); - } - } -} diff --git a/src/SMAPI/Framework/ModLoading/SymbolWriterProvider.cs b/src/SMAPI/Framework/ModLoading/SymbolWriterProvider.cs deleted file mode 100644 index 116e341a..00000000 --- a/src/SMAPI/Framework/ModLoading/SymbolWriterProvider.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Cecil.Pdb; - -namespace StardewModdingAPI.Framework.ModLoading -{ - internal class SymbolWriterProvider : ISymbolWriterProvider - { - private readonly ISymbolWriterProvider BaseProvider = new DefaultSymbolWriterProvider(); - - public ISymbolWriter GetSymbolWriter( ModuleDefinition module, string fileName ) - { - return this.BaseProvider.GetSymbolWriter( module, fileName ); - } - - public ISymbolWriter GetSymbolWriter( ModuleDefinition module, Stream symbolStream ) - { - // Not implemented in default native pdb writer, so fallback to portable - return new PortablePdbWriterProvider().GetSymbolWriter( module, symbolStream ); - } - } -} diff --git a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReader.cs b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReader.cs new file mode 100644 index 00000000..f1ae86a2 --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReader.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Cecil.Pdb; + +namespace StardewModdingAPI.Framework.ModLoading.Symbols +{ + internal class SymbolReader : ISymbolReader + { + private ModuleDefinition Module; + private Stream Stream; + private ISymbolReader Using; + + public SymbolReader( ModuleDefinition module, Stream stream ) + { + this.Module = module; + this.Stream = stream; + this.Using = new NativePdbReaderProvider().GetSymbolReader( module, stream ); + } + + public void Dispose() + { + this.Using.Dispose(); + } + + public ISymbolWriterProvider GetWriterProvider() + { + return new PortablePdbWriterProvider(); + } + + public bool ProcessDebugHeader( ImageDebugHeader header ) + { + try + { + return this.Using.ProcessDebugHeader( header ); + } + catch (Exception e) + { + this.Using.Dispose(); + this.Using = new PortablePdbReaderProvider().GetSymbolReader( this.Module, this.Stream ); + return this.Using.ProcessDebugHeader( header ); + } + } + + public MethodDebugInformation Read( MethodDefinition method ) + { + return this.Using.Read( method ); + } + } +} diff --git a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs new file mode 100644 index 00000000..e2a6d21e --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.IO; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace StardewModdingAPI.Framework.ModLoading.Symbols +{ + internal class SymbolReaderProvider : ISymbolReaderProvider + { + private readonly ISymbolReaderProvider BaseProvider = new DefaultSymbolReaderProvider(); + + private readonly Dictionary SymbolMapping = new Dictionary(); + + public void AddSymbolMapping( string dllName, Stream symbolStream ) + { + this.SymbolMapping.Add( dllName, symbolStream ); + } + + public ISymbolReader GetSymbolReader( ModuleDefinition module, string fileName ) + { + if ( this.SymbolMapping.ContainsKey( module.Name ) ) + return new SymbolReader( module, this.SymbolMapping[ module.Name ] ); + + return this.BaseProvider.GetSymbolReader( module, fileName ); + } + + public ISymbolReader GetSymbolReader( ModuleDefinition module, Stream symbolStream ) + { + if ( this.SymbolMapping.ContainsKey( module.Name ) ) + return new SymbolReader( module, this.SymbolMapping[ module.Name ] ); + + return this.BaseProvider.GetSymbolReader( module, symbolStream ); + } + } +} diff --git a/src/SMAPI/Framework/ModLoading/Symbols/SymbolWriterProvider.cs b/src/SMAPI/Framework/ModLoading/Symbols/SymbolWriterProvider.cs new file mode 100644 index 00000000..33e91db0 --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Symbols/SymbolWriterProvider.cs @@ -0,0 +1,22 @@ +using System.IO; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace StardewModdingAPI.Framework.ModLoading.Symbols +{ + internal class SymbolWriterProvider : ISymbolWriterProvider + { + private readonly ISymbolWriterProvider BaseProvider = new DefaultSymbolWriterProvider(); + + public ISymbolWriter GetSymbolWriter( ModuleDefinition module, string fileName ) + { + return this.BaseProvider.GetSymbolWriter( module, fileName ); + } + + public ISymbolWriter GetSymbolWriter( ModuleDefinition module, Stream symbolStream ) + { + // Not implemented in default native pdb writer, so fallback to portable + return new PortablePdbWriterProvider().GetSymbolWriter( module, symbolStream ); + } + } +} -- cgit From 0b29eb3bc37553aa2e9776e17727ba07018606ea Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 25 Aug 2021 20:01:59 -0400 Subject: minor refactoring in new symbol code --- src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 26 +++++----- .../Framework/ModLoading/Symbols/SymbolReader.cs | 59 +++++++++++++++------- .../ModLoading/Symbols/SymbolReaderProvider.cs | 44 +++++++++++----- .../ModLoading/Symbols/SymbolWriterProvider.cs | 28 ++++++++-- 4 files changed, 107 insertions(+), 50 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 72cfd119..5180f072 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -35,8 +35,11 @@ namespace StardewModdingAPI.Framework.ModLoading /// A minimal assembly definition resolver which resolves references to known loaded assemblies. private readonly AssemblyDefinitionResolver AssemblyDefinitionResolver; - private readonly SymbolReaderProvider SymbolReaderProvider; - private readonly SymbolWriterProvider SymbolWriterProvider; + /// Provides assembly symbol readers for Mono.Cecil. + private readonly SymbolReaderProvider SymbolReaderProvider = new SymbolReaderProvider(); + + /// Provides assembly symbol writers for Mono.Cecil. + private readonly SymbolWriterProvider SymbolWriterProvider = new SymbolWriterProvider(); /// The objects to dispose as part of this instance. private readonly HashSet Disposables = new HashSet(); @@ -65,9 +68,6 @@ namespace StardewModdingAPI.Framework.ModLoading this.AssemblyDefinitionResolver = this.TrackForDisposal(new AssemblyDefinitionResolver()); Constants.ConfigureAssemblyResolver(this.AssemblyDefinitionResolver); - this.SymbolReaderProvider = new SymbolReaderProvider(); - this.SymbolWriterProvider = new SymbolWriterProvider(); - // generate type => assembly lookup for types which should be rewritten this.TypeAssemblies = new Dictionary(); foreach (Assembly assembly in this.AssemblyMap.Targets) @@ -121,7 +121,7 @@ namespace StardewModdingAPI.Framework.ModLoading // rewrite assembly bool changed = this.RewriteAssembly(mod, assembly.Definition, loggedMessages, logPrefix: " "); - + // detect broken assembly reference foreach (AssemblyNameReference reference in assembly.Definition.MainModule.AssemblyReferences) { @@ -142,10 +142,10 @@ namespace StardewModdingAPI.Framework.ModLoading this.Monitor.Log($" Loading {assembly.File.Name} (rewritten)...", LogLevel.Trace); // load assembly - using MemoryStream outStream = new MemoryStream(); + using MemoryStream outAssemblyStream = new MemoryStream(); using MemoryStream outSymbolStream = new MemoryStream(); - assembly.Definition.Write(outStream, new WriterParameters() { WriteSymbols = true, SymbolStream = outSymbolStream, SymbolWriterProvider = this.SymbolWriterProvider } ); - byte[] bytes = outStream.ToArray(); + assembly.Definition.Write(outAssemblyStream, new WriterParameters { WriteSymbols = true, SymbolStream = outSymbolStream, SymbolWriterProvider = this.SymbolWriterProvider }); + byte[] bytes = outAssemblyStream.ToArray(); lastAssembly = Assembly.Load(bytes, outSymbolStream.ToArray()); } else @@ -233,13 +233,13 @@ namespace StardewModdingAPI.Framework.ModLoading if (!file.Exists) yield break; // not a local assembly - // read assembly and PDB (if present) + // read assembly and symbols byte[] assemblyBytes = File.ReadAllBytes(file.FullName); Stream readStream = this.TrackForDisposal(new MemoryStream(assemblyBytes)); { - string symbolsPath = Path.Combine(Path.GetDirectoryName(file.FullName), Path.GetFileNameWithoutExtension(file.FullName)) + ".pdb"; - if ( File.Exists( symbolsPath ) ) - this.SymbolReaderProvider.AddSymbolMapping( Path.GetFileName( file.FullName ), this.TrackForDisposal( new MemoryStream( File.ReadAllBytes( symbolsPath ) ) ) ); + FileInfo symbolsFile = new FileInfo(Path.Combine(Path.GetDirectoryName(file.FullName)!, Path.GetFileNameWithoutExtension(file.FullName)) + ".pdb"); + if (symbolsFile.Exists) + this.SymbolReaderProvider.TryAddSymbolData(file.Name, this.TrackForDisposal(symbolsFile.OpenRead())); } AssemblyDefinition assembly = this.TrackForDisposal(AssemblyDefinition.ReadAssembly(readStream, new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = assemblyResolver, InMemory = true, ReadSymbols = true, SymbolReaderProvider = this.SymbolReaderProvider })); diff --git a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReader.cs b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReader.cs index f1ae86a2..2171895d 100644 --- a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReader.cs +++ b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReader.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using Mono.Cecil; using Mono.Cecil.Cil; @@ -6,46 +5,68 @@ using Mono.Cecil.Pdb; namespace StardewModdingAPI.Framework.ModLoading.Symbols { + /// Reads symbol data for an assembly. internal class SymbolReader : ISymbolReader { - private ModuleDefinition Module; - private Stream Stream; - private ISymbolReader Using; + /********* + ** Fields + *********/ + /// The module for which to read symbols. + private readonly ModuleDefinition Module; - public SymbolReader( ModuleDefinition module, Stream stream ) + /// The symbol file stream. + private readonly Stream Stream; + + /// The underlying symbol reader. + private ISymbolReader Reader; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The module for which to read symbols. + /// The symbol file stream. + public SymbolReader(ModuleDefinition module, Stream stream) { this.Module = module; this.Stream = stream; - this.Using = new NativePdbReaderProvider().GetSymbolReader( module, stream ); - } - - public void Dispose() - { - this.Using.Dispose(); + this.Reader = new NativePdbReaderProvider().GetSymbolReader(module, stream); } + /// Get the symbol writer provider for the assembly. public ISymbolWriterProvider GetWriterProvider() { return new PortablePdbWriterProvider(); } - public bool ProcessDebugHeader( ImageDebugHeader header ) + /// Process a debug header in the symbol file. + /// The debug header. + public bool ProcessDebugHeader(ImageDebugHeader header) { try { - return this.Using.ProcessDebugHeader( header ); + return this.Reader.ProcessDebugHeader(header); } - catch (Exception e) + catch { - this.Using.Dispose(); - this.Using = new PortablePdbReaderProvider().GetSymbolReader( this.Module, this.Stream ); - return this.Using.ProcessDebugHeader( header ); + this.Reader.Dispose(); + this.Reader = new PortablePdbReaderProvider().GetSymbolReader(this.Module, this.Stream); + return this.Reader.ProcessDebugHeader(header); } } - public MethodDebugInformation Read( MethodDefinition method ) + /// Read the method debug information for a method in the assembly. + /// The method definition. + public MethodDebugInformation Read(MethodDefinition method) + { + return this.Reader.Read(method); + } + + /// + public void Dispose() { - return this.Using.Read( method ); + this.Reader.Dispose(); } } } diff --git a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs index e2a6d21e..02a70f1c 100644 --- a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs +++ b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using Mono.Cecil; @@ -5,31 +6,48 @@ using Mono.Cecil.Cil; namespace StardewModdingAPI.Framework.ModLoading.Symbols { + /// Provides assembly symbol readers for Mono.Cecil. internal class SymbolReaderProvider : ISymbolReaderProvider { + /********* + ** Fields + *********/ + /// The underlying symbol reader provider. private readonly ISymbolReaderProvider BaseProvider = new DefaultSymbolReaderProvider(); - private readonly Dictionary SymbolMapping = new Dictionary(); + /// The symbol data loaded by absolute assembly path. + private readonly Dictionary SymbolsByAssemblyPath = new Dictionary(StringComparer.OrdinalIgnoreCase); - public void AddSymbolMapping( string dllName, Stream symbolStream ) + + /********* + ** Public methods + *********/ + /// Add the symbol file for a given assembly name, if it's not already registered. + /// The assembly file name. + /// The raw file stream for the symbols. + public void AddSymbolData(string fileName, Stream symbolStream) { - this.SymbolMapping.Add( dllName, symbolStream ); + this.SymbolsByAssemblyPath.Add(fileName, symbolStream); } - public ISymbolReader GetSymbolReader( ModuleDefinition module, string fileName ) + /// Get a symbol reader for a given module and assembly name. + /// The loaded assembly module. + /// The assembly file name. + public ISymbolReader GetSymbolReader(ModuleDefinition module, string fileName) { - if ( this.SymbolMapping.ContainsKey( module.Name ) ) - return new SymbolReader( module, this.SymbolMapping[ module.Name ] ); - - return this.BaseProvider.GetSymbolReader( module, fileName ); + return this.SymbolsByAssemblyPath.TryGetValue(module.Name, out Stream symbolData) + ? new SymbolReader(module, symbolData) + : this.BaseProvider.GetSymbolReader(module, fileName); } - public ISymbolReader GetSymbolReader( ModuleDefinition module, Stream symbolStream ) + /// Get a symbol reader for a given module and symbol stream. + /// The loaded assembly module. + /// The loaded symbol file stream. + public ISymbolReader GetSymbolReader(ModuleDefinition module, Stream symbolStream) { - if ( this.SymbolMapping.ContainsKey( module.Name ) ) - return new SymbolReader( module, this.SymbolMapping[ module.Name ] ); - - return this.BaseProvider.GetSymbolReader( module, symbolStream ); + return this.SymbolsByAssemblyPath.TryGetValue(module.Name, out Stream symbolData) + ? new SymbolReader(module, symbolData) + : this.BaseProvider.GetSymbolReader(module, symbolStream); } } } diff --git a/src/SMAPI/Framework/ModLoading/Symbols/SymbolWriterProvider.cs b/src/SMAPI/Framework/ModLoading/Symbols/SymbolWriterProvider.cs index 33e91db0..8f7e05d1 100644 --- a/src/SMAPI/Framework/ModLoading/Symbols/SymbolWriterProvider.cs +++ b/src/SMAPI/Framework/ModLoading/Symbols/SymbolWriterProvider.cs @@ -4,19 +4,37 @@ using Mono.Cecil.Cil; namespace StardewModdingAPI.Framework.ModLoading.Symbols { + /// Provides assembly symbol writers for Mono.Cecil. internal class SymbolWriterProvider : ISymbolWriterProvider { - private readonly ISymbolWriterProvider BaseProvider = new DefaultSymbolWriterProvider(); + /********* + ** Fields + *********/ + /// The default symbol writer provider. + private readonly ISymbolWriterProvider DefaultProvider = new DefaultSymbolWriterProvider(); - public ISymbolWriter GetSymbolWriter( ModuleDefinition module, string fileName ) + /// The symbol writer provider for the portable PDB format. + private readonly ISymbolWriterProvider PortablePdbProvider = new PortablePdbWriterProvider(); + + + /********* + ** Public methods + *********/ + /// Get a symbol writer for a given module and assembly path. + /// The loaded assembly module. + /// The assembly name. + public ISymbolWriter GetSymbolWriter(ModuleDefinition module, string fileName) { - return this.BaseProvider.GetSymbolWriter( module, fileName ); + return this.DefaultProvider.GetSymbolWriter(module, fileName); } - public ISymbolWriter GetSymbolWriter( ModuleDefinition module, Stream symbolStream ) + /// Get a symbol writer for a given module and symbol stream. + /// The loaded assembly module. + /// The loaded symbol file stream. + public ISymbolWriter GetSymbolWriter(ModuleDefinition module, Stream symbolStream) { // Not implemented in default native pdb writer, so fallback to portable - return new PortablePdbWriterProvider().GetSymbolWriter( module, symbolStream ); + return this.PortablePdbProvider.GetSymbolWriter(module, symbolStream); } } } -- cgit From 687a396e9c7581ebc2b35e58fc9b44d20d93a5d3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 25 Aug 2021 20:02:51 -0400 Subject: fix error when reading a duplicate assembly --- src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 2 +- src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 5180f072..e1ad9d37 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -239,7 +239,7 @@ namespace StardewModdingAPI.Framework.ModLoading { FileInfo symbolsFile = new FileInfo(Path.Combine(Path.GetDirectoryName(file.FullName)!, Path.GetFileNameWithoutExtension(file.FullName)) + ".pdb"); if (symbolsFile.Exists) - this.SymbolReaderProvider.TryAddSymbolData(file.Name, this.TrackForDisposal(symbolsFile.OpenRead())); + this.SymbolReaderProvider.TryAddSymbolData(file.Name, () => this.TrackForDisposal(symbolsFile.OpenRead())); } AssemblyDefinition assembly = this.TrackForDisposal(AssemblyDefinition.ReadAssembly(readStream, new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = assemblyResolver, InMemory = true, ReadSymbols = true, SymbolReaderProvider = this.SymbolReaderProvider })); diff --git a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs index 02a70f1c..1b160690 100644 --- a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs +++ b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs @@ -24,10 +24,11 @@ namespace StardewModdingAPI.Framework.ModLoading.Symbols *********/ /// Add the symbol file for a given assembly name, if it's not already registered. /// The assembly file name. - /// The raw file stream for the symbols. - public void AddSymbolData(string fileName, Stream symbolStream) + /// Get the raw file stream for the symbols. + public void TryAddSymbolData(string fileName, Func getSymbolStream) { - this.SymbolsByAssemblyPath.Add(fileName, symbolStream); + if (!this.SymbolsByAssemblyPath.ContainsKey(fileName)) + this.SymbolsByAssemblyPath.Add(fileName, getSymbolStream()); } /// Get a symbol reader for a given module and assembly name. -- cgit From 11ecd578e960379db609cae5f9922df11ae79820 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 25 Aug 2021 20:03:06 -0400 Subject: fix error when no symbols are found --- src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs index 1b160690..44074337 100644 --- a/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs +++ b/src/SMAPI/Framework/ModLoading/Symbols/SymbolReaderProvider.cs @@ -13,7 +13,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Symbols ** Fields *********/ /// The underlying symbol reader provider. - private readonly ISymbolReaderProvider BaseProvider = new DefaultSymbolReaderProvider(); + private readonly ISymbolReaderProvider BaseProvider = new DefaultSymbolReaderProvider(throwIfNoSymbol: false); /// The symbol data loaded by absolute assembly path. private readonly Dictionary SymbolsByAssemblyPath = new Dictionary(StringComparer.OrdinalIgnoreCase); -- cgit