Skip to content

Commit c3d530f

Browse files
Update compilation errors logic in order to support multiple errors
1 parent 64bfa69 commit c3d530f

7 files changed

Lines changed: 33 additions & 34 deletions

File tree

src/CSharpPlugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ public override void HandleAddedToManager(PluginManager manager)
343343
catch (Exception ex)
344344
{
345345
Interface.Oxide.LogException($"Failed to initialize plugin '{Name} v{Version}'", ex);
346-
Loader.PluginErrors[Name] = ex.Message;
346+
Loader.GetPluginErrors(Name).Add(ex.Message);
347347
}
348348
}
349349

src/CSharpPluginLoader.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ public void Load(CompilablePlugin plugin)
209209
{
210210
string sentence = missingRequirements.ToSentence();
211211
Interface.Oxide.LogError($"{plugin.Name} plugin requires missing dependencies: {sentence}");
212-
PluginErrors[plugin.Name] = $"Missing dependencies: {sentence}";
212+
GetPluginErrors(plugin.Name).Add($"Missing dependencies: {sentence}");
213213
PluginLoadingCompleted(plugin);
214214
}
215215
}
@@ -287,31 +287,33 @@ private void CompileAssembly(CompilablePlugin[] plugins)
287287
foreach (CompilablePlugin plugin in compilation.plugins)
288288
{
289289
plugin.OnCompilationFailed();
290-
PluginErrors[plugin.Name] = $"Failed to compile: {plugin.CompilerErrors}";
291-
Interface.Oxide.LogError($"Error while compiling {plugin.ScriptName}: {plugin.CompilerErrors}");
290+
string errors = plugin.CompilerErrors.JoinValues(Environment.NewLine);
291+
GetPluginErrors(plugin.Name).Add($"Failed to compile: {errors}"); // todo: 2 messages are added when compiling fails
292+
Interface.Oxide.LogError($"Error while compiling {plugin.ScriptName}: {errors}");
292293
}
293294
}
294295
else
295296
{
296297
if (compilation.plugins.Count > 0)
297298
{
298-
string[] compiledNames = compilation.plugins.Where(pl => string.IsNullOrEmpty(pl.CompilerErrors)).Select(pl => pl.Name).ToArray();
299+
string[] compiledNames = compilation.plugins.Where(pl => pl.CompilerErrors.Count == 0).Select(pl => pl.Name).ToArray();
299300
string verb = compiledNames.Length > 1 ? "were" : "was";
300301
Interface.Oxide.LogInfo($"{compiledNames.ToSentence()} {verb} compiled successfully in {Math.Round(compilation.duration * 1000f)}ms");
301302
}
302303

303304
foreach (CompilablePlugin plugin in compilation.plugins)
304305
{
305-
if (plugin.CompilerErrors == null)
306+
if (plugin.CompilerErrors.Count == 0)
306307
{
307308
Interface.Oxide.UnloadPlugin(plugin.Name);
308309
plugin.OnCompilationSucceeded(compilation.compiledAssembly);
309310
}
310311
else
311312
{
312313
plugin.OnCompilationFailed();
313-
PluginErrors[plugin.Name] = $"Failed to compile: {plugin.CompilerErrors}";
314-
Interface.Oxide.LogError($"Error while compiling {plugin.ScriptName}: {plugin.CompilerErrors}");
314+
string errors = plugin.CompilerErrors.JoinValues(Environment.NewLine);
315+
GetPluginErrors(plugin.Name).Add($"Failed to compile: {errors}");
316+
Interface.Oxide.LogError($"Error while compiling {plugin.ScriptName}: {errors}");
315317
}
316318
}
317319
}

src/CompilableFile.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class CompilableFile
2424
public HashSet<string> Requires = new HashSet<string>();
2525
public HashSet<string> References = new HashSet<string>();
2626
public HashSet<string> IncludePaths = new HashSet<string>();
27-
public string CompilerErrors;
27+
public readonly HashSet<string> CompilerErrors;
2828
public CompiledAssembly CompiledAssembly;
2929
public DateTime LastModifiedAt;
3030
public DateTime LastCachedScriptAt;
@@ -47,6 +47,7 @@ public CompilableFile(CSharpExtension extension, CSharpPluginLoader loader, stri
4747
ScriptName = name;
4848
ScriptPath = Path.Combine(Directory, $"{ScriptName}.cs");
4949
Name = Regex.Replace(ScriptName, "_", "");
50+
CompilerErrors = new HashSet<string>();
5051
CheckLastModificationTime();
5152
}
5253

@@ -124,7 +125,7 @@ internal void OnCompilationFailed()
124125
internal void OnCompilationTimeout()
125126
{
126127
Interface.Oxide.LogError("Timed out waiting for plugin to be compiled: " + Name);
127-
CompilerErrors = "Timed out waiting for compilation";
128+
CompilerErrors.Add("Timed out waiting for compilation");
128129
OnCompilationFailed();
129130
}
130131

