diff --git a/.editorconfig b/.editorconfig index 956dac4..e6c2bc2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -105,6 +105,9 @@ dotnet_diagnostic.IDE0038.severity = warning # Use 'is null' check dotnet_diagnostic.IDE0041.severity = warning +# Remove unused parameter +dotnet_diagnostic.IDE0060.severity = warning + # Use simple 'using' statement dotnet_diagnostic.IDE0063.severity = warning @@ -223,11 +226,31 @@ dotnet_diagnostic.CA1016.severity = error # Mark attributes with AttributeUsageAttribute dotnet_diagnostic.CA1018.severity = error +# Do not use insecure deserializer BinaryFormatter +dotnet_diagnostic.CA2300.severity = error + +# Do not use insecure deserializer LosFormatter +dotnet_diagnostic.CA2305.severity = error + +# Do not use insecure deserializer NetDataContractSerializer +dotnet_diagnostic.CA2310.severity = error + +# Do not use insecure deserializer ObjectStateFormatter +dotnet_diagnostic.CA2315.severity = error + ## Warnings ## +# Do not declare static members on generic types +dotnet_diagnostic.CA1000.severity = warning +dotnet_code_quality.CA1000.api_surface = all + # Types that own disposable fields should be disposable dotnet_diagnostic.CA1001.severity = warning +# Do not expose generic lists +dotnet_diagnostic.CA1002.severity = warning +dotnet_code_quality.CA1002.api_surface = all + # Use generic event handler instances dotnet_diagnostic.CA1003.severity = warning dotnet_code_quality.CA1003.api_surface = all @@ -236,9 +259,17 @@ dotnet_code_quality.CA1003.api_surface = all dotnet_diagnostic.CA1010.severity = warning dotnet_code_quality.CA1010.api_surface = all +# Abstract types should not have public constructors +dotnet_diagnostic.CA1012.severity = warning +dotnet_code_quality.CA1012.api_surface = all + # Define accessors for attribute arguments dotnet_diagnostic.CA1019.severity = warning +# Use properties where appropriate +dotnet_diagnostic.CA1024.severity = warning +dotnet_code_quality.CA1024.api_surface = all + # Mark enums with FlagsAttribute dotnet_diagnostic.CA1027.severity = warning dotnet_code_quality.CA1027.api_surface = all @@ -260,10 +291,37 @@ dotnet_diagnostic.CA1033.severity = warning # Nested types should not be visible dotnet_diagnostic.CA1034.severity = warning +# Override methods on comparable types +dotnet_diagnostic.CA1036.severity = warning +dotnet_code_quality.CA1036.api_surface = all + +# Avoid empty interfaces +dotnet_diagnostic.CA1040.severity = warning +dotnet_code_quality.CA1040.api_surface = all + +# Provide ObsoleteAttribute message +dotnet_diagnostic.CA1041.severity = warning +dotnet_code_quality.CA1041.api_surface = all + # Use integral or string argument for indexers dotnet_diagnostic.CA1043.severity = warning dotnet_code_quality.CA1043.api_surface = all +# Properties should not be write only +dotnet_diagnostic.CA1044.severity = warning +dotnet_code_quality.CA1044.api_surface = all + +# Declare types in namespaces +dotnet_diagnostic.CA1050.severity = warning + +# Do not declare visible instance fields +dotnet_diagnostic.CA1051.severity = warning +dotnet_code_quality.CA1051.api_surface = all + +# Static holder types should be Static or NotInheritable +dotnet_diagnostic.CA1052.severity = warning +dotnet_code_quality.CA1052.api_surface = all + # URI parameters should not be strings dotnet_diagnostic.CA1054.severity = warning dotnet_code_quality.CA1054.api_surface = all @@ -283,10 +341,19 @@ dotnet_code_quality.CA1058.api_surface = all # Move P/Invokes to NativeMethods class dotnet_diagnostic.CA1060.severity = warning +# Do not hide base class methods +dotnet_diagnostic.CA1061.severity = warning + # Implement IDisposable correctly dotnet_diagnostic.CA1063.severity = warning dotnet_code_quality.CA1063.api_surface = all +# Exceptions should be public +dotnet_diagnostic.CA1064.severity = warning + +# Do not raise exceptions in unexpected locations +dotnet_diagnostic.CA1065.severity = warning + # Implement IEquatable when overriding Equals dotnet_diagnostic.CA1066.severity = warning @@ -299,6 +366,18 @@ dotnet_diagnostic.CA1068.severity = warning # Enums should not have duplicate values dotnet_diagnostic.CA1069.severity = warning +# Do not declare event fields as virtual +dotnet_diagnostic.CA1070.severity = warning + +# P/Invokes should not be visible +dotnet_diagnostic.CA1401.severity = warning + +# Use nameof in place of string +dotnet_diagnostic.CA1507.severity = warning + +# Avoid dead conditional code +dotnet_diagnostic.CA1508.severity = warning + # Use ArgumentNullException throw helper dotnet_diagnostic.CA1510.severity = warning @@ -311,9 +390,19 @@ dotnet_diagnostic.CA1512.severity = warning # Use ObjectDisposedException throw helper dotnet_diagnostic.CA1513.severity = warning +# Avoid redundant length argument +dotnet_diagnostic.CA1514.severity = warning + # Do not name enum values 'Reserved' dotnet_diagnostic.CA1700.severity = warning +# Identifiers should not contain underscores +dotnet_diagnostic.CA1707.severity = warning + +# Identifiers should differ by more than case +dotnet_diagnostic.CA1708.severity = warning +dotnet_code_quality.CA1708.api_surface = all + # Identifiers should have correct suffix dotnet_diagnostic.CA1710.severity = warning dotnet_code_quality.CA1710.api_surface = all @@ -344,9 +433,6 @@ dotnet_code_quality.CA1716.api_surface = all dotnet_diagnostic.CA1717.severity = warning dotnet_code_quality.CA1717.api_surface = all -# Properties should not return arrays -dotnet_diagnostic.CA1819.severity = warning - # Identifiers should not contain type names dotnet_diagnostic.CA1720.severity = warning dotnet_code_quality.CA1720.api_surface = all @@ -355,6 +441,16 @@ dotnet_code_quality.CA1720.api_surface = all dotnet_diagnostic.CA1721.severity = warning dotnet_code_quality.CA1721.api_surface = all +# Type names should not match namespaces +dotnet_diagnostic.CA1724.severity = warning + +# Parameter names should match base declaration +dotnet_diagnostic.CA1725.severity = warning +dotnet_code_quality.CA1725.api_surface = all + +# Use PascalCase for named placeholders +dotnet_diagnostic.CA1727.severity = warning + # Use Literals Where Appropriate dotnet_diagnostic.CA1802.severity = warning dotnet_code_quality.CA1802.api_surface = all @@ -362,8 +458,26 @@ dotnet_code_quality.CA1802.api_surface = all # Do not initialize unnecessarily dotnet_diagnostic.CA1805.severity = warning +# Do not ignore method results +dotnet_diagnostic.CA1806.severity = warning + +# Initialize reference type static fields inline +dotnet_diagnostic.CA1810.severity = warning + +# Avoid uninstantiated internal classes +dotnet_diagnostic.CA1812.severity = warning + # Avoid unsealed attributes dotnet_diagnostic.CA1813.severity = warning +dotnet_code_quality.CA1813.ignore_internalsvisibleto = true + +# Override equals and operator equals on value types +dotnet_diagnostic.CA1815.severity = warning +dotnet_code_quality.CA1815.api_surface = all + +# Call GC.SuppressFinalize correctly +dotnet_diagnostic.CA1816.severity = warning +dotnet_code_quality.CA1816.api_surface = all # Properties should not return arrays dotnet_diagnostic.CA1819.severity = warning @@ -379,18 +493,42 @@ dotnet_diagnostic.CA1821.severity = warning dotnet_diagnostic.CA1822.severity = warning dotnet_code_quality.CA1822.api_surface = all +# Mark assemblies with NeutralResourcesLanguageAttribute +dotnet_diagnostic.CA1824.severity = warning + # Avoid zero-length array allocations dotnet_diagnostic.CA1825.severity = warning +# Use property instead of Linq Enumerable method +dotnet_diagnostic.CA1826.severity = warning + +# Do not use Count()/LongCount() when Any() can be used +dotnet_diagnostic.CA1827.severity = warning + +# Do not use CountAsync/LongCountAsync when AnyAsync can be used +dotnet_diagnostic.CA1828.severity = warning + # Use Length/Count property instead of Enumerable.Count method dotnet_diagnostic.CA1829.severity = warning # Prefer strongly-typed Append and Insert method overloads on StringBuilder dotnet_diagnostic.CA1830.severity = warning +# Use AsSpan instead of Range-based indexers for string when appropriate +dotnet_diagnostic.CA1831.severity = warning + +# Use AsSpan or AsMemory instead of Range-based indexers for getting ReadOnlySpan or ReadOnlyMemory portion of an array +dotnet_diagnostic.CA1832.severity = warning + +# Use AsSpan or AsMemory instead of Range-based indexers for getting Span or Memory portion of an array +dotnet_diagnostic.CA1833.severity = warning + # Use StringBuilder.Append(char) for single character strings dotnet_diagnostic.CA1834.severity = warning +# Prefer the memory-based overloads of ReadAsync/WriteAsync methods in stream-based classes +dotnet_diagnostic.CA1835.severity = warning + # Prefer IsEmpty over Count when available dotnet_diagnostic.CA1836.severity = warning @@ -415,15 +553,28 @@ dotnet_diagnostic.CA1843.severity = warning # Use string.Contains(char) instead of string.Contains(string) with single characters dotnet_diagnostic.CA1847.severity = warning +# Call async methods when in an async method +dotnet_diagnostic.CA1849.severity = warning + +# Prefer static HashData method over ComputeHash +dotnet_diagnostic.CA1850.severity = warning + # Possible multiple enumerations of IEnumerable collection dotnet_diagnostic.CA1851.severity = warning +# Seal internal types +dotnet_diagnostic.CA1852.severity = warning +dotnet_code_quality.CA1852.ignore_internalsvisibleto = true + # Unnecessary call to 'Dictionary.ContainsKey(key)' dotnet_diagnostic.CA1853.severity = warning # Prefer the IDictionary.TryGetValue(TKey, out TValue) method dotnet_diagnostic.CA1854.severity = warning +# Use Span.Clear() instead of Span.Fill() +dotnet_diagnostic.CA1855.severity = warning + # Use StartsWith instead of IndexOf dotnet_diagnostic.CA1858.severity = warning @@ -434,36 +585,92 @@ dotnet_code_quality.CA1859.api_surface = all # Avoid using 'Enumerable.Any()' extension method dotnet_diagnostic.CA1860.severity = warning +# Avoid constant arrays as arguments +dotnet_diagnostic.CA1861.severity = warning + # Use the 'StringComparison' method overloads to perform case-insensitive string comparisons dotnet_diagnostic.CA1862.severity = warning # Prefer the 'IDictionary.TryAdd(TKey, TValue)' method dotnet_diagnostic.CA1864.severity = warning +# Use 'string.Method(char)' instead of 'string.Method(string)' for string with single char +dotnet_diagnostic.CA1865.severity = warning +dotnet_diagnostic.CA1866.severity = warning +dotnet_diagnostic.CA1867.severity = warning + # Unnecessary call to 'Contains' for sets dotnet_diagnostic.CA1868.severity = warning # Cache and reuse 'JsonSerializerOptions' instances dotnet_diagnostic.CA1869.severity = warning +# Use a cached 'SearchValues' instance +dotnet_diagnostic.CA1870.severity = warning + +# Do not pass a nullable struct to 'ArgumentNullException.ThrowIfNull' +dotnet_diagnostic.CA1871.severity = warning + +# Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString' +dotnet_diagnostic.CA1872.severity = warning + # Dispose objects before losing scope dotnet_diagnostic.CA2000.severity = warning +# Do not lock on objects with weak identity +dotnet_diagnostic.CA2002.severity = warning + # Do not call ToImmutableCollection on an ImmutableCollection value dotnet_diagnostic.CA2009.severity = warning +# Do not assign property within its setter +dotnet_diagnostic.CA2011.severity = warning + +# Use ValueTasks correctly +dotnet_diagnostic.CA2012.severity = warning + +# Do not use ReferenceEquals with value types +dotnet_diagnostic.CA2013.severity = warning + # Forward the CancellationToken parameter to methods that take one dotnet_diagnostic.CA2016.severity = warning # Specify marshalling for P/Invoke string arguments dotnet_diagnostic.CA2101.severity = warning +# Rethrow to preserve stack details +dotnet_diagnostic.CA2200.severity = warning + +# Do not raise reserved exception types +dotnet_diagnostic.CA2201.severity = warning + +# Initialize value type static fields inline +dotnet_diagnostic.CA2207.severity = warning + +# Instantiate argument exceptions correctly +dotnet_diagnostic.CA2208.severity = warning + +# Non-constant fields should not be visible +dotnet_diagnostic.CA2211.severity = warning + # Disposable fields should be disposed dotnet_diagnostic.CA2213.severity = warning +# Do not call overridable methods in constructors +dotnet_diagnostic.CA2214.severity = warning + +# Dispose methods should call base class dispose +dotnet_diagnostic.CA2215.severity = warning + # Disposable types should declare finalizer dotnet_diagnostic.CA2216.severity = warning +# Do not mark enums with FlagsAttribute +dotnet_diagnostic.CA2217.severity = warning + +# Do not raise exceptions in exception clauses +dotnet_diagnostic.CA2219.severity = warning + # Operator overloads have named alternates dotnet_diagnostic.CA2225.severity = warning dotnet_code_quality.CA2225.api_surface = all @@ -471,6 +678,9 @@ dotnet_code_quality.CA2225.api_surface = all # Collection properties should be read only dotnet_diagnostic.CA2227.severity = warning +# Overload operator equals on overriding ValueType.Equals +dotnet_diagnostic.CA2231.severity = warning + # Pass System.Uri objects instead of strings dotnet_diagnostic.CA2234.severity = warning dotnet_code_quality.CA2234.api_surface = all @@ -478,12 +688,21 @@ dotnet_code_quality.CA2234.api_surface = all # Provide correct arguments to formatting methods dotnet_diagnostic.CA2241.severity = warning +# Test for NaN correctly +dotnet_diagnostic.CA2242.severity = warning + # Attribute string literals should parse correctly dotnet_diagnostic.CA2243.severity = warning # Do not duplicate indexed element initializations dotnet_diagnostic.CA2244.severity = warning +# Do not assign a property to itself +dotnet_diagnostic.CA2245.severity = warning + +# Do not assign a symbol and its member in the same statement +dotnet_diagnostic.CA2246.severity = warning + # Provide correct enum argument to Enum.HasFlag dotnet_diagnostic.CA2248.severity = warning @@ -496,6 +715,41 @@ dotnet_diagnostic.CA2250.severity = warning # Use String.Equals over String.Compare dotnet_diagnostic.CA2251.severity = warning +# Named placeholders should not be numeric values +dotnet_diagnostic.CA2253.severity = warning + +# Template should be a static expression +dotnet_diagnostic.CA2254.severity = warning + +# Set 'MaxResponseHeadersLength' properly +dotnet_diagnostic.CA2262.severity = warning + +# Prefer generic overload when type is known +dotnet_diagnostic.CA2263.severity = warning + +# Do not pass a non-nullable value to 'ArgumentNullException.ThrowIfNull' +dotnet_diagnostic.CA2264.severity = warning + +# Do not compare Span to null or default +dotnet_diagnostic.CA2265.severity = warning + +## Suggestions ## + +# Avoid excessive inheritance +dotnet_diagnostic.CA1501.severity = suggestion + +# Avoid excessive complexity +dotnet_diagnostic.CA1502.severity = suggestion + +# Avoid unmaintainable code +dotnet_diagnostic.CA1505.severity = suggestion + +# Avoid excessive class coupling +dotnet_diagnostic.CA1506.severity = suggestion + +# Consider making public types internal +dotnet_diagnostic.CA1515.severity = suggestion + ### SYSLIB ### ## Silents ## diff --git a/Bluehill.Analyzers.Package/Bluehill.Analyzers.Package.csproj b/Bluehill.Analyzers.Package/Bluehill.Analyzers.Package.csproj index ac7a110..a748347 100644 --- a/Bluehill.Analyzers.Package/Bluehill.Analyzers.Package.csproj +++ b/Bluehill.Analyzers.Package/Bluehill.Analyzers.Package.csproj @@ -19,7 +19,6 @@ - diff --git a/Bluehill.Analyzers.Pages/Pages/BH0007.razor b/Bluehill.Analyzers.Pages/Pages/BH0007.razor new file mode 100644 index 0000000..4b1c5c2 --- /dev/null +++ b/Bluehill.Analyzers.Pages/Pages/BH0007.razor @@ -0,0 +1,37 @@ +@page "/BH0007" + +

