Add global AnalyzerConfig for custom Roslyn analyzer

This commit is contained in:
napoly 2025-06-18 23:39:20 +02:00
parent b544981bc5
commit 539528358b
25 changed files with 75 additions and 50 deletions

23
.globalconfig Normal file
View file

@ -0,0 +1,23 @@
# Top level global AnalyzerConfig file
is_global = true
# Remove unused imports
dotnet_diagnostic.IDE0005.severity = error
# Add braces
dotnet_diagnostic.IDE0011.severity = error
# Inline variable declaration
dotnet_diagnostic.IDE0018.severity = error
# Use collection initializers
dotnet_diagnostic.IDE0028.severity = error
# Simplify default expression
dotnet_diagnostic.IDE0034.severity = error
# Remove unused parameter
dotnet_diagnostic.IDE0060.severity = error
# Simplify new expression
dotnet_diagnostic.IDE0090.severity = error

View file

@ -1,6 +1,5 @@
using BTCPayServer.Rating;
using BTCPayServer.Services.Rates;
using BTCPayServer.Tests;
using BTCPayServer.Tests.Mocks;
using Xunit;

View file

@ -48,7 +48,7 @@ namespace BTCPayServer.Plugins.UnitTests.Monero.RPC.Models
var serializer = new JsonSerializer();
reader.Read();
Assert.Throws<Exception>(() => ParseStringConverter.Singleton.ReadJson(reader, typeof(long), null, serializer));
Assert.Throws<FormatException>(() => ParseStringConverter.Singleton.ReadJson(reader, typeof(long), null, serializer));
}
[Fact]

View file

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
<!-- Plugin specific properties -->
@ -29,6 +30,12 @@
</ProjectReference>
</ItemDefinitionGroup>
<!-- Workaround for https://github.com/dotnet/roslyn/issues/41640 -->
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);CS1591;CS1573</NoWarn>
</PropertyGroup>
<!-- Deterministic build -->
<ItemGroup>
<PackageReference Include="DotNet.ReproducibleBuilds" Version="1.2.25" PrivateAssets="All"/>

View file

@ -5,8 +5,7 @@ namespace BTCPayServer.Plugins.Monero.Configuration
{
public class MoneroLikeConfiguration
{
public Dictionary<string, MoneroLikeConfigurationItem> MoneroLikeConfigurationItems { get; set; } =
new Dictionary<string, MoneroLikeConfigurationItem>();
public Dictionary<string, MoneroLikeConfigurationItem> MoneroLikeConfigurationItems { get; set; } = [];
}
public class MoneroLikeConfigurationItem

View file

@ -1,4 +1,3 @@
using BTCPayServer.Filters;
using BTCPayServer.Plugins.Monero.RPC;
using Microsoft.AspNetCore.Mvc;

View file

@ -12,7 +12,6 @@ using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client;
using BTCPayServer.Data;
using BTCPayServer.Filters;
using BTCPayServer.Payments;
using BTCPayServer.Plugins.Monero.Configuration;
using BTCPayServer.Plugins.Monero.Payments;
@ -87,7 +86,11 @@ namespace BTCPayServer.Plugins.Monero.Controllers
return _MoneroRpcProvider.WalletRpcClients[cryptoCode].SendCommandAsync<GetAccountsRequest, GetAccountsResponse>("get_accounts", new GetAccountsRequest());
}
}
catch { }
catch
{
// ignored
}
return Task.FromResult<GetAccountsResponse>(null);
}
@ -224,6 +227,7 @@ namespace BTCPayServer.Plugins.Monero.Controllers
}
catch
{
// ignored
}
}
@ -237,8 +241,8 @@ namespace BTCPayServer.Plugins.Monero.Controllers
}
catch
{
// ignored
}
}
fileAddress = Path.Combine(configurationItem.WalletDirectory, "password");
@ -251,6 +255,7 @@ namespace BTCPayServer.Plugins.Monero.Controllers
}
catch
{
// ignored
}
}
@ -263,7 +268,7 @@ namespace BTCPayServer.Plugins.Monero.Controllers
});
if (response?.Error != null)
{
throw new Exception(response.Error.Message);
throw new WalletOpenException(response.Error.Message);
}
}
catch (Exception ex)

View file

@ -0,0 +1,5 @@
using System;
namespace BTCPayServer.Plugins.Monero.Controllers;
public class WalletOpenException(string message) : Exception(message);

View file

