Updated to .NET analyzers and fixed warnings

This commit is contained in:
Jonas Dellinger 2020-12-26 18:28:44 +01:00
parent 7659f83122
commit 8dd31420ea
19 changed files with 80 additions and 101 deletions

View File

@ -14,6 +14,10 @@ dotnet_diagnostic.CA1034.severity = none
dotnet_diagnostic.CA1054.severity = none
dotnet_diagnostic.CA2227.severity = none
dotnet_diagnostic.CA1308.severity = none
dotnet_diagnostic.CA1002.severity = none
# TODO: Enable for next major version, EventArgs breaking change:
dotnet_diagnostic.CA1003.severity = none
#
# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = true
dotnet_style_require_accessibility_modifiers = always:warning

View File

@ -0,0 +1,5 @@
using System;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("SpotifyAPI.Web.Tests")]
[assembly: CLSCompliant(true)]

View File

@ -1,20 +0,0 @@
using System.Collections.Generic;
using System;
using System.Threading.Tasks;
using NUnit.Framework;
namespace SpotifyAPI.Web.Tests
{
[TestFixture]
public class NetHTTPClientTest
{
[TestFixture]
public class BuildRequestsMethod
{
public void AddsHeaders()
{
}
}
}
}

View File

@ -11,7 +11,7 @@ namespace SpotifyAPI.Web.Tests
public void ApplyParameters_WithoutExistingParameters()
{
var expected = "http://google.com/?hello=world&nice=day";
Uri uri = new Uri("http://google.com/");
var uri = new Uri("http://google.com/");
var parameters = new Dictionary<string, string>
{
@ -25,7 +25,7 @@ namespace SpotifyAPI.Web.Tests
public void ApplyParameters_WithExistingParameters()
{
var expected = "http://google.com/?existing=paramter&hello=world&nice=day";
Uri uri = new Uri("http://google.com/?existing=paramter");
var uri = new Uri("http://google.com/?existing=paramter");
var parameters = new Dictionary<string, string>
{
@ -39,7 +39,7 @@ namespace SpotifyAPI.Web.Tests
public void ApplyParameters_HandlesEscape()
{
var expected = "http://google.com/?existing=paramter&hello=%26world++";
Uri uri = new Uri("http://google.com/?existing=paramter");
var uri = new Uri("http://google.com/?existing=paramter");
var parameters = new Dictionary<string, string>
{

View File

@ -1,3 +1,5 @@
using System;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("SpotifyAPI.Web.Tests")]
[assembly: CLSCompliant(true)]

View File

@ -4,7 +4,7 @@ namespace SpotifyAPI.Web
{
public abstract class APIClient
{
public APIClient(IAPIConnector apiConnector)
protected APIClient(IAPIConnector apiConnector)
{
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));

View File

@ -49,12 +49,12 @@ namespace SpotifyAPI.Web
return API.Post<FullPlaylist>(URLs.UserPlaylists(userId), null, request.BuildBodyParams());
}
public async Task<bool> UploadCover(string playlistId, string base64Jpg)
public async Task<bool> UploadCover(string playlistId, string base64JpgData)
{
Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId));
Ensure.ArgumentNotNullOrEmptyString(base64Jpg, nameof(base64Jpg));
Ensure.ArgumentNotNullOrEmptyString(base64JpgData, nameof(base64JpgData));
var statusCode = await API.PutRaw(URLs.PlaylistImages(playlistId), null, base64Jpg).ConfigureAwait(false);
var statusCode = await API.PutRaw(URLs.PlaylistImages(playlistId), null, base64JpgData).ConfigureAwait(false);
return statusCode == HttpStatusCode.Accepted;
}

View File

@ -24,7 +24,9 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(config, nameof(config));
if (config.Authenticator == null)
{
throw new NullReferenceException("Authenticator in config is null. Please supply it via `WithAuthenticator` or `WithToken`");
#pragma warning disable CA2208
throw new ArgumentNullException("Authenticator in config is null. Please supply it via `WithAuthenticator` or `WithToken`");
#pragma warning restore CA2208
}
_apiConnector = new APIConnector(

View File

@ -279,15 +279,13 @@ namespace SpotifyAPI.Web.Http
return;
}
switch (response.StatusCode)
throw response.StatusCode switch
{
case HttpStatusCode.Unauthorized:
throw new APIUnauthorizedException(response);
case (HttpStatusCode)429: // TODO: Remove hack once .netstandard 2.0 is not supported
throw new APITooManyRequestsException(response);
default:
throw new APIException(response);
}
HttpStatusCode.Unauthorized => new APIUnauthorizedException(response),
// TODO: Remove hack once .netstandard 2.0 is not supported
(HttpStatusCode)429 => new APITooManyRequestsException(response),
_ => new APIException(response),
};
}
}
}

