Adding the missing documentation on every classes and methods

This commit is contained in:
Zoe Roux 2021-10-07 21:48:40 +02:00
parent 6ee5f3ef24
commit fd50a2dedc
18 changed files with 159 additions and 47 deletions

View File

@ -45,7 +45,6 @@
<PropertyGroup Condition="$(CheckCodingStyle) == true"> <PropertyGroup Condition="$(CheckCodingStyle) == true">
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>CS1591;SA1600;SA1601</NoWarn>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)../Kyoo.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)../Kyoo.ruleset</CodeAnalysisRuleSet>
<!-- <AnalysisMode>AllEnabledByDefault</AnalysisMode>--> <!-- <AnalysisMode>AllEnabledByDefault</AnalysisMode>-->

View File

@ -105,9 +105,17 @@ namespace Kyoo.Abstractions.Models
return CreateReference(path, typeof(T)); return CreateReference(path, typeof(T));
} }
/// <summary>
/// Return a <see cref="ConfigurationReference"/> meaning that the given path is of any type.
/// It means that the type can't be edited.
/// </summary>
/// <param name="path">
/// The path that will be untyped (separated by ':' or "__". If empty, it will start at root).
/// </param>
/// <returns>A configuration reference representing a path of any type.</returns>
public static ConfigurationReference CreateUntyped(string path) public static ConfigurationReference CreateUntyped(string path)
{ {
return new(path, null); return new ConfigurationReference(path, null);
} }
} }
} }

View File