@ -1,5 +1,3 @@
using BTCPayServer.Payments;
namespace BTCPayServer.Plugins.Monero.Payments
{
public class MoneroLikeOnChainPaymentMethodDetails

View file

@ -1,9 +1,3 @@
using BTCPayServer.Client.Models;
using BTCPayServer.Payments;
using BTCPayServer.Plugins.Altcoins;
using BTCPayServer.Plugins.Monero.Utils;
using BTCPayServer.Services.Invoices;
namespace BTCPayServer.Plugins.Monero.Payments
{
public class MoneroLikePaymentData

View file

@ -62,8 +62,12 @@ namespace BTCPayServer.Plugins.Monero.Payments
{
throw new PaymentMethodUnavailableException($"BTCPAY_XMR_WALLET_DAEMON_URI or BTCPAY_XMR_DAEMON_URI isn't configured");
}
if (!_moneroRpcProvider.IsAvailable(_network.CryptoCode) || context.State is not Prepare moneroPrepare)
{
throw new PaymentMethodUnavailableException($"Node or wallet not available");
}
var invoice = context.InvoiceEntity;
var feeRatePerKb = await moneroPrepare.GetFeeRate;
var address = await moneroPrepare.ReserveAddress(invoice.Id);

View file

@ -2,7 +2,6 @@
using System.Globalization;
using BTCPayServer.Payments;
using BTCPayServer.Plugins.Altcoins;
using BTCPayServer.Services.Invoices;
using Microsoft.AspNetCore.Mvc;

View file

@ -1,7 +1,3 @@
using BTCPayServer.Payments;
using Newtonsoft.Json;
namespace BTCPayServer.Plugins.Monero.Payments
{
public class MoneroPaymentPromptDetails

View file

@ -27,7 +27,7 @@ namespace BTCPayServer.Plugins.Monero.RPC
public async Task<TResponse> SendCommandAsync<TRequest, TResponse>(string method, TRequest data,
CancellationToken cts = default(CancellationToken))
CancellationToken cts = default)
{
var jsonSerializer = new JsonSerializerSettings
{
@ -75,7 +75,7 @@ namespace BTCPayServer.Plugins.Monero.RPC
public class NoRequestModel
{
public static readonly NoRequestModel Instance = new NoRequestModel();
public static readonly NoRequestModel Instance = new();
}
public class JsonRpcApiException : Exception

View file

@ -1,5 +1,4 @@

using Newtonsoft.Json;
using Newtonsoft.Json;
namespace BTCPayServer.Plugins.Monero.RPC.Models;

View file

@ -1,5 +1,3 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace BTCPayServer.Plugins.Monero.RPC.Models

View file

@ -16,13 +16,12 @@ namespace BTCPayServer.Plugins.Monero.RPC.Models
return null;
}
var value = serializer.Deserialize<string>(reader);
long l;
if (Int64.TryParse(value, out l))
if (Int64.TryParse(value, out long l))
{
return l;
}
throw new Exception("Cannot unmarshal type long");
throw new FormatException("Cannot unmarshal type long");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
@ -38,6 +37,6 @@ namespace BTCPayServer.Plugins.Monero.RPC.Models
return;
}
public static readonly ParseStringConverter Singleton = new ParseStringConverter();
public static readonly ParseStringConverter Singleton = new();
}
}

View file

@ -1,13 +1,9 @@
using System;
using System.Threading.Tasks;
using System.Threading.Tasks;
using BTCPayServer.Payments;
using BTCPayServer.Plugins.Altcoins;
using BTCPayServer.Plugins.Monero.RPC;
using BTCPayServer.Plugins.Monero.RPC.Models;
using NBitcoin;
namespace BTCPayServer.Plugins.Monero.Services;
public class MoneroCheckoutCheatModeExtension : ICheckoutCheatModeExtension

View file

@ -60,7 +60,10 @@ namespace BTCPayServer.Plugins.Monero.Services
}
}
}
catch when (cancellation.IsCancellationRequested) { }
catch when (cancellation.IsCancellationRequested)
{
// ignored
}
}
public Task StopAsync(CancellationToken cancellationToken)

View file

