diff --git a/CHANGELOG.md b/CHANGELOG.md
index c80f64b58..92d83cac6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Use string interpolation instead of `+` concatenation #724 [@xperiandri]
- Run tests in parallel #728 [@xperiandri]
- Remove `NoPartialFunctions` compiler workaround (#698) [@webwarrior-ws]
+- Add `SLNX` and `SLNF` format support and migrate to SLNX solution #723 [@xperiandri]\
+ Remove `Ionide.ProjInfo.Sln` NuGet package dependency
## [0.24.2] - 2024-02-29
@@ -26,7 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New rule FavourNonMutablePropertyInitialization #683 #662 #535 [@webwarrior-ws]
- Workaround for NoPartialFuncs bug #682 [@webwarrior-ws]
- Fix AvoidSinglePipeOperator false positive #684 [@Mersho]
-- docs(CSS): capitalize
rather than uppercase [@knocte]
+- docs(CSS): capitalize `` rather than uppercase [@knocte]
- Simplify SelfCheck #679 [@knocte]
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 78a0e4d24..76426fc2c 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -14,7 +14,6 @@
-
diff --git a/FSharpLint.sln b/FSharpLint.sln
deleted file mode 100644
index cb85d26a2..000000000
--- a/FSharpLint.sln
+++ /dev/null
@@ -1,216 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.14.36221.1
-MinimumVisualStudioVersion = 15.0.26124.0
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{40C2798B-7078-4D4F-BD37-195240CB827B}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{1CD44876-BCDC-4C93-9DC2-C45244BD62AE}"
-EndProject
-Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpLint.Console", "src\FSharpLint.Console\FSharpLint.Console.fsproj", "{AC24094C-4AB5-4A6B-8430-3D21EF788AEC}"
-EndProject
-Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpLint.Core", "src\FSharpLint.Core\FSharpLint.Core.fsproj", "{7691E4E4-EC5B-4751-9578-109258A3B1DA}"
-EndProject
-Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpLint.Core.Tests", "tests\FSharpLint.Core.Tests\FSharpLint.Core.Tests.fsproj", "{E51042D9-CE14-4373-AE1E-FEB78FE23F40}"
-EndProject
-Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpLint.FunctionalTest", "tests\FSharpLint.FunctionalTest\FSharpLint.FunctionalTest.fsproj", "{0DE70980-49E9-4613-84D4-FCF6ACABA5EE}"
-EndProject
-Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpLint.Console.Tests", "tests\FSharpLint.Console.Tests\FSharpLint.Console.Tests.fsproj", "{73AD322D-2E3F-45C4-8DB2-179571DECCD0}"
-EndProject
-Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpLint.Benchmarks", "tests\FSharpLint.Benchmarks\FSharpLint.Benchmarks.fsproj", "{B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{270E691D-ECA1-4BC5-B851-C5431A64E9FA}"
- ProjectSection(SolutionItems) = preProject
- build.fsx = build.fsx
- Directory.Build.props = Directory.Build.props
- Directory.Packages.props = Directory.Packages.props
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{E1E03FFE-30DF-4522-83DA-9089147B431E}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rules", "rules", "{AEBB56D7-30B4-40D7-B065-54B8BE960298}"
- ProjectSection(SolutionItems) = preProject
- docs\content\how-tos\rules\FL0001.md = docs\content\how-tos\rules\FL0001.md
- docs\content\how-tos\rules\FL0002.md = docs\content\how-tos\rules\FL0002.md
- docs\content\how-tos\rules\FL0003.md = docs\content\how-tos\rules\FL0003.md
- docs\content\how-tos\rules\FL0004.md = docs\content\how-tos\rules\FL0004.md
- docs\content\how-tos\rules\FL0005.md = docs\content\how-tos\rules\FL0005.md
- docs\content\how-tos\rules\FL0006.md = docs\content\how-tos\rules\FL0006.md
- docs\content\how-tos\rules\FL0007.md = docs\content\how-tos\rules\FL0007.md
- docs\content\how-tos\rules\FL0008.md = docs\content\how-tos\rules\FL0008.md
- docs\content\how-tos\rules\FL0009.md = docs\content\how-tos\rules\FL0009.md
- docs\content\how-tos\rules\FL0010.md = docs\content\how-tos\rules\FL0010.md
- docs\content\how-tos\rules\FL0011.md = docs\content\how-tos\rules\FL0011.md
- docs\content\how-tos\rules\FL0012.md = docs\content\how-tos\rules\FL0012.md
- docs\content\how-tos\rules\FL0013.md = docs\content\how-tos\rules\FL0013.md
- docs\content\how-tos\rules\FL0014.md = docs\content\how-tos\rules\FL0014.md
- docs\content\how-tos\rules\FL0015.md = docs\content\how-tos\rules\FL0015.md
- docs\content\how-tos\rules\FL0016.md = docs\content\how-tos\rules\FL0016.md
- docs\content\how-tos\rules\FL0017.md = docs\content\how-tos\rules\FL0017.md
- docs\content\how-tos\rules\FL0018.md = docs\content\how-tos\rules\FL0018.md
- docs\content\how-tos\rules\FL0019.md = docs\content\how-tos\rules\FL0019.md
- docs\content\how-tos\rules\FL0020.md = docs\content\how-tos\rules\FL0020.md
- docs\content\how-tos\rules\FL0021.md = docs\content\how-tos\rules\FL0021.md
- docs\content\how-tos\rules\FL0022.md = docs\content\how-tos\rules\FL0022.md
- docs\content\how-tos\rules\FL0023.md = docs\content\how-tos\rules\FL0023.md
- docs\content\how-tos\rules\FL0024.md = docs\content\how-tos\rules\FL0024.md
- docs\content\how-tos\rules\FL0025.md = docs\content\how-tos\rules\FL0025.md
- docs\content\how-tos\rules\FL0026.md = docs\content\how-tos\rules\FL0026.md
- docs\content\how-tos\rules\FL0027.md = docs\content\how-tos\rules\FL0027.md
- docs\content\how-tos\rules\FL0028.md = docs\content\how-tos\rules\FL0028.md
- docs\content\how-tos\rules\FL0029.md = docs\content\how-tos\rules\FL0029.md
- docs\content\how-tos\rules\FL0030.md = docs\content\how-tos\rules\FL0030.md
- docs\content\how-tos\rules\FL0031.md = docs\content\how-tos\rules\FL0031.md
- docs\content\how-tos\rules\FL0032.md = docs\content\how-tos\rules\FL0032.md
- docs\content\how-tos\rules\FL0033.md = docs\content\how-tos\rules\FL0033.md
- docs\content\how-tos\rules\FL0034.md = docs\content\how-tos\rules\FL0034.md
- docs\content\how-tos\rules\FL0035.md = docs\content\how-tos\rules\FL0035.md
- docs\content\how-tos\rules\FL0036.md = docs\content\how-tos\rules\FL0036.md
- docs\content\how-tos\rules\FL0037.md = docs\content\how-tos\rules\FL0037.md
- docs\content\how-tos\rules\FL0038.md = docs\content\how-tos\rules\FL0038.md
- docs\content\how-tos\rules\FL0039.md = docs\content\how-tos\rules\FL0039.md
- docs\content\how-tos\rules\FL0040.md = docs\content\how-tos\rules\FL0040.md
- docs\content\how-tos\rules\FL0041.md = docs\content\how-tos\rules\FL0041.md
- docs\content\how-tos\rules\FL0042.md = docs\content\how-tos\rules\FL0042.md
- docs\content\how-tos\rules\FL0043.md = docs\content\how-tos\rules\FL0043.md
- docs\content\how-tos\rules\FL0044.md = docs\content\how-tos\rules\FL0044.md
- docs\content\how-tos\rules\FL0045.md = docs\content\how-tos\rules\FL0045.md
- docs\content\how-tos\rules\FL0046.md = docs\content\how-tos\rules\FL0046.md
- docs\content\how-tos\rules\FL0047.md = docs\content\how-tos\rules\FL0047.md
- docs\content\how-tos\rules\FL0048.md = docs\content\how-tos\rules\FL0048.md
- docs\content\how-tos\rules\FL0049.md = docs\content\how-tos\rules\FL0049.md
- docs\content\how-tos\rules\FL0050.md = docs\content\how-tos\rules\FL0050.md
- docs\content\how-tos\rules\FL0051.md = docs\content\how-tos\rules\FL0051.md
- docs\content\how-tos\rules\FL0052.md = docs\content\how-tos\rules\FL0052.md
- docs\content\how-tos\rules\FL0053.md = docs\content\how-tos\rules\FL0053.md
- docs\content\how-tos\rules\FL0054.md = docs\content\how-tos\rules\FL0054.md
- docs\content\how-tos\rules\FL0055.md = docs\content\how-tos\rules\FL0055.md
- docs\content\how-tos\rules\FL0056.md = docs\content\how-tos\rules\FL0056.md
- docs\content\how-tos\rules\FL0057.md = docs\content\how-tos\rules\FL0057.md
- docs\content\how-tos\rules\FL0058.md = docs\content\how-tos\rules\FL0058.md
- docs\content\how-tos\rules\FL0059.md = docs\content\how-tos\rules\FL0059.md
- docs\content\how-tos\rules\FL0060.md = docs\content\how-tos\rules\FL0060.md
- docs\content\how-tos\rules\FL0061.md = docs\content\how-tos\rules\FL0061.md
- docs\content\how-tos\rules\FL0062.md = docs\content\how-tos\rules\FL0062.md
- docs\content\how-tos\rules\FL0063.md = docs\content\how-tos\rules\FL0063.md
- docs\content\how-tos\rules\FL0064.md = docs\content\how-tos\rules\FL0064.md
- docs\content\how-tos\rules\FL0065.md = docs\content\how-tos\rules\FL0065.md
- docs\content\how-tos\rules\FL0066.md = docs\content\how-tos\rules\FL0066.md
- docs\content\how-tos\rules\FL0067.md = docs\content\how-tos\rules\FL0067.md
- docs\content\how-tos\rules\FL0068.md = docs\content\how-tos\rules\FL0068.md
- docs\content\how-tos\rules\FL0069.md = docs\content\how-tos\rules\FL0069.md
- docs\content\how-tos\rules\FL0070.md = docs\content\how-tos\rules\FL0070.md
- docs\content\how-tos\rules\FL0071.md = docs\content\how-tos\rules\FL0071.md
- docs\content\how-tos\rules\FL0072.md = docs\content\how-tos\rules\FL0072.md
- docs\content\how-tos\rules\FL0073.md = docs\content\how-tos\rules\FL0073.md
- docs\content\how-tos\rules\FL0074.md = docs\content\how-tos\rules\FL0074.md
- docs\content\how-tos\rules\FL0075.md = docs\content\how-tos\rules\FL0075.md
- docs\content\how-tos\rules\FL0076.md = docs\content\how-tos\rules\FL0076.md
- docs\content\how-tos\rules\FL0077.md = docs\content\how-tos\rules\FL0077.md
- docs\content\how-tos\rules\FL0078.md = docs\content\how-tos\rules\FL0078.md
- docs\content\how-tos\rules\FL0079.md = docs\content\how-tos\rules\FL0079.md
- docs\content\how-tos\rules\FL0080.md = docs\content\how-tos\rules\FL0080.md
- docs\content\how-tos\rules\FL0081.md = docs\content\how-tos\rules\FL0081.md
- docs\content\how-tos\rules\FL0082.md = docs\content\how-tos\rules\FL0082.md
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|Any CPU = Release|Any CPU
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Debug|x64.ActiveCfg = Debug|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Debug|x64.Build.0 = Debug|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Debug|x86.ActiveCfg = Debug|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Debug|x86.Build.0 = Debug|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Release|Any CPU.Build.0 = Release|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Release|x64.ActiveCfg = Release|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Release|x64.Build.0 = Release|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Release|x86.ActiveCfg = Release|Any CPU
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC}.Release|x86.Build.0 = Release|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Debug|x64.ActiveCfg = Debug|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Debug|x64.Build.0 = Debug|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Debug|x86.ActiveCfg = Debug|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Debug|x86.Build.0 = Debug|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Release|Any CPU.Build.0 = Release|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Release|x64.ActiveCfg = Release|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Release|x64.Build.0 = Release|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Release|x86.ActiveCfg = Release|Any CPU
- {7691E4E4-EC5B-4751-9578-109258A3B1DA}.Release|x86.Build.0 = Release|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Debug|x64.ActiveCfg = Debug|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Debug|x64.Build.0 = Debug|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Debug|x86.ActiveCfg = Debug|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Debug|x86.Build.0 = Debug|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Release|Any CPU.Build.0 = Release|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Release|x64.ActiveCfg = Release|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Release|x64.Build.0 = Release|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Release|x86.ActiveCfg = Release|Any CPU
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40}.Release|x86.Build.0 = Release|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Debug|x64.ActiveCfg = Debug|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Debug|x64.Build.0 = Debug|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Debug|x86.ActiveCfg = Debug|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Debug|x86.Build.0 = Debug|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Release|Any CPU.Build.0 = Release|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Release|x64.ActiveCfg = Release|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Release|x64.Build.0 = Release|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Release|x86.ActiveCfg = Release|Any CPU
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE}.Release|x86.Build.0 = Release|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Debug|x64.ActiveCfg = Debug|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Debug|x64.Build.0 = Debug|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Debug|x86.ActiveCfg = Debug|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Debug|x86.Build.0 = Debug|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Release|Any CPU.Build.0 = Release|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Release|x64.ActiveCfg = Release|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Release|x64.Build.0 = Release|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Release|x86.ActiveCfg = Release|Any CPU
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0}.Release|x86.Build.0 = Release|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Debug|x64.ActiveCfg = Debug|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Debug|x64.Build.0 = Debug|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Debug|x86.ActiveCfg = Debug|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Debug|x86.Build.0 = Debug|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Release|Any CPU.Build.0 = Release|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Release|x64.ActiveCfg = Release|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Release|x64.Build.0 = Release|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Release|x86.ActiveCfg = Release|Any CPU
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}.Release|x86.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {AC24094C-4AB5-4A6B-8430-3D21EF788AEC} = {40C2798B-7078-4D4F-BD37-195240CB827B}
- {7691E4E4-EC5B-4751-9578-109258A3B1DA} = {40C2798B-7078-4D4F-BD37-195240CB827B}
- {E51042D9-CE14-4373-AE1E-FEB78FE23F40} = {1CD44876-BCDC-4C93-9DC2-C45244BD62AE}
- {0DE70980-49E9-4613-84D4-FCF6ACABA5EE} = {1CD44876-BCDC-4C93-9DC2-C45244BD62AE}
- {73AD322D-2E3F-45C4-8DB2-179571DECCD0} = {1CD44876-BCDC-4C93-9DC2-C45244BD62AE}
- {B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0} = {1CD44876-BCDC-4C93-9DC2-C45244BD62AE}
- {E1E03FFE-30DF-4522-83DA-9089147B431E} = {270E691D-ECA1-4BC5-B851-C5431A64E9FA}
- {AEBB56D7-30B4-40D7-B065-54B8BE960298} = {E1E03FFE-30DF-4522-83DA-9089147B431E}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {B54B4B7D-F019-48A3-BB5B-635B68FE41C3}
- EndGlobalSection
-EndGlobal
diff --git a/FSharpLint.slnx b/FSharpLint.slnx
new file mode 100644
index 000000000..2d3d31087
--- /dev/null
+++ b/FSharpLint.slnx
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build.fsx b/build.fsx
index 1942bc876..cb64e6246 100644
--- a/build.fsx
+++ b/build.fsx
@@ -47,6 +47,7 @@ Target.initEnvironment()
// --------------------------------------------------------------------------------------
let project = "FSharpLint"
+let solutionFileName = "FSharpLint.slnx"
let authors = "Matthew Mcveigh"
@@ -139,7 +140,7 @@ Target.create "Clean" (fun _ ->
)
Target.create "Build" (fun _ ->
- DotNet.build id "FSharpLint.sln"
+ DotNet.build id solutionFileName
)
let filterPerformanceTests (p:DotNet.TestOptions) = { p with Filter = Some "\"TestCategory!=Performance\""; Configuration = DotNet.Release }
@@ -168,7 +169,7 @@ Target.create "BuildRelease" (fun _ ->
OutputPath = Some buildDir
MSBuildParams = { p.MSBuildParams with Properties = properties }
}
- ) "FSharpLint.sln"
+ ) solutionFileName
)
@@ -188,7 +189,7 @@ Target.create "Pack" (fun _ ->
OutputPath = Some nugetDir
MSBuildParams = { p.MSBuildParams with Properties = properties }
}
- ) "FSharpLint.sln"
+ ) solutionFileName
)
Target.create "Push" (fun _ ->
@@ -250,7 +251,7 @@ Target.create "SelfCheck" (fun _ ->
let srcDir = Path.Combine(rootDir.FullName, "src") |> DirectoryInfo
let consoleProj = Path.Combine(srcDir.FullName, "FSharpLint.Console", "FSharpLint.Console.fsproj") |> FileInfo
- let sol = Path.Combine(rootDir.FullName, "FSharpLint.sln") |> FileInfo
+ let sol = Path.Combine(rootDir.FullName, solutionFileName) |> FileInfo
exec "dotnet" $"run lint %s{sol.FullName}" consoleProj.Directory.FullName
)
diff --git a/src/FSharpLint.Console/FSharpLint.Console.fsproj b/src/FSharpLint.Console/FSharpLint.Console.fsproj
index 028d418ad..5be5cdf16 100644
--- a/src/FSharpLint.Console/FSharpLint.Console.fsproj
+++ b/src/FSharpLint.Console/FSharpLint.Console.fsproj
@@ -15,6 +15,12 @@
Major
+
+
+ <_Parameter1>FSharpLint.Console.Tests
+
+
+
diff --git a/src/FSharpLint.Console/Program.fs b/src/FSharpLint.Console/Program.fs
index 85174ca67..fac9a7418 100644
--- a/src/FSharpLint.Console/Program.fs
+++ b/src/FSharpLint.Console/Program.fs
@@ -3,9 +3,9 @@
open Argu
open System
open System.IO
+open System.Reflection
open FSharpLint.Framework
open FSharpLint.Application
-open System.Reflection
/// Output format the linter will use.
type private OutputFormat =
@@ -13,7 +13,7 @@ type private OutputFormat =
| MSBuild = 2
/// File type the linter is running against.
-type private FileType =
+type internal FileType =
| Project = 1
| Solution = 2
| File = 3
@@ -60,12 +60,12 @@ let private parserProgress (output:Output.IOutput) = function
|> output.WriteError
/// Infers the file type of the target based on its file extension.
-let private inferFileType (target:string) =
+let internal inferFileType (target:string) =
if target.EndsWith ".fs" || target.EndsWith ".fsx" then
FileType.File
else if target.EndsWith ".fsproj" then
FileType.Project
- else if target.EndsWith ".sln" then
+ else if target.EndsWith ".slnx" || target.EndsWith ".slnf" || target.EndsWith ".sln" then
FileType.Solution
else
FileType.Source
diff --git a/src/FSharpLint.Core/Application/Lint.fs b/src/FSharpLint.Core/Application/Lint.fs
index 2ad5e7084..f1fb06839 100644
--- a/src/FSharpLint.Core/Application/Lint.fs
+++ b/src/FSharpLint.Core/Application/Lint.fs
@@ -9,6 +9,7 @@ open System.Threading
open FSharp.Compiler.Text
open FSharp.Compiler.Diagnostics
open FSharp.Compiler.CodeAnalysis
+open Microsoft.Build.Construction
open Ionide.ProjInfo.ProjectSystem
open Ionide.ProjInfo.FCS
open FSharpLint.Core
@@ -464,36 +465,41 @@ module Lint =
| Ok config ->
let optionalParams = { optionalParams with Configuration = ConfigurationParam.Configuration config }
- let projectsInSolution =
- File.ReadAllText(solutionFilePath)
- |> String.toLines
- |> Array.filter (fun (s, _, _) -> s.StartsWith("Project") && s.Contains(".fsproj"))
- |> Array.map (fun (s, _, _) ->
- let endIndex = s.IndexOf(".fsproj") + 7
- let startIndex = s.IndexOf(",") + 1
- let projectPath = s.Substring(startIndex, endIndex - startIndex).Trim([|'"'; ' '|])
- let projectPath =
- if Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then
+ try
+ // Use Microsoft.Build.Construction.SolutionFile for modern solution parsing
+ let solutionFile = SolutionFile.Parse(solutionFilePath)
+
+ let projectsInSolution =
+ solutionFile.ProjectsInOrder
+ |> Seq.filter (fun project ->
+ project.ProjectType = SolutionProjectType.KnownToBeMSBuildFormat &&
+ project.RelativePath.EndsWith(".fsproj"))
+ |> Seq.map (fun project ->
+ let projectPath = Path.Combine(solutionFolder, project.RelativePath)
+ if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then
projectPath
- else // For non-Windows, we need to convert the project path in the solution to Unix format.
- projectPath.Replace("\\", "/")
- Path.Combine(solutionFolder, projectPath))
-
- let (successes, failures) =
- projectsInSolution
- |> Array.map (fun projectFilePath -> lintProject optionalParams projectFilePath toolsPath)
- |> Array.fold (fun (successes, failures) result ->
- match result with
- | LintResult.Success warnings ->
- (List.append warnings successes, failures)
- | LintResult.Failure err ->
- (successes, err :: failures)) ([], [])
-
- match failures with
- | [] ->
- LintResult.Success successes
- | firstErr :: _ ->
- LintResult.Failure firstErr
+ else // For non-Windows, ensure Unix format
+ projectPath.Replace("\\", "/"))
+ |> Seq.toArray
+
+ let (successes, failures) =
+ projectsInSolution
+ |> Array.map (fun projectFilePath -> lintProject optionalParams projectFilePath toolsPath)
+ |> Array.fold (fun (successes, failures) result ->
+ match result with
+ | LintResult.Success warnings ->
+ (List.append warnings successes, failures)
+ | LintResult.Failure err ->
+ (successes, err :: failures)) ([], [])
+
+ match failures with
+ | [] ->
+ LintResult.Success successes
+ | firstErr :: _ ->
+ LintResult.Failure firstErr
+ with
+ | ex ->
+ LintResult.Failure (MSBuildFailedToLoadProjectFile (solutionFilePath, BuildFailure.InvalidProjectFileMessage ex.Message))
| Error err -> LintResult.Failure (RunTimeConfigError err)
else
diff --git a/src/FSharpLint.Core/FSharpLint.Core.fsproj b/src/FSharpLint.Core/FSharpLint.Core.fsproj
index 5fac0ce03..f6dac62ba 100644
--- a/src/FSharpLint.Core/FSharpLint.Core.fsproj
+++ b/src/FSharpLint.Core/FSharpLint.Core.fsproj
@@ -127,6 +127,9 @@
+
+
+
Always
@@ -142,7 +145,6 @@
-
diff --git a/tests/FSharpLint.Console.Tests/TestApp.fs b/tests/FSharpLint.Console.Tests/TestApp.fs
index 8b320fe2d..322a39cab 100644
--- a/tests/FSharpLint.Console.Tests/TestApp.fs
+++ b/tests/FSharpLint.Console.Tests/TestApp.fs
@@ -117,3 +117,25 @@ type TestConsoleApplication() =
Assert.AreEqual(-1, returnCode)
Assert.AreEqual(set ["Use prefix syntax for generic type."], errors)
+
+open FSharpLint.Console.Program
+
+[]
+type TestFileTypeInference() =
+
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ member _.``File type inference test cases``(filename: string, expectedType: int) =
+ let result = FSharpLint.Console.Program.inferFileType filename
+ let expectedType = enum(expectedType)
+ Assert.AreEqual(expectedType, result)
diff --git a/tests/FSharpLint.FunctionalTest.TestedProject/FSharpLint.FunctionalTest.TestedProject.slnf b/tests/FSharpLint.FunctionalTest.TestedProject/FSharpLint.FunctionalTest.TestedProject.slnf
new file mode 100644
index 000000000..898667fe4
--- /dev/null
+++ b/tests/FSharpLint.FunctionalTest.TestedProject/FSharpLint.FunctionalTest.TestedProject.slnf
@@ -0,0 +1,9 @@
+{
+ "solution": {
+ "path": "FSharpLint.FunctionalTest.TestedProject.slnx",
+ "projects": [
+ "FSharpLint.FunctionalTest.TestedProject.MultiTarget\\FSharpLint.FunctionalTest.TestedProject.MultiTarget.fsproj",
+ "FSharpLint.FunctionalTest.TestedProject.NetCore\\FSharpLint.FunctionalTest.TestedProject.NetCore.fsproj"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/tests/FSharpLint.FunctionalTest.TestedProject/FSharpLint.FunctionalTest.TestedProject.slnx b/tests/FSharpLint.FunctionalTest.TestedProject/FSharpLint.FunctionalTest.TestedProject.slnx
new file mode 100644
index 000000000..334a11125
--- /dev/null
+++ b/tests/FSharpLint.FunctionalTest.TestedProject/FSharpLint.FunctionalTest.TestedProject.slnx
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/tests/FSharpLint.FunctionalTest/TestApi.fs b/tests/FSharpLint.FunctionalTest/TestApi.fs
index ffa91a3aa..f42a6ffb2 100644
--- a/tests/FSharpLint.FunctionalTest/TestApi.fs
+++ b/tests/FSharpLint.FunctionalTest/TestApi.fs
@@ -102,40 +102,28 @@ module TestApi =
| LintResult.Failure err ->
Assert.True(false, string err)
- []
- member _.``Lint solution via absolute path``() =
+ []
+ []
+ []
+ member _.``Lint solution via absolute path``(solutionFileName: string, expectedWarnings: int) =
let projectPath = basePath > "tests" > "FSharpLint.FunctionalTest.TestedProject"
- let solutionFile = projectPath > "FSharpLint.FunctionalTest.TestedProject.sln"
+ let solutionFile = projectPath > solutionFileName
let result = lintSolution OptionalLintParameters.Default solutionFile toolsPath
match result with
| LintResult.Success warnings ->
- Assert.AreEqual(18, warnings.Length)
- | LintResult.Failure err ->
- Assert.True(false, string err)
-
-#if NETCOREAPP // GetRelativePath is netcore-only
- []
- member _.``Lint project via relative path``() =
- let projectPath = basePath > "tests" > "FSharpLint.FunctionalTest.TestedProject" > "FSharpLint.FunctionalTest.TestedProject.NetCore"
- let projectFile = projectPath > "FSharpLint.FunctionalTest.TestedProject.NetCore.fsproj"
-
- let relativePathToProjectFile = Path.GetRelativePath (Directory.GetCurrentDirectory(), projectFile)
-
- let result = lintProject OptionalLintParameters.Default relativePathToProjectFile toolsPath
-
- match result with
- | LintResult.Success warnings ->
- Assert.AreEqual(9, warnings.Length)
+ Assert.AreEqual(expectedWarnings, warnings.Length)
| LintResult.Failure err ->
Assert.True(false, string err)
- ()
- []
- member _.``Lint solution via relative path``() =
+#if NETCOREAPP
+ []
+ []
+ []
+ member _.``Lint solution via relative path``(solutionFileName: string, expectedWarnings: int) =
let projectPath = basePath > "tests" > "FSharpLint.FunctionalTest.TestedProject"
- let solutionFile = projectPath > "FSharpLint.FunctionalTest.TestedProject.sln"
+ let solutionFile = projectPath > solutionFileName
let relativePathToSolutionFile = Path.GetRelativePath (Directory.GetCurrentDirectory(), solutionFile)
@@ -143,7 +131,7 @@ module TestApi =
match result with
| LintResult.Success warnings ->
- Assert.AreEqual(18, warnings.Length)
+ Assert.AreEqual(expectedWarnings, warnings.Length)
| LintResult.Failure err ->
Assert.True(false, string err)
#endif