@ -425,6 +425,11 @@ namespace Kyoo.Utils
return (T)method.MakeGenericMethod(types).Invoke(instance, args.ToArray()); return (T)method.MakeGenericMethod(types).Invoke(instance, args.ToArray());
} }
/// <summary>
/// Convert a dictionary to a query string.
/// </summary>
/// <param name="query">The list of query parameters.</param>
/// <returns>A valid query string with all items in the dictionary.</returns>
public static string ToQueryString(this Dictionary<string, string> query) public static string ToQueryString(this Dictionary<string, string> query)
{ {
if (!query.Any()) if (!query.Any())
@ -432,6 +437,11 @@ namespace Kyoo.Utils
return "?" + string.Join('&', query.Select(x => $"{x.Key}={x.Value}")); return "?" + string.Join('&', query.Select(x => $"{x.Key}={x.Value}"));
} }
/// <summary>
/// Rethrow the exception without modifying the stack trace.
/// This is similar to the <c>rethrow;</c> code but is useful when the exception is not in a catch block.
/// </summary>
/// <param name="ex">The exception to rethrow.</param>
[System.Diagnostics.CodeAnalysis.DoesNotReturn] [System.Diagnostics.CodeAnalysis.DoesNotReturn]
public static void ReThrow([NotNull] this Exception ex) public static void ReThrow([NotNull] this Exception ex)
{ {

View File

@ -23,6 +23,9 @@ using IdentityModel;
namespace Kyoo.Authentication namespace Kyoo.Authentication
{ {
/// <summary>
/// Some functions to handle password management.
/// </summary>
public static class PasswordUtils public static class PasswordUtils
{ {
/// <summary> /// <summary>

View File

@ -32,6 +32,11 @@ using Newtonsoft.Json.Linq;
namespace Kyoo.Core.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary>
/// A class to ease configuration management. This work WITH Microsoft's package, you can still use IOptions patterns
/// to access your options, this manager ease dynamic work and editing.
/// It works with <see cref="ConfigurationReference"/>.
/// </summary>
public class ConfigurationManager : IConfigurationManager public class ConfigurationManager : IConfigurationManager
{ {
/// <summary> /// <summary>

View File

@ -165,11 +165,13 @@ namespace Kyoo.Core.Controllers
}); });
} }
/// <inheritdoc />
public Task<ICollection<Track>> ExtractInfos(Episode episode, bool reExtract) public Task<ICollection<Track>> ExtractInfos(Episode episode, bool reExtract)
{ {
return _transcoder.ExtractInfos(episode, reExtract); return _transcoder.ExtractInfos(episode, reExtract);
} }
/// <inheritdoc />
public IActionResult Transmux(Episode episode) public IActionResult Transmux(Episode episode)
{ {
return _transcoder.Transmux(episode); return _transcoder.Transmux(episode);

View File

@ -29,6 +29,9 @@ using Kyoo.Utils;
namespace Kyoo.Core.Controllers namespace Kyoo.Core.Controllers
{ {
/// <summary>
/// An class to interact with the database. Every repository is mapped through here.
/// </summary>
public class LibraryManager : ILibraryManager public class LibraryManager : ILibraryManager
{ {
/// <summary> /// <summary>

View File

@ -29,6 +29,10 @@ namespace Kyoo.Core.Controllers
/// </summary> /// </summary>
public class PassthroughPermissionValidator : IPermissionValidator public class PassthroughPermissionValidator : IPermissionValidator
{ {
/// <summary>
/// Create a new <see cref="PassthroughPermissionValidator"/>.
/// </summary>
/// <param name="logger">The logger used to warn that no real permission validator exists.</param>
[SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor", [SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor",
Justification = "ILogger should include the typeparam for context.")] Justification = "ILogger should include the typeparam for context.")]
public PassthroughPermissionValidator(ILogger<PassthroughPermissionValidator> logger) public PassthroughPermissionValidator(ILogger<PassthroughPermissionValidator> logger)

View File

@ -22,6 +22,9 @@ using Newtonsoft.Json;
namespace Kyoo.Core namespace Kyoo.Core
{ {
/// <summary>
/// A class containing helper methods.
/// </summary>
public static class Helper public static class Helper
{ {
/// <summary> /// <summary>

View File

@ -22,24 +22,53 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using JetBrains.Annotations;
using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models;
namespace Kyoo.Core.Api namespace Kyoo.Core.Api
{ {
/// <summary>
/// A static class containing methods to parse the <c>where</c> query string.
/// </summary>
public static class ApiHelper public static class ApiHelper
{ {
public static Expression StringCompatibleExpression(Func<Expression, Expression, BinaryExpression> operand, /// <summary>
Expression left, /// Make an expression (like
Expression right) /// <see cref="Expression.LessThan(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)"/>
{ /// compatible with strings). If the expressions are not strings, the given <paramref name="operand"/> is
if (left is MemberExpression member && ((PropertyInfo)member.Member).PropertyType == typeof(string)) /// constructed but if the expressions are strings, this method make the <param name="operand"/> compatible with
/// strings.
/// </summary>
/// <param name="operand">
/// The expression to make compatible. It should be something like
/// <see cref="Expression.LessThan(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)"/> or
/// <see cref="Expression.Equal(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)"/>.
/// </param>
/// <param name="left">The first parameter to compare.</param>
/// <param name="right">The second parameter to compare.</param>
/// <returns>A comparison expression compatible with strings</returns>
public static BinaryExpression StringCompatibleExpression(
[NotNull] Func<Expression, Expression, BinaryExpression> operand,
[NotNull] Expression left,
[NotNull] Expression right)
{ {
if (left is not MemberExpression member || ((PropertyInfo)member.Member).PropertyType != typeof(string))
return operand(left, right);
MethodCallExpression call = Expression.Call(typeof(string), "Compare", null, left, right); MethodCallExpression call = Expression.Call(typeof(string), "Compare", null, left, right);
return operand(call, Expression.Constant(0)); return operand(call, Expression.Constant(0));
} }
return operand(left, right);
}
/// <summary>
/// Parse a <c>where</c> query for the given <typeparamref name="T"/>. Items can be filtered by any property
/// of the given type.
/// </summary>
/// <param name="where">The list of filters.</param>
/// <param name="defaultWhere">
/// A custom expression to initially filter a collection. It will be combined with the parsed expression.
/// </param>
/// <typeparam name="T">The type to create filters for.</typeparam>
/// <exception cref="ArgumentException">A filter is invalid.</exception>
/// <returns>An expression representing the filters that can be used anywhere or compiled</returns>
public static Expression<Func<T, bool>> ParseWhere<T>(Dictionary<string, string> where, public static Expression<Func<T, bool>> ParseWhere<T>(Dictionary<string, string> where,
Expression<Func<T, bool>> defaultWhere = null) Expression<Func<T, bool>> defaultWhere = null)
{ {
@ -96,18 +125,17 @@ namespace Kyoo.Core.Api
"not" when valueExpr == null => _ResourceEqual(propertyExpr, value, true), "not" when valueExpr == null => _ResourceEqual(propertyExpr, value, true),
"eq" => Expression.Equal(propertyExpr, valueExpr), "eq" => Expression.Equal(propertyExpr, valueExpr),
"not" => Expression.NotEqual(propertyExpr, valueExpr!), "not" => Expression.NotEqual(propertyExpr, valueExpr),
"lt" => StringCompatibleExpression(Expression.LessThan, propertyExpr, valueExpr), "lt" => StringCompatibleExpression(Expression.LessThan, propertyExpr, valueExpr!),
"lte" => StringCompatibleExpression(Expression.LessThanOrEqual, propertyExpr, valueExpr), "lte" => StringCompatibleExpression(Expression.LessThanOrEqual, propertyExpr, valueExpr!),
"gt" => StringCompatibleExpression(Expression.GreaterThan, propertyExpr, valueExpr), "gt" => StringCompatibleExpression(Expression.GreaterThan, propertyExpr, valueExpr!),
"gte" => StringCompatibleExpression(Expression.GreaterThanOrEqual, propertyExpr, valueExpr), "gte" => StringCompatibleExpression(Expression.GreaterThanOrEqual, propertyExpr, valueExpr!),
_ => throw new ArgumentException($"Invalid operand: {operand}") _ => throw new ArgumentException($"Invalid operand: {operand}")
}; };
if (expression != null) expression = expression != null
expression = Expression.AndAlso(expression, condition); ? Expression.AndAlso(expression, condition)
else : condition;
expression = condition;
} }
return Expression.Lambda<Func<T, bool>>(expression!, param); return Expression.Lambda<Func<T, bool>>(expression!, param);

View File

@ -27,7 +27,10 @@ using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Core.Api namespace Kyoo.Core.Api
{ {
public class BaseApi : ControllerBase /// <summary>
/// A common API containing custom methods to help inheritors.
/// </summary>
public abstract class BaseApi : ControllerBase
{ {
/// <summary> /// <summary>
/// Construct and return a page from an api. /// Construct and return a page from an api.

View File

@ -32,8 +32,13 @@ using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Core.Api namespace Kyoo.Core.Api
{ {
/// <summary>
/// An attribute to put on most controllers. It handle fields loading (only retuning fields requested and if they
/// are requested, load them) and help for the <c>where</c> query parameter.
/// </summary>
public class ResourceViewAttribute : ActionFilterAttribute public class ResourceViewAttribute : ActionFilterAttribute
{ {
/// <inheritdoc />
public override void OnActionExecuting(ActionExecutingContext context) public override void OnActionExecuting(ActionExecutingContext context)
{ {
if (context.ActionArguments.TryGetValue("where", out object dic) && dic is Dictionary<string, string> where) if (context.ActionArguments.TryGetValue("where", out object dic) && dic is Dictionary<string, string> where)
@ -92,6 +97,7 @@ namespace Kyoo.Core.Api
base.OnActionExecuting(context); base.OnActionExecuting(context);
} }
/// <inheritdoc />
public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{ {
if (context.Result is ObjectResult result) if (context.Result is ObjectResult result)

View File

@ -24,8 +24,13 @@ using Newtonsoft.Json.Linq;
namespace Kyoo.Core.Api namespace Kyoo.Core.Api
{ {
/// <summary>
/// A custom role's convertor to inline the person or the show depending on the value of
/// <see cref="PeopleRole.ForPeople"/>.
/// </summary>
public class PeopleRoleConverter : JsonConverter<PeopleRole> public class PeopleRoleConverter : JsonConverter<PeopleRole>
{ {
/// <inheritdoc />
public override void WriteJson(JsonWriter writer, PeopleRole value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, PeopleRole value, JsonSerializer serializer)
{ {
ICollection<PeopleRole> oldPeople = value.Show?.People; ICollection<PeopleRole> oldPeople = value.Show?.People;
@ -46,6 +51,7 @@ namespace Kyoo.Core.Api
value.People.Roles = oldRoles; value.People.Roles = oldRoles;
} }
/// <inheritdoc />
public override PeopleRole ReadJson(JsonReader reader, public override PeopleRole ReadJson(JsonReader reader,
Type objectType, Type objectType,
PeopleRole existingValue, PeopleRole existingValue,

View File

@ -41,9 +41,21 @@ namespace Kyoo.Core.Api
[ApiDefinition("Videos", Group = WatchGroup)] [ApiDefinition("Videos", Group = WatchGroup)]
public class VideoApi : Controller public class VideoApi : Controller
{ {
/// <summary>
/// The library manager used to modify or retrieve information in the data store.
/// </summary>
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
/// <summary>
/// The file system used to send video files.
/// </summary>
private readonly IFileSystem _files; private readonly IFileSystem _files;
/// <summary>
/// Create a new <see cref="VideoApi"/>.
/// </summary>
/// <param name="libraryManager">The library manager used to retrieve episodes.</param>
/// <param name="files">The file manager used to send video files.</param>
public VideoApi(ILibraryManager libraryManager, public VideoApi(ILibraryManager libraryManager,
IFileSystem files) IFileSystem files)
{ {

View File

@ -24,8 +24,12 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Kyoo.Postgresql.Migrations namespace Kyoo.Postgresql.Migrations
{ {
/// <summary>
/// The initial migration that build most of the database.
/// </summary>
public partial class Initial : Migration public partial class Initial : Migration
{ {
/// <inheritdoc/>
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.AlterDatabase() migrationBuilder.AlterDatabase()
@ -783,6 +787,7 @@ namespace Kyoo.Postgresql.Migrations
column: "episode_id"); column: "episode_id");
} }
/// <inheritdoc/>
protected override void Down(MigrationBuilder migrationBuilder) protected override void Down(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.DropTable( migrationBuilder.DropTable(

View File

@ -20,8 +20,12 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace Kyoo.Postgresql.Migrations namespace Kyoo.Postgresql.Migrations
{ {
/// <summary>
/// A migration that adds postgres triggers to update slugs.
/// </summary>
public partial class Triggers : Migration public partial class Triggers : Migration
{ {
/// <inheritdoc/>
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
// language=PostgreSQL // language=PostgreSQL
@ -172,6 +176,7 @@ namespace Kyoo.Postgresql.Migrations
FROM collections AS c0"); FROM collections AS c0");
} }
/// <inheritdoc/>
protected override void Down(MigrationBuilder migrationBuilder) protected override void Down(MigrationBuilder migrationBuilder)
{ {
// language=PostgreSQL // language=PostgreSQL

View File

@ -21,8 +21,12 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace Kyoo.SqLite.Migrations namespace Kyoo.SqLite.Migrations
{ {
/// <summary>
/// The initial migration that build most of the database.
/// </summary>
public partial class Initial : Migration public partial class Initial : Migration
{ {
/// <inheritdoc/>
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
@ -775,6 +779,7 @@ namespace Kyoo.SqLite.Migrations
column: "EpisodeID"); column: "EpisodeID");
} }
/// <inheritdoc/>
protected override void Down(MigrationBuilder migrationBuilder) protected override void Down(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.DropTable( migrationBuilder.DropTable(

View File

@ -20,8 +20,12 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace Kyoo.SqLite.Migrations namespace Kyoo.SqLite.Migrations
{ {
/// <summary>
/// A migration that adds sqlite triggers to update slugs.
/// </summary>
public partial class Triggers : Migration public partial class Triggers : Migration
{ {
/// <inheritdoc/>
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
// language=SQLite // language=SQLite
@ -186,6 +190,7 @@ namespace Kyoo.SqLite.Migrations
FROM collections AS c0"); FROM collections AS c0");
} }
/// <inheritdoc/>
protected override void Down(MigrationBuilder migrationBuilder) protected override void Down(MigrationBuilder migrationBuilder)
{ {
// language=SQLite // language=SQLite