@ -152,8 +152,7 @@ namespace BTCPayServer.Plugins.Monero.Services
foreach (var expandedInvoice in expandedInvoices)
{
var addressIndexList =
accountToAddressQuery.GetValueOrDefault(expandedInvoice.PaymentMethodDetails.AccountIndex,
new List<long>());
accountToAddressQuery.GetValueOrDefault(expandedInvoice.PaymentMethodDetails.AccountIndex, []);
addressIndexList.AddRange(
expandedInvoice.ExistingPayments.Select(tuple => tuple.PaymentData.SubaddressIndex));
@ -210,7 +209,7 @@ namespace BTCPayServer.Plugins.Monero.Services
}
return HandlePaymentData(cryptoCode, transfer.Address, transfer.Amount, transfer.SubaddrIndex.Major,
return HandlePaymentData(cryptoCode, transfer.Amount, transfer.SubaddrIndex.Major,
transfer.SubaddrIndex.Minor, transfer.Txid, transfer.Confirmations, transfer.Height,
transfer.UnlockTime, invoice,
updatedPaymentEntities);
@ -259,7 +258,6 @@ namespace BTCPayServer.Plugins.Monero.Services
var index = destination.First().SubaddrIndex;
await HandlePaymentData(cryptoCode,
destination.Key,
destination.Sum(destination1 => destination1.Amount),
index.Major,
index.Minor,
@ -329,7 +327,7 @@ namespace BTCPayServer.Plugins.Monero.Services
}
}
private async Task HandlePaymentData(string cryptoCode, string address, long totalAmount, long subaccountIndex,
private async Task HandlePaymentData(string cryptoCode, long totalAmount, long subaccountIndex,
long subaddressIndex,
string txId, long confirmations, long blockHeight, long locktime, InvoiceEntity invoice,
List<(PaymentEntity Payment, InvoiceEntity invoice)> paymentsToUpdate)

View file

@ -25,8 +25,7 @@ namespace BTCPayServer.Plugins.Monero.Services
public ImmutableDictionary<string, JsonRpcClient> DaemonRpcClients;
public ImmutableDictionary<string, JsonRpcClient> WalletRpcClients;
private readonly ConcurrentDictionary<string, MoneroLikeSummary> _summaries =
new ConcurrentDictionary<string, MoneroLikeSummary>();
private readonly ConcurrentDictionary<string, MoneroLikeSummary> _summaries = new();
public ConcurrentDictionary<string, MoneroLikeSummary> Summaries => _summaries;
@ -185,6 +184,7 @@ namespace BTCPayServer.Plugins.Monero.Services
}
catch
{
// ignored
}
await walletRpcClient.SendCommandAsync<CreateWalletRequest, JsonRpcClient.NoRequestModel>("create_wallet",

View file

@ -2,7 +2,7 @@ using System.Globalization;
namespace BTCPayServer.Plugins.Monero.Utils
{
public class MoneroMoney
public static class MoneroMoney
{
public static decimal Convert(long piconero)
{

View file

@ -93,6 +93,8 @@ We use the **unmodified** standardized `.editorconfig` from .NET SDK. Run `dotne
To enforce formatting for the whole project, run `dotnet format btcpay-monero-plugin.sln --exclude submodules/* --verbosity diagnostic`
To enforce custom analyzer configuration options, we do use global _AnalyzerConfig_ `.globalconfig` file.
## 4. Configure BTCPay Server to Load the Plugin
For vscode, open the `launch.json` file in the `.vscode` folder and set the `launchSettingsProfile` to `Altcoins-HTTPS`.

View file

@ -32,6 +32,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{BDB6EEEA-4
.dockerignore = .dockerignore
.gitignore = .gitignore
.gitmodules = .gitmodules
.editorconfig = .editorconfig
.globalconfig = .globalconfig
LICENSE.md = LICENSE.md
README.md = README.md
EndProjectSection
@ -87,10 +89,10 @@ Global
{BC95362E-D430-4CB4-B888-EE1C054C1E7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BC95362E-D430-4CB4-B888-EE1C054C1E7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BC95362E-D430-4CB4-B888-EE1C054C1E7A}.Release|Any CPU.Build.0 = Release|Any CPU
{EE24163B-B82C-4561-92F2-C7198CE91F67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE24163B-B82C-4561-92F2-C7198CE91F67}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE24163B-B82C-4561-92F2-C7198CE91F67}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE24163B-B82C-4561-92F2-C7198CE91F67}.Release|Any CPU.Build.0 = Release|Any CPU
{DA3599F0-C2DD-4323-A52F-DED5F86722ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA3599F0-C2DD-4323-A52F-DED5F86722ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA3599F0-C2DD-4323-A52F-DED5F86722ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA3599F0-C2DD-4323-A52F-DED5F86722ED}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{049FC011-1952-4140-9652-12921C106B02} = {891F21E0-262C-4430-90C5-7A540AD7C9AD}