src/CompilablePlugin.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ internal void LoadPlugin(Action<CSharpPlugin> callback = null)
3838
return;
3939
}
4040

41-
if (CompilerErrors != null)
41+
if (CompilerErrors.Count > 0)
4242
{
43-
InitFailed($"Unable to load {ScriptName}. {CompilerErrors}");
43+
InitFailed($"Unable to load {ScriptName}. {CompilerErrors.JoinValues(Environment.NewLine)}");
4444
return;
4545
}
4646

@@ -148,7 +148,7 @@ protected override void InitFailed(string message = null)
148148
}
149149
Interface.Oxide.LogInfo("Rolling back plugin to last good version: {0}", ScriptName);
150150
CompiledAssembly = LastGoodAssembly;
151-
CompilerErrors = null;
151+
CompilerErrors.Clear();
152152
LoadPlugin();
153153
}
154154
}

src/Compilation.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ internal Compilation(int id, Action<Compilation> callback, CompilablePlugin[] pl
4545

4646
foreach (CompilablePlugin plugin in plugins)
4747
{
48-
plugin.CompilerErrors = null;
48+
plugin.CompilerErrors.Clear();
4949
plugin.OnCompilationStarted();
5050
}
5151

@@ -77,7 +77,7 @@ internal void Add(CompilablePlugin plugin)
7777
}
7878

7979
plugin.Loader.PluginLoadingStarted(plugin);
80-
plugin.CompilerErrors = null;
80+
plugin.CompilerErrors.Clear();
8181
plugin.OnCompilationStarted();
8282

8383
foreach (Core.Plugins.Plugin pl in Interface.Oxide.RootPluginManager.GetPlugins().Where(pl => pl is CSharpPlugin))
@@ -100,7 +100,7 @@ internal bool IncludesRequiredPlugin(string name)
100100
}
101101

102102
CompilablePlugin compilablePlugin = plugins.SingleOrDefault(pl => pl.Name == name);
103-
return compilablePlugin != null && compilablePlugin.CompilerErrors == null;
103+
return compilablePlugin is { CompilerErrors.Count: 0 };
104104
}
105105

106106
internal void Prepare(Action callback)
@@ -221,7 +221,7 @@ private void PreparseScript(CompilablePlugin plugin)
221221
if (line.IndexOf("namespace uMod.Plugins", StringComparison.InvariantCultureIgnoreCase) >= 0)
222222
{
223223
Interface.Oxide.LogError($"Plugin {plugin.ScriptName}.cs is a uMod plugin, not an Oxide plugin. Please downgrade to the Oxide version if available.");
224-
plugin.CompilerErrors = $"Plugin {plugin.ScriptName}.cs is a uMod plugin, not an Oxide plugin. Please downgrade to the Oxide version if available.";
224+
plugin.CompilerErrors.Add($"Plugin {plugin.ScriptName}.cs is a uMod plugin, not an Oxide plugin. Please downgrade to the Oxide version if available.");
225225
RemovePlugin(plugin);
226226
return;
227227
}
@@ -259,7 +259,7 @@ private void PreparseScript(CompilablePlugin plugin)
259259
if (className != plugin.Name)
260260
{
261261
Interface.Oxide.LogError($"Plugin filename {plugin.ScriptName}.cs must match the main class {className} (should be {className}.cs)");
262-
plugin.CompilerErrors = $"Plugin filename {plugin.ScriptName}.cs must match the main class {className} (should be {className}.cs)";
262+
plugin.CompilerErrors.Add($"Plugin filename {plugin.ScriptName}.cs must match the main class {className} (should be {className}.cs)");
263263
RemovePlugin(plugin);
264264
}
265265

@@ -275,7 +275,7 @@ private void PreparseScript(CompilablePlugin plugin)
275275
if (!File.Exists(Path.Combine(plugin.Directory, dependencyName + ".cs")))
276276
{
277277
Interface.Oxide.LogError($"{plugin.Name} plugin requires missing dependency: {dependencyName}");
278-
plugin.CompilerErrors = $"Missing dependency: {dependencyName}";
278+
plugin.CompilerErrors.Add($"Missing dependency: {dependencyName}");
279279
RemovePlugin(plugin);
280280
return;
281281
}
@@ -360,7 +360,7 @@ private void ResolveReferences(CompilablePlugin plugin)
360360

361361
string message = $"{fullName} is referenced by {plugin.Name} plugin but is not loaded";
362362
Interface.Oxide.LogError(message);
363-
plugin.CompilerErrors = message;
363+
plugin.CompilerErrors.Add(message);
364364
RemovePlugin(plugin);
365365
}
366366
}
@@ -401,7 +401,7 @@ private void AddReference(CompilablePlugin plugin, string assemblyNameString)
401401
}
402402

