Skip to content

Commit

Permalink
Xml comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikasoukhov committed Feb 18, 2025
1 parent 54a674d commit 7254e82
Show file tree
Hide file tree
Showing 17 changed files with 463 additions and 13 deletions.
14 changes: 14 additions & 0 deletions Compilation/AssemblyLoadContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

using Ecng.Common;

/// <summary>
/// Provides extension methods for AssemblyLoadContext related to compilation operations.
/// </summary>
public static class AssemblyLoadContextExtensions
{
private class AssemblyLoadContextWrapper(AssemblyLoadContext context) : Disposable, ICompilerContext
Expand All @@ -24,9 +27,20 @@ protected override void DisposeManaged()
}
}

/// <summary>
/// Loads an assembly from the provided binary data using a memory stream.
/// </summary>
/// <param name="visitor">The AssemblyLoadContext instance to load the assembly.</param>
/// <param name="assembly">The byte array containing the assembly binary.</param>
/// <returns>The loaded Assembly.</returns>
public static Assembly LoadFromBinary(this AssemblyLoadContext visitor, byte[] assembly)
=> visitor.CheckOnNull(nameof(visitor)).LoadFromStream(assembly.To<Stream>());

/// <summary>
/// Wraps the specified AssemblyLoadContext into an ICompilerContext so that the context can be used for loading assemblies.
/// </summary>
/// <param name="context">The AssemblyLoadContext instance to wrap.</param>
/// <returns>An ICompilerContext that uses the specified AssemblyLoadContext.</returns>
public static ICompilerContext ToContext(this AssemblyLoadContext context)
=> new AssemblyLoadContextWrapper(context);
}
14 changes: 14 additions & 0 deletions Compilation/AssemblyLoadContextTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,23 @@

using Ecng.Common;

/// <summary>
/// Provides tracking functionality for AssemblyLoadContext instances when loading assemblies dynamically.
/// Implements ICompilerContext and manages unloading of previous contexts when loading a new assembly.
/// </summary>
public class AssemblyLoadContextTracker(Action<Exception> uploadingError = default) : Disposable, ICompilerContext
{
private readonly SyncObject _lock = new();
private readonly Action<Exception> _uploadingError = uploadingError;
private AssemblyLoadContext _context;
private byte[] _assembly;

/// <summary>
/// Loads an assembly from the provided binary data.
/// If a different assembly is passed than the one previously loaded, the previous context is unloaded.
/// </summary>
/// <param name="assembly">The binary representation of the assembly to load.</param>
/// <returns>The loaded <see cref="Assembly"/> instance.</returns>
public Assembly LoadFromBinary(byte[] assembly)
{
void init()
Expand Down Expand Up @@ -51,6 +61,9 @@ void init()
return _context.LoadFromBinary(assembly);
}

/// <summary>
/// Unloads the current AssemblyLoadContext and resets the internal state.
/// </summary>
public void Unload()
{
lock (_lock)
Expand All @@ -64,6 +77,7 @@ public void Unload()
}
}

/// <inheritdoc />
protected override void DisposeManaged()
{
base.DisposeManaged();
Expand Down
13 changes: 13 additions & 0 deletions Compilation/AssemblyReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,19 @@ public AssemblyReference()
{
}

/// <summary>
/// Gets the display name of the assembly reference.
/// </summary>
public override string Name => Path.GetFileNameWithoutExtension(FileName);

/// <summary>
/// Determines whether the assembly reference is valid.
/// </summary>
public override bool IsValid => File.Exists(Location);

/// <summary>
/// Gets or sets the file name of the assembly reference.
/// </summary>
public string FileName { get; set; }

/// <summary>
Expand Down Expand Up @@ -51,16 +61,19 @@ public override string Location
}
}

/// <inheritdoc />
public override void Load(SettingsStorage storage)
{
FileName = storage.GetValue<string>(nameof(FileName)) ?? storage.GetValue<string>(nameof(Location));
}

/// <inheritdoc />
public override void Save(SettingsStorage storage)
{
storage.SetValue(nameof(FileName), FileName);
}

