Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add analysis suite #3

Merged
merged 47 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
426becd
Add analysis project
thinker227 Dec 23, 2023
a996e60
Add testing project
thinker227 Dec 23, 2023
7e75ab8
Add ThrowAnalyzer
thinker227 Dec 23, 2023
94f5809
Merge branch 'main' into analysis
thinker227 Dec 23, 2023
64abaa8
Update ThrowAnalyzer
thinker227 Dec 23, 2023
330339d
Merge branch 'main' into analysis
thinker227 Dec 29, 2023
b468b55
Fix async stuff
thinker227 Dec 29, 2023
e8f3f24
Move DoNotThrow diagnostic to RASCAL0002
thinker227 Dec 29, 2023
050c132
Add UseMapAnalyzer
thinker227 Dec 29, 2023
0872fd4
Remove ThrowAnalayzer
thinker227 Dec 29, 2023
de5f101
Add UseThenAnalyzer
thinker227 Dec 29, 2023
995ee0d
Add UnnecessaryIdMapAnalyzer
thinker227 Dec 29, 2023
e595b72
Add RemoveMapIdCallCodeFixer
thinker227 Dec 29, 2023
2bd09ae
Add more comments
thinker227 Dec 29, 2023
7b522ed
Rename RemoveMapIdCallCodeFixer.cs
thinker227 Dec 29, 2023
8d7331b
Move RemoveMapIdCallCodeFixTests into namespace
thinker227 Dec 29, 2023
f8345fe
Inline some pattern matching
thinker227 Dec 29, 2023
611b3b3
Update messages
thinker227 Jan 2, 2024
5112646
ToSusTypeAnalyzer wip
thinker227 Jan 2, 2024
de68cc7
Merge branch 'main' into analysis
thinker227 Jan 2, 2024
da2a8fb
Finish implementing ToSusTypeAnalyzer
thinker227 Jan 2, 2024
34dc7a0
Specify equivalence key
thinker227 Jan 2, 2024
3447d25
Add Usings.cs
thinker227 Jan 2, 2024
3bc7c01
Use pattern matching instead of hard-casts
thinker227 Jan 2, 2024
78913e0
Some comments
thinker227 Jan 2, 2024
e3d3efb
Use ToDisplayString
thinker227 Jan 2, 2024
e8de916
Fix name thing
thinker227 Jan 2, 2024
60056d0
Add UseDefaultOrForIdMatchAnalyzer
thinker227 Jan 2, 2024
d443550
Fix small typo
thinker227 Jan 4, 2024
ccfe839
Add UseDefaultOrForIdMatchCodeFix
thinker227 Jan 4, 2024
340efb6
Merge branch 'main' into analysis
thinker227 Jan 4, 2024
8cfb8fb
Add analyzer reference to Playground project
thinker227 Jan 4, 2024
ca35084
Rename UseDefaultOrForIdMatch
thinker227 Jan 4, 2024
d2d1e21
Use lambda parameter names
thinker227 Jan 4, 2024
38ac672
Simplify some logic and add syntax failsafes
thinker227 Jan 5, 2024
07ee81b
Update UseMapAnalyzerTests
thinker227 Jan 5, 2024
9d0f6d0
Update RemoveMapIdCallCodeFix
thinker227 Jan 5, 2024
ed85b03
Add UseMapCodeFix
thinker227 Jan 5, 2024
afaf42e
Take into account conversions and target-type new
thinker227 Jan 5, 2024
e49b21c
Minor whitespace
thinker227 Jan 5, 2024
b80ad6c
Add UseThenCodeFix
thinker227 Jan 8, 2024
0ef1d28
Use 3-digit diagnostic IDs
thinker227 Jan 8, 2024
da1d08e
Rename some tests
thinker227 Jan 8, 2024
ae53281
Add WellKnownSymbols
thinker227 Jan 8, 2024
77f0d0e
Add BaseAnalyzer and MissingSymbolAnalyzer
thinker227 Jan 8, 2024
a70d7f4
Include analysis project into nupkg
thinker227 Jan 9, 2024
11f5e9f
Update changelog
thinker227 Jan 9, 2024
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@
- Add additional overloads for `Result<T>.Equals` which allow specifying an equality comparer to use for comparing values.