View File

@ -35,23 +35,20 @@ namespace SpotifyAPI.Web.Http
{
Ensure.ArgumentNotNull(request, nameof(request));
using (HttpRequestMessage requestMsg = BuildRequestMessage(request))
{
using HttpRequestMessage requestMsg = BuildRequestMessage(request);
var responseMsg = await _httpClient
.SendAsync(requestMsg, HttpCompletionOption.ResponseContentRead)
.ConfigureAwait(false);
return await BuildResponse(responseMsg).ConfigureAwait(false);
}
}
private static async Task<IResponse> BuildResponse(HttpResponseMessage responseMsg)
{
Ensure.ArgumentNotNull(responseMsg, nameof(responseMsg));
// We only support text stuff for now
using (var content = responseMsg.Content)
{
using var content = responseMsg.Content;
var headers = responseMsg.Headers.ToDictionary(header => header.Key, header => header.Value.First());
var body = await responseMsg.Content.ReadAsStringAsync().ConfigureAwait(false);
var contentType = content.Headers?.ContentType?.MediaType;
@ -63,7 +60,6 @@ namespace SpotifyAPI.Web.Http
Body = body
};
}
}
private static HttpRequestMessage BuildRequestMessage(IRequest request)
{

View File

@ -16,7 +16,7 @@ namespace SpotifyAPI.Web.Http
if (request.Parameters != null)
{
parameters = string.Join(",",
request.Parameters?.Select(kv => kv.Key + "=" + kv.Value)?.ToArray() ?? Array.Empty<string>()
request.Parameters.Select(kv => kv.Key + "=" + kv.Value)?.ToArray() ?? Array.Empty<string>()
);
}
@ -33,7 +33,7 @@ namespace SpotifyAPI.Web.Http
string? body = response.Body?.ToString()?.Replace("\n", "", StringComparison.InvariantCulture);
#endif
body = body?.Substring(0, Math.Min(50, body?.Length ?? 0));
body = body?.Substring(0, Math.Min(50, body.Length));
Console.WriteLine("--> {0} {1} {2}\n", response.StatusCode, response.ContentType, body);
}
}

View File