/// <inheritdoc />
public override ValueTask<IEnumerable<(string name, byte[] body)>> GetImages(CancellationToken cancellationToken)
{
return new([Location.ToRef()]);
Expand Down
26 changes: 26 additions & 0 deletions Compilation/CompilationError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,41 @@ namespace Ecng.Compilation;

using Ecng.Common;

/// <summary>
/// Represents a compilation error with details about its location and type.
/// </summary>
public class CompilationError : Equatable<CompilationError>
{
/// <summary>
/// Gets or sets the identifier of the compilation error.
/// </summary>
public string Id { get; set; }

/// <summary>
/// Gets or sets the line number where the error occurred.
/// </summary>
public int Line { get; set; }

/// <summary>
/// Gets or sets the character position where the error occurred.
/// </summary>
public int Character { get; set; }

/// <summary>
/// Gets or sets the message that describes the error.
/// </summary>
public string Message { get; set; }

/// <summary>
/// Gets or sets the type of the compilation error.
/// </summary>
public CompilationErrorTypes Type { get; set; }

/// <inheritdoc />
public override string ToString()
=> $"{Type} ({Id}) {Message} ({Line}-{Character})";

/// <inheritdoc />
public override CompilationError Clone()
=> new()
{
Expand All @@ -23,6 +47,7 @@ public override CompilationError Clone()
Line = Line
};

/// <inheritdoc />
protected override bool OnEquals(CompilationError other)
=>
Id == other.Id &&
Expand All @@ -31,6 +56,7 @@ protected override bool OnEquals(CompilationError other)
Message == other.Message &&
Type == other.Type;

/// <inheritdoc />
public override int GetHashCode()
=> (Id?.GetHashCode() ?? 0) ^ Line.GetHashCode() ^ Character.GetHashCode() ^ (Message?.GetHashCode() ?? 0) ^ Type.GetHashCode();
}
14 changes: 14 additions & 0 deletions Compilation/CompilationErrorTypes.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
namespace Ecng.Compilation
{
/// <summary>
/// Represents the type of a compilation error.
/// </summary>
public enum CompilationErrorTypes
{
/// <summary>
/// Represents an informational message.
/// </summary>
Info,

/// <summary>
/// Represents a warning message.
/// </summary>
Warning,

/// <summary>
/// Represents an error message.
/// </summary>
Error,
}
}
22 changes: 22 additions & 0 deletions Compilation/CompilationResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,40 @@ namespace Ecng.Compilation;
using System.Linq;
using System.Reflection;

/// <summary>
/// Represents the result of a compilation process including any compilation errors.
/// </summary>
/// <param name="errors">A collection of compilation errors.</param>
public abstract class CompilationResult(IEnumerable<CompilationError> errors)
{
/// <summary>
/// Gets the collection of compilation errors.
/// </summary>
public IEnumerable<CompilationError> Errors { get; } = errors.ToArray();

/// <summary>
/// Loads the compiled assembly using the provided compiler context.
/// </summary>
/// <param name="context">The compiler context used to load the assembly.</param>
/// <returns>The loaded assembly, or null if the assembly body is not available.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="context"/> is null.</exception>
public abstract Assembly GetAssembly(ICompilerContext context);
}

/// <summary>
/// Represents a compilation result that includes a binary representation of an assembly.
/// </summary>
/// <param name="errors">A collection of compilation errors.</param>
/// <param name="assemblyBody">The binary content of the compiled assembly.</param>
public class AssemblyCompilationResult(IEnumerable<CompilationError> errors, byte[] assemblyBody = null)
: CompilationResult(errors)
{
/// <summary>
/// Gets the binary content of the compiled assembly.
/// </summary>
public byte[] AssemblyBody { get; } = assemblyBody;

/// <inheritdoc />
public override Assembly GetAssembly(ICompilerContext context)
{
if (context is null)
Expand Down
6 changes: 6 additions & 0 deletions Compilation/CompilerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@

using Ecng.Collections;

/// <summary>
/// Represents a provider for compilers.
/// </summary>
public class CompilerProvider : SynchronizedDictionary<string, ICompiler>
{
/// <summary>
/// Initializes a new instance of the <see cref="CompilerProvider"/> class.
/// </summary>
public CompilerProvider()
: base(StringComparer.InvariantCultureIgnoreCase)
{
Expand Down
58 changes: 58 additions & 0 deletions Compilation/ICodeReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,86 @@

using Ecng.Serialization;

/// <summary>
/// Represents a reference to code that supports persistence.
/// </summary>
public interface ICodeReference : IPersistable
{
/// <summary>
/// Gets the identifier of the code reference.
/// </summary>
string Id { get; }

/// <summary>
/// Gets the name of the code reference.
/// </summary>
string Name { get; }

/// <summary>
/// Gets the location of the code reference.
/// </summary>
string Location { get; }

/// <summary>
/// Gets a value indicating whether the code reference is valid.
/// </summary>
bool IsValid { get; }

/// <summary>
/// Asynchronously retrieves the images associated with the code reference.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains an enumerable of tuples with image name and image body.</returns>
ValueTask<IEnumerable<(string name, byte[] body)>> GetImages(CancellationToken cancellationToken);
}

/// <summary>
/// Provides a base implementation for a code reference with persistence support.
/// </summary>
public abstract class BaseCodeReference : ICodeReference
{
/// <summary>
/// Gets the identifier of the code reference. Defaults to the location.
/// </summary>
public virtual string Id => Location;

/// <summary>
/// Gets the name of the code reference.
/// </summary>
public abstract string Name { get; }

/// <summary>
/// Gets the location of the code reference.
/// </summary>
public abstract string Location { get; }

/// <summary>
/// Gets a value indicating whether the code reference is valid.
/// </summary>
public abstract bool IsValid { get; }

/// <summary>
/// Loads the settings from the specified storage.
/// </summary>
/// <param name="storage">The storage containing the settings.</param>
public abstract void Load(SettingsStorage storage);

/// <summary>
/// Saves the settings to the specified storage.
/// </summary>
/// <param name="storage">The storage where the settings will be saved.</param>
public abstract void Save(SettingsStorage storage);

/// <summary>
/// Returns a string that represents the current code reference.
/// </summary>
/// <returns>The location of the code reference.</returns>
public override string ToString() => Location;

/// <summary>
/// Asynchronously retrieves the images associated with the code reference.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains an enumerable of tuples with image name and image body.</returns>
public abstract ValueTask<IEnumerable<(string name, byte[] body)>> GetImages(CancellationToken cancellationToken);
}
Loading

0 comments on commit 7254e82

Please sign in to comment.