- Rename `GetValueOrDefault(T @default)` and `GetValueOrDefault(Func<T> getDefault)` to `GetValueOr`.

- Add analyzer and code-fix suite.
96 changes: 55 additions & 41 deletions Rascal.sln
Original file line number Diff line number Diff line change
@@ -1,41 +1,55 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D92004B4-8D01-4BC3-B76B-A80D657FEC30}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rascal", "src\Rascal\Rascal.csproj", "{04DE173D-4E74-4104-94FA-2B1807FCD34D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rascal.Tests", "src\Rascal.Tests\Rascal.Tests.csproj", "{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rascal.Playground", "src\Rascal.Playground\Rascal.Playground.csproj", "{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{04DE173D-4E74-4104-94FA-2B1807FCD34D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{04DE173D-4E74-4104-94FA-2B1807FCD34D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{04DE173D-4E74-4104-94FA-2B1807FCD34D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{04DE173D-4E74-4104-94FA-2B1807FCD34D}.Release|Any CPU.Build.0 = Release|Any CPU
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}.Release|Any CPU.Build.0 = Release|Any CPU
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{04DE173D-4E74-4104-94FA-2B1807FCD34D} = {D92004B4-8D01-4BC3-B76B-A80D657FEC30}
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58} = {D92004B4-8D01-4BC3-B76B-A80D657FEC30}
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4} = {D92004B4-8D01-4BC3-B76B-A80D657FEC30}
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D92004B4-8D01-4BC3-B76B-A80D657FEC30}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rascal", "src\Rascal\Rascal.csproj", "{04DE173D-4E74-4104-94FA-2B1807FCD34D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rascal.Tests", "src\Rascal.Tests\Rascal.Tests.csproj", "{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rascal.Analysis", "src\Rascal.Analysis\Rascal.Analysis.csproj", "{076764E7-54D5-41EF-99C9-96C483F15E31}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rascal.Analysis.Tests", "src\Rascal.Analysis.Tests\Rascal.Analysis.Tests.csproj", "{C2197909-F734-4435-869A-422CD571D061}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rascal.Playground", "src\Rascal.Playground\Rascal.Playground.csproj", "{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{04DE173D-4E74-4104-94FA-2B1807FCD34D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{04DE173D-4E74-4104-94FA-2B1807FCD34D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{04DE173D-4E74-4104-94FA-2B1807FCD34D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{04DE173D-4E74-4104-94FA-2B1807FCD34D}.Release|Any CPU.Build.0 = Release|Any CPU
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58}.Release|Any CPU.Build.0 = Release|Any CPU
{076764E7-54D5-41EF-99C9-96C483F15E31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{076764E7-54D5-41EF-99C9-96C483F15E31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{076764E7-54D5-41EF-99C9-96C483F15E31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{076764E7-54D5-41EF-99C9-96C483F15E31}.Release|Any CPU.Build.0 = Release|Any CPU
{C2197909-F734-4435-869A-422CD571D061}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2197909-F734-4435-869A-422CD571D061}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2197909-F734-4435-869A-422CD571D061}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2197909-F734-4435-869A-422CD571D061}.Release|Any CPU.Build.0 = Release|Any CPU
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{04DE173D-4E74-4104-94FA-2B1807FCD34D} = {D92004B4-8D01-4BC3-B76B-A80D657FEC30}
{291FDB2E-8AC8-4B7A-B6E6-6DF5DCBCEB58} = {D92004B4-8D01-4BC3-B76B-A80D657FEC30}
{076764E7-54D5-41EF-99C9-96C483F15E31} = {D92004B4-8D01-4BC3-B76B-A80D657FEC30}
{C2197909-F734-4435-869A-422CD571D061} = {D92004B4-8D01-4BC3-B76B-A80D657FEC30}
{F5A7C08C-51B5-4043-9666-C8DCD4F9C1E4} = {D92004B4-8D01-4BC3-B76B-A80D657FEC30}
EndGlobalSection
EndGlobal
164 changes: 164 additions & 0 deletions src/Rascal.Analysis.Tests/Analyzers/ToSusTypeAnalyzerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
using VerifyCS = Rascal.Analysis.Tests.Verifiers.AnalyzerVerifier<Rascal.Analysis.Analyzers.ToSusTypeAnalyzer>;

namespace Rascal.Analysis.Analyzers.Tests;

public class ToSusTypeAnalyzerTests
{
[Fact]
public async Task Reports_SameType_OnSameType() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var x = Ok(2);
var r = x.To<{|RASCAL004:int|}>();
}
}
""");

[Fact]
public async Task Reports_ImpossibleType_OnBothStructTypes() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var x = Ok(2);
var r = x.To<{|RASCAL005:bool|}>();
}
}
""");

[Fact]
public async Task Reports_ImpossibleType_OnBothClassTypes_OutsideHierarchy() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var x = Ok(new B());
var r = x.To<{|RASCAL005:C|}>();
}
}

class A {}
class B : A {}
class C : A {}
""");

[Fact]
public async Task DoesNotReport_OnBothClassTypes_InsideHierarchy_Up() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var x = Ok(new B());
var r = x.To<A>();
}
}

class A {}
class B : A {}
""");

[Fact]
public async Task DoesNotReport_OnBothClassTypes_InsideHierarchy_Down() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var x = Ok(new A());
var r = x.To<B>();
}
}