BH0007: Prefer System.Threading.Lock over System.Object

+ +

It is recommended to use System.Threading.Lock instead of System.Object for locking.

+ +

Code with violation

+ + + public class TestClass { + private object? lockObj; + + public void TestMethod() { + lockObj = new(); + + lock (lockObj) { + Console.WriteLine(); + } + } + } + + +

Fixed Code

+ + + public class TestClass { + private Lock? lockObj; + + public void TestMethod() { + lockObj = new(); + + lock (lockObj) { + Console.WriteLine(); + } + } + } + diff --git a/Bluehill.Analyzers.Pages/Pages/Rules.razor b/Bluehill.Analyzers.Pages/Pages/Rules.razor index 104c4ff..39b3fff 100644 --- a/Bluehill.Analyzers.Pages/Pages/Rules.razor +++ b/Bluehill.Analyzers.Pages/Pages/Rules.razor @@ -7,4 +7,5 @@
  • BH0002
  • BH0003
  • BH0004, BH0005, BH0006
  • +
  • BH0007
  • diff --git a/Bluehill.Analyzers.Pages/packages.lock.json b/Bluehill.Analyzers.Pages/packages.lock.json index 12c1d77..fd60608 100644 --- a/Bluehill.Analyzers.Pages/packages.lock.json +++ b/Bluehill.Analyzers.Pages/packages.lock.json @@ -4,9 +4,9 @@ "net9.0": { "Bluehill.Blazor": { "type": "Direct", - "requested": "[0.8.1, )", - "resolved": "0.8.1", - "contentHash": "UlaWDS0MH66tq0vcje85eG5HBEHPoQ4vYeg+by54j4/dEYRaIYl5wpVnXoMUCYuCrH7Oe/hwC1aueo98PztHOw==" + "requested": "[0.9.0, )", + "resolved": "0.9.0", + "contentHash": "ze8fchl63EqohDUcMqKew94lf/pqMDVLOr5K23rUCjP+xc4XrQ1ZWYNAavEC0aB57fxQ6HXgO5mhlEFZNFtAyw==" }, "Bluehill.Blazor.GHPages": { "type": "Direct", diff --git a/Bluehill.Analyzers/BH0004ToBH0006Analyzer.cs b/Bluehill.Analyzers/BH0004ToBH0006Analyzer.cs index 04b28c5..45c4fb4 100644 --- a/Bluehill.Analyzers/BH0004ToBH0006Analyzer.cs +++ b/Bluehill.Analyzers/BH0004ToBH0006Analyzer.cs @@ -53,8 +53,8 @@ private static void register(CompilationStartAnalysisContext context) { var ixs = context.Compilation.GetTypeByMetadataName("System.Xml.Serialization.IXmlSerializable") ?? throw new InvalidOperationException("Something went wrong"); var ixsgs = (IMethodSymbol)ixs.GetMembers("GetSchema").Single(); - context.RegisterSyntaxNodeAction(ac => analyzeMethod(ac, ixs, ixsgs), SyntaxKind.MethodDeclaration); - context.RegisterOperationAction(oc => analyzeInvocation(oc, ixs, ixsgs), OperationKind.Invocation); + context.RegisterSyntaxNodeAction(context => analyzeMethod(context, ixs, ixsgs), SyntaxKind.MethodDeclaration); + context.RegisterOperationAction(context => analyzeInvocation(context, ixs, ixsgs), OperationKind.Invocation); } // Analyze method declarations diff --git a/Bluehill.Analyzers/BH0007PreferLockAnalyzer.cs b/Bluehill.Analyzers/BH0007PreferLockAnalyzer.cs new file mode 100644 index 0000000..8c08075 --- /dev/null +++ b/Bluehill.Analyzers/BH0007PreferLockAnalyzer.cs @@ -0,0 +1,54 @@ +namespace Bluehill.Analyzers; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class BH0007PreferLockAnalyzer : DiagnosticAnalyzer { + public const string DiagnosticId = "BH0007"; + private const string category = "Performance"; + private static readonly LocalizableString title = + new LocalizableResourceString(nameof(Resources.BH0007AnalyzerTitle), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableString messageFormat = + new LocalizableResourceString(nameof(Resources.BH0007AnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources)); + private static readonly LocalizableString description = + new LocalizableResourceString(nameof(Resources.BH0007AnalyzerDescription), Resources.ResourceManager, typeof(Resources)); + private static readonly DiagnosticDescriptor rule = + new(DiagnosticId, title, messageFormat, category, DiagnosticSeverity.Warning, true, description, "https://na1307.github.io/Bluehill.Analyzers/BH0007"); + + public override ImmutableArray SupportedDiagnostics => [rule]; + + public override void Initialize(AnalysisContext context) { + // Configure generated code analysis + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + + // Enable concurrent execution + context.EnableConcurrentExecution(); + + // Register compilation start action + context.RegisterCompilationStartAction(compilationStartAction); + } + + private static void compilationStartAction(CompilationStartAnalysisContext context) { + var lockType = context.Compilation.GetTypeByMetadataName("System.Threading.Lock"); + + // Lock is not available because it is .NET 8 or lower. + if (lockType is null) { + return; + } + + var objectType = context.Compilation.GetTypeByMetadataName("System.Object")!; + + context.RegisterOperationAction(context => lockOperationAction(context, objectType), OperationKind.Lock); + } + + private static void lockOperationAction(OperationAnalysisContext context, INamedTypeSymbol objectType) { + var lockOperation = (ILockOperation)context.Operation; + var lockedType = lockOperation.LockedValue.Type!; + + // Whether the locked type is System.Object + if (!SymbolEqualityComparer.Default.Equals(lockedType, objectType)) { + return; + } + + // Report diagnostic + context.ReportDiagnostic(Diagnostic.Create(rule, lockOperation.LockedValue.Syntax.GetLocation())); + } +} diff --git a/Bluehill.Analyzers/Resources.Designer.cs b/Bluehill.Analyzers/Resources.Designer.cs index cc2082e..4048f60 100644 --- a/Bluehill.Analyzers/Resources.Designer.cs +++ b/Bluehill.Analyzers/Resources.Designer.cs @@ -221,5 +221,32 @@ internal static string BH0006AnalyzerTitle { return ResourceManager.GetString("BH0006AnalyzerTitle", resourceCulture); } } + + /// + /// It is recommended to use System.Threading.Lock instead of System.Object for locking.과(와) 유사한 지역화된 문자열을 찾습니다. + /// + internal static string BH0007AnalyzerDescription { + get { + return ResourceManager.GetString("BH0007AnalyzerDescription", resourceCulture); + } + } + + /// + /// Use System.Threading.Lock과(와) 유사한 지역화된 문자열을 찾습니다. + /// + internal static string BH0007AnalyzerMessageFormat { + get { + return ResourceManager.GetString("BH0007AnalyzerMessageFormat", resourceCulture); + } + } + + /// + /// Prefer System.Threading.Lock over System.Object과(와) 유사한 지역화된 문자열을 찾습니다. + /// + internal static string BH0007AnalyzerTitle { + get { + return ResourceManager.GetString("BH0007AnalyzerTitle", resourceCulture); + } + } } } diff --git a/Bluehill.Analyzers/Resources.ko.resx b/Bluehill.Analyzers/Resources.ko.resx index 5af3856..eae7730 100644 --- a/Bluehill.Analyzers/Resources.ko.resx +++ b/Bluehill.Analyzers/Resources.ko.resx @@ -1,17 +1,17 @@ - @@ -177,4 +177,13 @@ IXmlSerializable.GetSchema()를 절대 호출해서는 안됨 + + 잠금에는 System.Object 대신 System.Threading.Lock을 사용하는 것이 좋습니다. + + + System.Threading.Lock 사용 + + + System.Object보다 System.Threading.Lock을 사용하세요 + \ No newline at end of file diff --git a/Bluehill.Analyzers/Resources.resx b/Bluehill.Analyzers/Resources.resx index 9c44afb..43979ab 100644 --- a/Bluehill.Analyzers/Resources.resx +++ b/Bluehill.Analyzers/Resources.resx @@ -177,4 +177,13 @@ Never call IXmlSerializable.GetSchema() + + It is recommended to use System.Threading.Lock instead of System.Object for locking. + + + Use System.Threading.Lock + + + Prefer System.Threading.Lock over System.Object + \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index fabea11..eb065bc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ false - +