Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Testing;
using CodeFixTest = Meziantou.Analyzer.Test.Harness.CSharpCodeFixTest<
Meziantou.Analyzer.Rules.AvoidClosureWhenUsingConcurrentDictionaryAnalyzer,
Meziantou.Analyzer.Rules.AvoidClosureWhenUsingConcurrentDictionaryFixer>;

namespace Meziantou.Analyzer.Test.Rules;

public sealed class ConcurrentDictionaryMustPreventClosureWhenAccessingTheKeyAnalyzerTests_MA0105
public sealed class ConcurrentDictionaryMustPreventClosureWhenAccessingTheKeyAnalyzerTests
{
// This class covers MA0105 only, the way the original test filtered the diagnostics to that rule
private static CodeFixTest CreateTest()
{
var test = new CodeFixTest();
test.DisabledDiagnostics.Add(RuleIdentifiers.AvoidClosureWhenUsingConcurrentDictionaryByUsingFactoryArg);
return test;
}

[Fact]
public Task GetOrAdd_IsValid()
{
var test = CreateTest();
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;
Expand All @@ -30,11 +21,11 @@ public Task GetOrAdd_IsValid()
var a = new ConcurrentDictionary<int, int>();
a.GetOrAdd(key, (k) => k + 1);
a.GetOrAdd(key, (k, v) => k + v, factoryArg);
a.GetOrAdd(key, (k, v) =>
a.GetOrAdd(key, {|MA0106:(k, v) =>
{
key = 2; // ok to write a value
return key + v; // ok to use the value if it is written
}, factoryArg);
}|}, factoryArg);
""";

return test.RunAsync();
Expand All @@ -43,7 +34,7 @@ public Task GetOrAdd_IsValid()
[Fact]
public Task AddOrUpdate_IsValid()
{
var test = CreateTest();
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;
Expand All @@ -63,7 +54,7 @@ public Task AddOrUpdate_IsValid()
[Fact]
public Task GetOrAdd()
{
var test = CreateTest();
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;
Expand All @@ -80,7 +71,7 @@ public Task GetOrAdd()
[Fact]
public Task GetOrAdd_StringInterpolation()
{
var test = CreateTest();
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;
Expand All @@ -97,7 +88,7 @@ public Task GetOrAdd_StringInterpolation()
[Fact]
public Task GetOrAdd_StringInterpolation_CodeFix()
{
var test = CreateTest();
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;
Expand All @@ -122,7 +113,7 @@ public Task GetOrAdd_StringInterpolation_CodeFix()
[Fact]
public Task AddOrUpdate_Parameter()
{
var test = CreateTest();
var test = new CodeFixTest();
test.TestCode = """
using System.Collections.Concurrent;

Expand All @@ -132,7 +123,7 @@ void A(int value)
{
var key = 1;
var a = new ConcurrentDictionary<int, int>();
a.AddOrUpdate(key, value, (k, oldValue) => value);
a.AddOrUpdate(key, value, {|MA0106:(k, oldValue) => value|});
}
}
""";
Expand All @@ -143,7 +134,7 @@ void A(int value)
[Fact]
public Task AddOrUpdate_Parameter_IsValid()
{
var test = CreateTest();
var test = new CodeFixTest();
test.TestCode = """
using System.Collections.Concurrent;

Expand All @@ -164,7 +155,7 @@ void A(int value)
[Fact]
public Task AddOrUpdate_Variable_IsValid()
{
var test = CreateTest();
var test = new CodeFixTest();
test.TestCode = """
using System.Collections.Concurrent;

Expand All @@ -176,7 +167,7 @@ void A()
var value = 1;
var a = new ConcurrentDictionary<int, int>();

a.AddOrUpdate(key, addValueFactory: k => k, updateValueFactory: (k, v) => value);
a.AddOrUpdate(key, addValueFactory: k => k, updateValueFactory: {|MA0106:(k, v) => value|});
}
}
""";
Expand All @@ -187,7 +178,7 @@ void A()
[Fact]
public Task AddOrUpdate_Variable_netstandard2()
{
var test = CreateTest();
var test = new CodeFixTest();
test.ReferenceAssemblies = ReferenceAssemblies.NetStandard.NetStandard20;
test.TestCode = """
using System.Collections.Concurrent;
Expand All @@ -206,4 +197,159 @@ void A()

return test.RunAsync();
}

[Fact]
public Task GetOrAdd_FactoryArg_IsValid()
{
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;

var key = 1;
var value = 1;
var a = new ConcurrentDictionary<int, int>();
a.GetOrAdd(key, (k) => k + 1);
a.GetOrAdd(key, (_, v) => v, value);
""";

return test.RunAsync();
}

[Fact]
public Task GetOrAdd_NoOverload_IsValid()
{
var test = new CodeFixTest();
test.ReferenceAssemblies = ReferenceAssemblies.NetStandard.NetStandard20;
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;

var key = 1;
var value = 1;
var a = new ConcurrentDictionary<int, int>();
a.GetOrAdd(key, (k) => k + 1);
a.GetOrAdd(key, _ => value);
""";

return test.RunAsync();
}

[Fact]
public Task GetOrAdd_TArg_IsValid()
{
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System;
using System.Collections.Concurrent;

var key = 1;
var closure = "";
var a = new ConcurrentDictionary<int, Func<string>>();
a.GetOrAdd<Func<string>>(key, (_, v) => v, () => closure);
""";

return test.RunAsync();
}

[Fact]
public Task GetOrAdd_Key_IsValid()
{
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System;
using System.Collections.Concurrent;

var key = 1;
var closure = "";
var a = new ConcurrentDictionary<Func<string>, int>();
a.GetOrAdd(() => closure, _ => 0);
""";

return test.RunAsync();
}

[Fact]
public Task GetOrAdd_Closure()
{
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;

var key = 1;
var value = 1;
var a = new ConcurrentDictionary<int, int>();
a.GetOrAdd(key, {|MA0106:_ => value|});
""";

return test.RunAsync();
}

[Fact]
public Task GetOrAdd_Closure_CodeFix()
{
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;

var key = 1;
var value = 1;
var a = new ConcurrentDictionary<int, int>();
a.GetOrAdd(key, {|MA0106:_ => value|});
""";
test.FixedCode = """
using System.Collections.Concurrent;

var key = 1;
var value = 1;
var a = new ConcurrentDictionary<int, int>();
a.GetOrAdd(key, (_, arg) => arg, value);
""";

return test.RunAsync();
}

[Fact]
public Task GetOrAdd_ClosureWithLambdaParameter()
{
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System.Collections.Concurrent;

var key = 1;
var a = new ConcurrentDictionary<int, int>();
a.GetOrAdd(key, k => new System.Func<int>(() => k)());
""";

return test.RunAsync();
}

[Fact]
public Task GetOrAdd_NoClosure()
{
var test = new CodeFixTest();
test.TestState.OutputKind = OutputKind.ConsoleApplication;
test.TestCode = """
using System;
using System.Collections.Concurrent;
using System.Linq;

var dict = new ConcurrentDictionary<string, Type>();
dict.GetOrAdd("", static layout2 =>
{
var types = System.Array.Empty<string>().Where(t => t == layout2);
throw null!;
});

var dummy = new object();
var f = new System.Func<bool>(() => dummy != null);
""";

return test.RunAsync();
}
}
Loading