403403
Interface.Oxide.LogError($"Assembly referenced by {plugin.Name} plugin does not exist: {assemblyNameString}.dll");
404-
plugin.CompilerErrors = $"Referenced assembly does not exist: {assemblyNameString}";
404+
plugin.CompilerErrors.Add($"Referenced assembly does not exist: {assemblyNameString}");
405405
RemovePlugin(plugin);
406406
return;
407407
}
@@ -414,7 +414,7 @@ private void AddReference(CompilablePlugin plugin, string assemblyNameString)
414414
catch (FileNotFoundException)
415415
{
416416
Interface.Oxide.LogError($"Assembly referenced by {plugin.Name} plugin is invalid: {assemblyNameString}.dll");
417-
plugin.CompilerErrors = $"Referenced assembly is invalid: {assemblyNameString}";
417+
plugin.CompilerErrors.Add($"Referenced assembly is invalid: {assemblyNameString}");
418418
RemovePlugin(plugin);
419419
return;
420420
}
@@ -466,7 +466,7 @@ private bool CacheScriptLines(CompilablePlugin plugin)
466466
if (!File.Exists(plugin.ScriptPath))
467467
{
468468
Interface.Oxide.LogWarning("Script no longer exists: {0}", plugin.Name);
469-
plugin.CompilerErrors = "Plugin file was deleted";
469+
plugin.CompilerErrors.Add("Plugin file was deleted");
470470
RemovePlugin(plugin);
471471
return false;
472472
}

src/CompiledAssembly.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ private void ValidateAssembly(Action<byte[], byte[]> callback)
124124
AssemblyDefinition assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyStream, readerParameters);
125125

126126
int foundPlugins = 0;
127-
int totalPlugins = CompilablePlugins.Count(p => p.CompilerErrors == null);
127+
int totalPlugins = CompilablePlugins.Count(p => p.CompilerErrors.Count == 0);
128128
for (int i = 0; i < assemblyDefinition.MainModule.Types.Count; i++)
129129
{
130130
if (foundPlugins == totalPlugins)
@@ -159,10 +159,7 @@ private void ValidateAssembly(Action<byte[], byte[]> callback)
159159
$"User defined constructors are not supported. Please remove the constructor from {typeDefinition.Name}.cs"); // Should be allowed
160160

161161
CompilablePlugin plugin = CompilablePlugins.SingleOrDefault(p => p.Name == typeDefinition.Name);
162-
if (plugin != null)
163-
{
164-
plugin.CompilerErrors = "Primary constructor in main class must be public";
165-
}
162+
plugin?.CompilerErrors.Add("Primary constructor in main class must be public");
166163
}
167164
else
168165
{

src/CompilerService.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -326,14 +326,13 @@ private void OnMessageReceived(CompilerMessage message)
326326
string[] missingRequirementsArray = missingRequirements.ToArray();
327327
if (missingRequirementsArray.Length > 0)
328328
{
329-
compilablePlugin.CompilerErrors = $"Missing dependencies: {string.Join(",", missingRequirementsArray)}";
329+
compilablePlugin.CompilerErrors.Add($"Missing dependencies: {string.Join(",", missingRequirementsArray)}");
330330

331331
Log(LogType.Error, $"[{error.File}] Missing dependencies: {string.Join(",", missingRequirementsArray)}");
332332
}
333333
else
334334
{
335-
// TODO: Allow multiple errors
336-
compilablePlugin.CompilerErrors = error.Message;
335+
compilablePlugin.CompilerErrors.Add(error.Message);
337336

338337
Log(LogType.Error, $"[{error.File}] {error.Message}");
339338
}
@@ -370,7 +369,7 @@ private void OnMessageReceived(CompilerMessage message)
370369

371370
foreach (CompilablePlugin p in compilation.plugins)
372371
{
373-
p.CompilerErrors = errorMessage;
372+
p.CompilerErrors.Add(errorMessage);
374373
}
375374

376375
compilation.Completed();
@@ -558,7 +557,7 @@ private void EnqueueCompilation(Compilation compilation)
558557
string name = Path.GetFileName(plugin.ScriptPath ?? plugin.ScriptName);
559558
if (plugin.ScriptSource == null || plugin.ScriptSource.Length == 0)
560559
{
561-
plugin.CompilerErrors = "No data contained in .cs file";
560+
plugin.CompilerErrors.Add("No data contained in .cs file");
562561
Log(LogType.Error, $"Ignoring plugin {name}, file is empty");
563562
continue;
564563
}
@@ -629,7 +628,7 @@ private void OnCompilerFailed(string reason)
629628
{
630629
foreach (CompilablePlugin plugin in compilation.plugins)
631630
{
632-
plugin.CompilerErrors = reason;
631+
plugin.CompilerErrors.Add(reason);
633632
}
634633

635634
compilation.Completed();

0 commit comments

Comments
 (0)