@ -36,7 +36,7 @@ namespace SpotifyAPI.Web
}
else
{
throw new Exception($@"Received unkown playlist element type: {type}.
throw new APIException($@"Received unkown playlist element type: {type}.
If you're requesting a subset of available fields via the fields query paramter,
make sure to include at least the type field. Often it's `items(track(type))` or `item(type)`");
}

View File

@ -29,7 +29,7 @@ namespace SpotifyAPI.Web
public Uri ToUri()
{
StringBuilder builder = new StringBuilder(SpotifyUrls.Authorize.ToString());
var builder = new StringBuilder(SpotifyUrls.Authorize.ToString());
builder.Append($"?client_id={ClientId}");
builder.Append($"&response_type={ResponseTypeParam.ToString().ToLower(CultureInfo.InvariantCulture)}");
builder.Append($"&redirect_uri={HttpUtility.UrlEncode(RedirectUri.ToString())}");

View File

@ -11,7 +11,7 @@ namespace SpotifyAPI.Web
public abstract class RequestParams
{
private static readonly ConcurrentDictionary<Type, List<(PropertyInfo, BodyParamAttribute)>> _bodyParamsCache =
new ConcurrentDictionary<Type, List<(PropertyInfo, BodyParamAttribute)>>();
new();
public JObject BuildBodyParams()
{
@ -59,7 +59,7 @@ namespace SpotifyAPI.Web
}
private static readonly ConcurrentDictionary<Type, List<(PropertyInfo, QueryParamAttribute)>> _queryParamsCache =
new ConcurrentDictionary<Type, List<(PropertyInfo, QueryParamAttribute)>>();
new();
public Dictionary<string, string> BuildQueryParams()
{
@ -146,7 +146,7 @@ namespace SpotifyAPI.Web
}
else
{
queryParams.Add(attribute.Key ?? prop.Name, value.ToString() ?? throw new Exception("ToString was null on a value"));
queryParams.Add(attribute.Key ?? prop.Name, value.ToString() ?? throw new APIException("ToString returned null for query parameter"));
}
}
}
@ -156,7 +156,7 @@ namespace SpotifyAPI.Web
}
[AttributeUsage(AttributeTargets.Property)]
public class QueryParamAttribute : Attribute
public sealed class QueryParamAttribute : Attribute
{
public string Key { get; }
@ -167,7 +167,7 @@ namespace SpotifyAPI.Web
}
[AttributeUsage(AttributeTargets.Property)]
public class BodyParamAttribute : Attribute
public sealed class BodyParamAttribute : Attribute
{
public string Key { get; }

View File

@ -35,9 +35,9 @@
<PackageReference Include="Newtonsoft.Json" Version="12.0.3">
<PrivateAssets>None</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
</PropertyGroup>
</Project>

View File

@ -3,13 +3,13 @@ namespace SpotifyAPI.Web
{
public static class SpotifyUrls
{
static private readonly URIParameterFormatProvider _provider = new URIParameterFormatProvider();
static private readonly URIParameterFormatProvider _provider = new();
public static readonly Uri APIV1 = new Uri("https://api.spotify.com/v1/");
public static readonly Uri APIV1 = new("https://api.spotify.com/v1/");
public static readonly Uri Authorize = new Uri("https://accounts.spotify.com/authorize");
public static readonly Uri Authorize = new("https://accounts.spotify.com/authorize");
public static readonly Uri OAuthToken = new Uri("https://accounts.spotify.com/api/token");
public static readonly Uri OAuthToken = new("https://accounts.spotify.com/api/token");
public static Uri Me() => EUri($"me");
@ -125,6 +125,6 @@ namespace SpotifyAPI.Web
public static Uri LibraryShows() => EUri($"me/shows");
private static Uri EUri(FormattableString path) => new Uri(path.ToString(_provider), UriKind.Relative);
private static Uri EUri(FormattableString path) => new(path.ToString(_provider), UriKind.Relative);
}
}

View File

@ -114,21 +114,17 @@ namespace SpotifyAPI.Web
private static int GetNumBase64PaddingCharsToAddForDecode(int inputLength)
{
switch (inputLength % 4)
return (inputLength % 4) switch
{
case 0:
return 0;
case 2:
return 2;
case 3:
return 1;
default:
throw new FormatException(
0 => 0,
2 => 2,
3 => 1,
_ => throw new FormatException(
string.Format(
CultureInfo.CurrentCulture,
WebEncoders_MalformedInput,
inputLength));
}
inputLength)),
};
}
}

View File

@ -52,22 +52,18 @@ namespace SpotifyAPI.Web
private static string GenerateRandomURLSafeString(int length)
{
using (var rng = new RNGCryptoServiceProvider())
{
using var rng = new RNGCryptoServiceProvider();
var bit_count = length * 6;
var byte_count = (bit_count + 7) / 8; // rounded up
var bytes = new byte[byte_count];
rng.GetBytes(bytes);
return Base64Util.UrlEncode(bytes);
}
}
private static byte[] ComputeSHA256(string value)
{
using (var hash = SHA256.Create())
{
using var hash = SHA256.Create();
return hash.ComputeHash(Encoding.UTF8.GetBytes(value));
}
}
}
}

View File

@ -6,14 +6,14 @@ using System.Diagnostics.CodeAnalysis;
namespace SpotifyAPI.Web
{
[AttributeUsage(AttributeTargets.Field)]
public class StringAttribute : Attribute
public sealed class StringAttribute : Attribute
{
public StringAttribute(string value)
{
Value = value;
}
public string Value { get; set; }
public string Value { get; }
#if NETSTANDARD2_0
public static bool GetValue(Type enumType, Enum enumValue, out string? result)