class A {}
class B : A {}
""");

[Fact]
public async Task DoesNotReport_OnFromInterfaceType() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var x = Err<I>("error");
var r = x.To<int>();
}
}

interface I {}
""");

[Fact]
public async Task DoesNotReport_OnToInterfaceType() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var x = Ok(2);
var r = x.To<I>();
}
}

interface I {}
""");

[Fact]
public async Task DoesNotReport_OnFromTypeParameter() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar<T>()
{
var x = Err<T>("error");
var r = x.To<int>();
}
}
""");

[Fact]
public async Task DoesNotReport_OnToTypeParameter() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar<T>()
{
var x = Ok(2);
var r = x.To<T>();
}
}
""");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using VerifyCS = Rascal.Analysis.Tests.Verifiers.AnalyzerVerifier<Rascal.Analysis.Analyzers.UnnecessaryIdMapAnalyzer>;

namespace Rascal.Analysis.Analyzers.Tests;

public class UnnecessaryIdMapAnalyzerTests
{
[Fact]
public async Task DoesNotReport_OnMapOperationCall() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var result = Ok(2);
var v = result.Map(x => x + 1);
}
}
""");

[Fact]
public async Task Reports_OnMapIdCall() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var result = Ok(2);
var v = result.{|RASCAL003:Map(x => x)|};
}
}
""");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using VerifyCS = Rascal.Analysis.Tests.Verifiers.AnalyzerVerifier<Rascal.Analysis.Analyzers.UseGetValueOrForIdMatchAnalyzer>;

namespace Rascal.Analysis.Analyzers.Tests;

public class UseGetValueOrForIdMatchAnalyzerTests
{
[Fact]
public async Task DoesNotReport_OnOperation() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var r = Ok(2);
var x = r.Match(x => x + 1, _ => 0);
}
}
""");

[Fact]
public async Task Reports_OnId() => await VerifyCS.VerifyAnalyzerAsync("""
using System;
using Rascal;
using static Rascal.Prelude;

public static class Foo
{
public static void Bar()
{
var r = Ok(2);
var x = r.{|RASCAL006:Match|}(x => x, _ => 0);
}
}
""");
}
Loading