diff --git a/.gitattributes b/.gitattributes index ac2ad936669..25b46f84a6d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -26,4 +26,6 @@ launcher.in text eol=lf config.make.in text eol=lf targets.make text eol=lf configure.ac text eol=lf -Makefile.in text eol=lf \ No newline at end of file +Makefile.in text eol=lf + +*.bsl linguist-vendored=true diff --git a/.gitignore b/.gitignore index 133aa1231be..1a7e530e494 100644 --- a/.gitignore +++ b/.gitignore @@ -118,3 +118,6 @@ source_link.json /VSRelease/net40/bin System.ValueTuple.dll tests/fsharpqa/testenv/bin/System.ValueTuple.dll +*/.fake +/fcs/packages/ +*/paket-files/ diff --git a/README.md b/README.md index 594ab032e56..b1cd4283bcd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # The F# Language, Library, and Visual F# Tools Repository -You are invited to help producing future releases of the F# language compiler, library, and tools. This repository enables development on Linux, macOS and Windows, along with some automated CI testing for these. +You are invited to help produce future releases of the F# language compiler, library, and tools. This repository enables development on Linux, macOS and Windows, along with some automated CI testing for these. * [About F#](http://fsharp.org) * [Testimonials](http://fsharp.org/testimonials) diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 0ee5cddaad4..90a1a3a4e0a 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26730.3 +VisualStudioVersion = 15.0.27005.2 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Private", "src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject @@ -144,10 +144,14 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TestTP", "tests\service\dat EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceFile", "vsintegration\ItemTemplates\ResourceFile\ResourceFile.csproj", "{0385564F-07B4-4264-AB8A-17C393E9140C}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Build.UnitTests", "src\fsharp\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj", "{400FAB03-786E-40CC-85A8-04B0C2869B14}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 + Proto|Any CPU = Proto|Any CPU + Proto|x86 = Proto|x86 Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 EndGlobalSection @@ -156,6 +160,10 @@ Global {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.ActiveCfg = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.Build.0 = Debug|Any CPU + {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Proto|Any CPU.Build.0 = Proto|Any CPU + {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Proto|x86.ActiveCfg = Proto|Any CPU + {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Proto|x86.Build.0 = Proto|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.ActiveCfg = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.Build.0 = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.ActiveCfg = Release|Any CPU @@ -164,6 +172,10 @@ Global {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Debug|Any CPU.Build.0 = Debug|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Debug|x86.ActiveCfg = Debug|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Debug|x86.Build.0 = Debug|Any CPU + {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Proto|Any CPU.Build.0 = Proto|Any CPU + {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Proto|x86.ActiveCfg = Proto|Any CPU + {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Proto|x86.Build.0 = Proto|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Release|Any CPU.ActiveCfg = Release|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Release|Any CPU.Build.0 = Release|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Release|x86.ActiveCfg = Release|Any CPU @@ -172,6 +184,10 @@ Global {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|Any CPU.Build.0 = Debug|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|x86.ActiveCfg = Debug|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|x86.Build.0 = Debug|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Proto|Any CPU.Build.0 = Proto|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Proto|x86.ActiveCfg = Proto|Any CPU + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Proto|x86.Build.0 = Proto|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|Any CPU.ActiveCfg = Release|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|Any CPU.Build.0 = Release|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|x86.ActiveCfg = Release|Any CPU @@ -180,6 +196,10 @@ Global {DED3BBD7-53F4-428A-8C9F-27968E768605}.Debug|Any CPU.Build.0 = Debug|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Debug|x86.ActiveCfg = Debug|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Debug|x86.Build.0 = Debug|Any CPU + {DED3BBD7-53F4-428A-8C9F-27968E768605}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {DED3BBD7-53F4-428A-8C9F-27968E768605}.Proto|Any CPU.Build.0 = Proto|Any CPU + {DED3BBD7-53F4-428A-8C9F-27968E768605}.Proto|x86.ActiveCfg = Proto|Any CPU + {DED3BBD7-53F4-428A-8C9F-27968E768605}.Proto|x86.Build.0 = Proto|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Release|Any CPU.ActiveCfg = Release|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Release|Any CPU.Build.0 = Release|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Release|x86.ActiveCfg = Release|Any CPU @@ -188,6 +208,10 @@ Global {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Debug|x86.ActiveCfg = Debug|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Debug|x86.Build.0 = Debug|Any CPU + {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Proto|Any CPU.Build.0 = Proto|Any CPU + {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Proto|x86.ActiveCfg = Proto|Any CPU + {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Proto|x86.Build.0 = Proto|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Release|Any CPU.ActiveCfg = Release|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Release|Any CPU.Build.0 = Release|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Release|x86.ActiveCfg = Release|Any CPU @@ -196,6 +220,10 @@ Global {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Debug|Any CPU.Build.0 = Debug|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Debug|x86.ActiveCfg = Debug|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Debug|x86.Build.0 = Debug|Any CPU + {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Proto|Any CPU.Build.0 = Proto|Any CPU + {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Proto|x86.ActiveCfg = Proto|Any CPU + {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Proto|x86.Build.0 = Proto|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Release|Any CPU.ActiveCfg = Release|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Release|Any CPU.Build.0 = Release|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Release|x86.ActiveCfg = Release|Any CPU @@ -204,6 +232,10 @@ Global {65E0E82A-EACE-4787-8994-888674C2FE87}.Debug|Any CPU.Build.0 = Debug|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Debug|x86.ActiveCfg = Debug|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Debug|x86.Build.0 = Debug|Any CPU + {65E0E82A-EACE-4787-8994-888674C2FE87}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {65E0E82A-EACE-4787-8994-888674C2FE87}.Proto|Any CPU.Build.0 = Proto|Any CPU + {65E0E82A-EACE-4787-8994-888674C2FE87}.Proto|x86.ActiveCfg = Proto|Any CPU + {65E0E82A-EACE-4787-8994-888674C2FE87}.Proto|x86.Build.0 = Proto|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Release|Any CPU.ActiveCfg = Release|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Release|Any CPU.Build.0 = Release|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Release|x86.ActiveCfg = Release|Any CPU @@ -212,6 +244,10 @@ Global {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Debug|Any CPU.Build.0 = Debug|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Debug|x86.ActiveCfg = Debug|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Debug|x86.Build.0 = Debug|Any CPU + {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Proto|Any CPU.Build.0 = Proto|Any CPU + {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Proto|x86.ActiveCfg = Proto|Any CPU + {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Proto|x86.Build.0 = Proto|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Release|Any CPU.ActiveCfg = Release|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Release|Any CPU.Build.0 = Release|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Release|x86.ActiveCfg = Release|Any CPU @@ -220,6 +256,10 @@ Global {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Debug|Any CPU.Build.0 = Debug|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Debug|x86.ActiveCfg = Debug|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Debug|x86.Build.0 = Debug|Any CPU + {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Proto|Any CPU.Build.0 = Proto|Any CPU + {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Proto|x86.ActiveCfg = Proto|Any CPU + {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Proto|x86.Build.0 = Proto|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Release|Any CPU.ActiveCfg = Release|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Release|Any CPU.Build.0 = Release|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Release|x86.ActiveCfg = Release|Any CPU @@ -228,6 +268,10 @@ Global {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Debug|Any CPU.Build.0 = Debug|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Debug|x86.ActiveCfg = Debug|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Debug|x86.Build.0 = Debug|Any CPU + {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Proto|Any CPU.Build.0 = Proto|Any CPU + {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Proto|x86.ActiveCfg = Proto|Any CPU + {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Proto|x86.Build.0 = Proto|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Release|Any CPU.ActiveCfg = Release|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Release|Any CPU.Build.0 = Release|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Release|x86.ActiveCfg = Release|Any CPU @@ -236,6 +280,10 @@ Global {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Debug|x86.ActiveCfg = Debug|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Debug|x86.Build.0 = Debug|Any CPU + {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Proto|Any CPU.Build.0 = Proto|Any CPU + {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Proto|x86.ActiveCfg = Proto|Any CPU + {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Proto|x86.Build.0 = Proto|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Release|Any CPU.ActiveCfg = Release|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Release|Any CPU.Build.0 = Release|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Release|x86.ActiveCfg = Release|Any CPU @@ -244,6 +292,10 @@ Global {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Debug|x86.ActiveCfg = Debug|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Debug|x86.Build.0 = Debug|Any CPU + {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Proto|Any CPU.Build.0 = Proto|Any CPU + {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Proto|x86.ActiveCfg = Proto|Any CPU + {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Proto|x86.Build.0 = Proto|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Release|Any CPU.ActiveCfg = Release|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Release|Any CPU.Build.0 = Release|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Release|x86.ActiveCfg = Release|Any CPU @@ -252,6 +304,10 @@ Global {DA39AD38-4A58-47BF-9215-E49768295169}.Debug|Any CPU.Build.0 = Debug|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Debug|x86.ActiveCfg = Debug|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Debug|x86.Build.0 = Debug|Any CPU + {DA39AD38-4A58-47BF-9215-E49768295169}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {DA39AD38-4A58-47BF-9215-E49768295169}.Proto|Any CPU.Build.0 = Proto|Any CPU + {DA39AD38-4A58-47BF-9215-E49768295169}.Proto|x86.ActiveCfg = Proto|Any CPU + {DA39AD38-4A58-47BF-9215-E49768295169}.Proto|x86.Build.0 = Proto|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Release|Any CPU.ActiveCfg = Release|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Release|Any CPU.Build.0 = Release|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Release|x86.ActiveCfg = Release|Any CPU @@ -260,6 +316,10 @@ Global {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Debug|Any CPU.Build.0 = Debug|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Debug|x86.ActiveCfg = Debug|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Debug|x86.Build.0 = Debug|Any CPU + {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Proto|Any CPU.Build.0 = Proto|Any CPU + {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Proto|x86.ActiveCfg = Proto|Any CPU + {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Proto|x86.Build.0 = Proto|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Release|Any CPU.ActiveCfg = Release|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Release|Any CPU.Build.0 = Release|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Release|x86.ActiveCfg = Release|Any CPU @@ -268,6 +328,10 @@ Global {F47196DC-186D-4055-BAF2-658282A12F33}.Debug|Any CPU.Build.0 = Debug|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Debug|x86.ActiveCfg = Debug|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Debug|x86.Build.0 = Debug|Any CPU + {F47196DC-186D-4055-BAF2-658282A12F33}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {F47196DC-186D-4055-BAF2-658282A12F33}.Proto|Any CPU.Build.0 = Proto|Any CPU + {F47196DC-186D-4055-BAF2-658282A12F33}.Proto|x86.ActiveCfg = Proto|Any CPU + {F47196DC-186D-4055-BAF2-658282A12F33}.Proto|x86.Build.0 = Proto|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Release|Any CPU.ActiveCfg = Release|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Release|Any CPU.Build.0 = Release|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Release|x86.ActiveCfg = Release|Any CPU @@ -276,6 +340,10 @@ Global {D4C88934-5893-467E-A55C-A11ECD6479FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Debug|x86.ActiveCfg = Debug|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Debug|x86.Build.0 = Debug|Any CPU + {D4C88934-5893-467E-A55C-A11ECD6479FE}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {D4C88934-5893-467E-A55C-A11ECD6479FE}.Proto|Any CPU.Build.0 = Proto|Any CPU + {D4C88934-5893-467E-A55C-A11ECD6479FE}.Proto|x86.ActiveCfg = Proto|Any CPU + {D4C88934-5893-467E-A55C-A11ECD6479FE}.Proto|x86.Build.0 = Proto|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Release|Any CPU.ActiveCfg = Release|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Release|Any CPU.Build.0 = Release|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Release|x86.ActiveCfg = Release|Any CPU @@ -284,6 +352,10 @@ Global {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Debug|Any CPU.Build.0 = Debug|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Debug|x86.ActiveCfg = Debug|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Debug|x86.Build.0 = Debug|Any CPU + {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Proto|Any CPU.Build.0 = Proto|Any CPU + {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Proto|x86.ActiveCfg = Proto|Any CPU + {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Proto|x86.Build.0 = Proto|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Release|Any CPU.ActiveCfg = Release|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Release|Any CPU.Build.0 = Release|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Release|x86.ActiveCfg = Release|Any CPU @@ -292,6 +364,10 @@ Global {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Debug|x86.ActiveCfg = Debug|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Debug|x86.Build.0 = Debug|Any CPU + {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Proto|Any CPU.Build.0 = Proto|Any CPU + {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Proto|x86.ActiveCfg = Proto|Any CPU + {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Proto|x86.Build.0 = Proto|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Release|Any CPU.ActiveCfg = Release|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Release|Any CPU.Build.0 = Release|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Release|x86.ActiveCfg = Release|Any CPU @@ -300,6 +376,10 @@ Global {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Debug|Any CPU.Build.0 = Debug|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Debug|x86.ActiveCfg = Debug|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Debug|x86.Build.0 = Debug|Any CPU + {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Proto|Any CPU.Build.0 = Proto|Any CPU + {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Proto|x86.ActiveCfg = Proto|Any CPU + {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Proto|x86.Build.0 = Proto|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Release|Any CPU.ActiveCfg = Release|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Release|Any CPU.Build.0 = Release|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Release|x86.ActiveCfg = Release|Any CPU @@ -308,6 +388,10 @@ Global {243A81AC-A954-4601-833A-60EEEFB00FCD}.Debug|Any CPU.Build.0 = Debug|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Debug|x86.ActiveCfg = Debug|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Debug|x86.Build.0 = Debug|Any CPU + {243A81AC-A954-4601-833A-60EEEFB00FCD}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {243A81AC-A954-4601-833A-60EEEFB00FCD}.Proto|Any CPU.Build.0 = Proto|Any CPU + {243A81AC-A954-4601-833A-60EEEFB00FCD}.Proto|x86.ActiveCfg = Proto|Any CPU + {243A81AC-A954-4601-833A-60EEEFB00FCD}.Proto|x86.Build.0 = Proto|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Release|Any CPU.ActiveCfg = Release|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Release|Any CPU.Build.0 = Release|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Release|x86.ActiveCfg = Release|Any CPU @@ -316,6 +400,10 @@ Global {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Debug|Any CPU.Build.0 = Debug|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Debug|x86.ActiveCfg = Debug|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Debug|x86.Build.0 = Debug|Any CPU + {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Proto|Any CPU.Build.0 = Proto|Any CPU + {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Proto|x86.ActiveCfg = Proto|Any CPU + {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Proto|x86.Build.0 = Proto|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Release|Any CPU.ActiveCfg = Release|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Release|Any CPU.Build.0 = Release|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Release|x86.ActiveCfg = Release|Any CPU @@ -324,6 +412,10 @@ Global {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Debug|Any CPU.Build.0 = Debug|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Debug|x86.ActiveCfg = Debug|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Debug|x86.Build.0 = Debug|Any CPU + {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Proto|Any CPU.Build.0 = Proto|Any CPU + {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Proto|x86.ActiveCfg = Proto|Any CPU + {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Proto|x86.Build.0 = Proto|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Release|Any CPU.ActiveCfg = Release|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Release|Any CPU.Build.0 = Release|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Release|x86.ActiveCfg = Release|Any CPU @@ -332,6 +424,10 @@ Global {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Debug|x86.ActiveCfg = Debug|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Debug|x86.Build.0 = Debug|Any CPU + {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Proto|Any CPU.Build.0 = Proto|Any CPU + {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Proto|x86.ActiveCfg = Proto|Any CPU + {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Proto|x86.Build.0 = Proto|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Release|Any CPU.ActiveCfg = Release|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Release|Any CPU.Build.0 = Release|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Release|x86.ActiveCfg = Release|Any CPU @@ -340,6 +436,10 @@ Global {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Debug|Any CPU.Build.0 = Debug|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Debug|x86.ActiveCfg = Debug|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Debug|x86.Build.0 = Debug|Any CPU + {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Proto|Any CPU.Build.0 = Proto|Any CPU + {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Proto|x86.ActiveCfg = Proto|Any CPU + {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Proto|x86.Build.0 = Proto|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Release|Any CPU.ActiveCfg = Release|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Release|Any CPU.Build.0 = Release|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Release|x86.ActiveCfg = Release|Any CPU @@ -348,6 +448,10 @@ Global {702A7979-BCF9-4C41-853E-3ADFC9897890}.Debug|Any CPU.Build.0 = Debug|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Debug|x86.ActiveCfg = Debug|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Debug|x86.Build.0 = Debug|Any CPU + {702A7979-BCF9-4C41-853E-3ADFC9897890}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {702A7979-BCF9-4C41-853E-3ADFC9897890}.Proto|Any CPU.Build.0 = Proto|Any CPU + {702A7979-BCF9-4C41-853E-3ADFC9897890}.Proto|x86.ActiveCfg = Proto|Any CPU + {702A7979-BCF9-4C41-853E-3ADFC9897890}.Proto|x86.Build.0 = Proto|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Release|Any CPU.ActiveCfg = Release|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Release|Any CPU.Build.0 = Release|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Release|x86.ActiveCfg = Release|Any CPU @@ -356,6 +460,10 @@ Global {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Debug|Any CPU.Build.0 = Debug|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Debug|x86.ActiveCfg = Debug|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Debug|x86.Build.0 = Debug|Any CPU + {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Proto|Any CPU.Build.0 = Proto|Any CPU + {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Proto|x86.ActiveCfg = Proto|Any CPU + {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Proto|x86.Build.0 = Proto|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|Any CPU.ActiveCfg = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|Any CPU.Build.0 = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.ActiveCfg = Release|Any CPU @@ -364,6 +472,10 @@ Global {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.Build.0 = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|x86.ActiveCfg = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|x86.Build.0 = Debug|Any CPU + {649FA588-F02E-457C-9FCF-87E46407481E}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {649FA588-F02E-457C-9FCF-87E46407481E}.Proto|Any CPU.Build.0 = Proto|Any CPU + {649FA588-F02E-457C-9FCF-87E46407481E}.Proto|x86.ActiveCfg = Proto|Any CPU + {649FA588-F02E-457C-9FCF-87E46407481E}.Proto|x86.Build.0 = Proto|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Release|Any CPU.ActiveCfg = Release|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Release|Any CPU.Build.0 = Release|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Release|x86.ActiveCfg = Release|Any CPU @@ -372,6 +484,10 @@ Global {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|x86.ActiveCfg = Debug|Any CPU {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|x86.Build.0 = Debug|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Proto|Any CPU.Build.0 = Proto|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Proto|x86.ActiveCfg = Proto|Any CPU + {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Proto|x86.Build.0 = Proto|Any CPU {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|Any CPU.Build.0 = Release|Any CPU {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|x86.ActiveCfg = Release|Any CPU @@ -380,6 +496,10 @@ Global {D0E98C0D-490B-4C61-9329-0862F6E87645}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Debug|x86.ActiveCfg = Debug|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Debug|x86.Build.0 = Debug|Any CPU + {D0E98C0D-490B-4C61-9329-0862F6E87645}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {D0E98C0D-490B-4C61-9329-0862F6E87645}.Proto|Any CPU.Build.0 = Proto|Any CPU + {D0E98C0D-490B-4C61-9329-0862F6E87645}.Proto|x86.ActiveCfg = Proto|Any CPU + {D0E98C0D-490B-4C61-9329-0862F6E87645}.Proto|x86.Build.0 = Proto|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Release|Any CPU.Build.0 = Release|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Release|x86.ActiveCfg = Release|Any CPU @@ -388,6 +508,10 @@ Global {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|Any CPU.Build.0 = Debug|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|x86.ActiveCfg = Debug|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|x86.Build.0 = Debug|Any CPU + {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Proto|Any CPU.Build.0 = Proto|Any CPU + {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Proto|x86.ActiveCfg = Proto|Any CPU + {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Proto|x86.Build.0 = Proto|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Release|Any CPU.ActiveCfg = Release|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Release|Any CPU.Build.0 = Release|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Release|x86.ActiveCfg = Release|Any CPU @@ -396,6 +520,10 @@ Global {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Debug|Any CPU.Build.0 = Debug|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Debug|x86.ActiveCfg = Debug|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Debug|x86.Build.0 = Debug|Any CPU + {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Proto|Any CPU.Build.0 = Proto|Any CPU + {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Proto|x86.ActiveCfg = Proto|Any CPU + {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Proto|x86.Build.0 = Proto|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Release|Any CPU.ActiveCfg = Release|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Release|Any CPU.Build.0 = Release|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Release|x86.ActiveCfg = Release|Any CPU @@ -404,6 +532,10 @@ Global {88E2D422-6852-46E3-A740-83E391DC7973}.Debug|Any CPU.Build.0 = Debug|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Debug|x86.ActiveCfg = Debug|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Debug|x86.Build.0 = Debug|Any CPU + {88E2D422-6852-46E3-A740-83E391DC7973}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {88E2D422-6852-46E3-A740-83E391DC7973}.Proto|Any CPU.Build.0 = Proto|Any CPU + {88E2D422-6852-46E3-A740-83E391DC7973}.Proto|x86.ActiveCfg = Proto|Any CPU + {88E2D422-6852-46E3-A740-83E391DC7973}.Proto|x86.Build.0 = Proto|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Release|Any CPU.ActiveCfg = Release|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Release|Any CPU.Build.0 = Release|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Release|x86.ActiveCfg = Release|Any CPU @@ -412,6 +544,10 @@ Global {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Debug|Any CPU.Build.0 = Debug|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Debug|x86.ActiveCfg = Debug|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Debug|x86.Build.0 = Debug|Any CPU + {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Proto|Any CPU.Build.0 = Proto|Any CPU + {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Proto|x86.ActiveCfg = Proto|Any CPU + {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Proto|x86.Build.0 = Proto|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Release|Any CPU.ActiveCfg = Release|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Release|Any CPU.Build.0 = Release|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Release|x86.ActiveCfg = Release|Any CPU @@ -420,6 +556,10 @@ Global {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Debug|x86.ActiveCfg = Debug|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Debug|x86.Build.0 = Debug|Any CPU + {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Proto|Any CPU.Build.0 = Proto|Any CPU + {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Proto|x86.ActiveCfg = Proto|Any CPU + {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Proto|x86.Build.0 = Proto|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Release|Any CPU.Build.0 = Release|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Release|x86.ActiveCfg = Release|Any CPU @@ -428,6 +568,10 @@ Global {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Debug|Any CPU.Build.0 = Debug|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Debug|x86.ActiveCfg = Debug|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Debug|x86.Build.0 = Debug|Any CPU + {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Proto|Any CPU.Build.0 = Proto|Any CPU + {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Proto|x86.ActiveCfg = Proto|Any CPU + {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Proto|x86.Build.0 = Proto|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Release|Any CPU.ActiveCfg = Release|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Release|Any CPU.Build.0 = Release|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Release|x86.ActiveCfg = Release|Any CPU @@ -436,6 +580,10 @@ Global {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Debug|Any CPU.Build.0 = Debug|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Debug|x86.ActiveCfg = Debug|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Debug|x86.Build.0 = Debug|Any CPU + {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Proto|Any CPU.Build.0 = Proto|Any CPU + {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Proto|x86.ActiveCfg = Proto|Any CPU + {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Proto|x86.Build.0 = Proto|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Release|Any CPU.ActiveCfg = Release|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Release|Any CPU.Build.0 = Release|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Release|x86.ActiveCfg = Release|Any CPU @@ -444,6 +592,10 @@ Global {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Debug|Any CPU.Build.0 = Debug|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Debug|x86.ActiveCfg = Debug|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Debug|x86.Build.0 = Debug|Any CPU + {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Proto|Any CPU.Build.0 = Proto|Any CPU + {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Proto|x86.ActiveCfg = Proto|Any CPU + {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Proto|x86.Build.0 = Proto|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Release|Any CPU.ActiveCfg = Release|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Release|Any CPU.Build.0 = Release|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Release|x86.ActiveCfg = Release|Any CPU @@ -452,6 +604,10 @@ Global {DB374A0C-7560-479F-9B21-D37C81F7624F}.Debug|Any CPU.Build.0 = Debug|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Debug|x86.ActiveCfg = Debug|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Debug|x86.Build.0 = Debug|Any CPU + {DB374A0C-7560-479F-9B21-D37C81F7624F}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {DB374A0C-7560-479F-9B21-D37C81F7624F}.Proto|Any CPU.Build.0 = Proto|Any CPU + {DB374A0C-7560-479F-9B21-D37C81F7624F}.Proto|x86.ActiveCfg = Proto|Any CPU + {DB374A0C-7560-479F-9B21-D37C81F7624F}.Proto|x86.Build.0 = Proto|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Release|Any CPU.ActiveCfg = Release|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Release|Any CPU.Build.0 = Release|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Release|x86.ActiveCfg = Release|Any CPU @@ -460,6 +616,10 @@ Global {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Debug|Any CPU.Build.0 = Debug|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Debug|x86.ActiveCfg = Debug|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Debug|x86.Build.0 = Debug|Any CPU + {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Proto|Any CPU.Build.0 = Proto|Any CPU + {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Proto|x86.ActiveCfg = Proto|Any CPU + {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Proto|x86.Build.0 = Proto|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Release|Any CPU.Build.0 = Release|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Release|x86.ActiveCfg = Release|Any CPU @@ -468,6 +628,10 @@ Global {6BA13AA4-C25F-480F-856B-8E8000299A72}.Debug|Any CPU.Build.0 = Debug|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Debug|x86.ActiveCfg = Debug|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Debug|x86.Build.0 = Debug|Any CPU + {6BA13AA4-C25F-480F-856B-8E8000299A72}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {6BA13AA4-C25F-480F-856B-8E8000299A72}.Proto|Any CPU.Build.0 = Proto|Any CPU + {6BA13AA4-C25F-480F-856B-8E8000299A72}.Proto|x86.ActiveCfg = Proto|Any CPU + {6BA13AA4-C25F-480F-856B-8E8000299A72}.Proto|x86.Build.0 = Proto|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Release|Any CPU.ActiveCfg = Release|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Release|Any CPU.Build.0 = Release|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Release|x86.ActiveCfg = Release|Any CPU @@ -476,6 +640,10 @@ Global {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Debug|Any CPU.Build.0 = Debug|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Debug|x86.ActiveCfg = Debug|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Debug|x86.Build.0 = Debug|Any CPU + {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Proto|Any CPU.Build.0 = Proto|Any CPU + {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Proto|x86.ActiveCfg = Proto|Any CPU + {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Proto|x86.Build.0 = Proto|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Release|Any CPU.ActiveCfg = Release|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Release|Any CPU.Build.0 = Release|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Release|x86.ActiveCfg = Release|Any CPU @@ -484,6 +652,10 @@ Global {A333B85A-DC23-49B6-9797-B89A7951E92D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Debug|x86.ActiveCfg = Debug|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Debug|x86.Build.0 = Debug|Any CPU + {A333B85A-DC23-49B6-9797-B89A7951E92D}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {A333B85A-DC23-49B6-9797-B89A7951E92D}.Proto|Any CPU.Build.0 = Proto|Any CPU + {A333B85A-DC23-49B6-9797-B89A7951E92D}.Proto|x86.ActiveCfg = Proto|Any CPU + {A333B85A-DC23-49B6-9797-B89A7951E92D}.Proto|x86.Build.0 = Proto|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Release|Any CPU.Build.0 = Release|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Release|x86.ActiveCfg = Release|Any CPU @@ -492,6 +664,10 @@ Global {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Debug|Any CPU.Build.0 = Debug|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Debug|x86.ActiveCfg = Debug|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Debug|x86.Build.0 = Debug|Any CPU + {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Proto|Any CPU.Build.0 = Proto|Any CPU + {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Proto|x86.ActiveCfg = Proto|Any CPU + {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Proto|x86.Build.0 = Proto|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Release|Any CPU.ActiveCfg = Release|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Release|Any CPU.Build.0 = Release|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Release|x86.ActiveCfg = Release|Any CPU @@ -500,6 +676,10 @@ Global {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Debug|x86.ActiveCfg = Debug|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Debug|x86.Build.0 = Debug|Any CPU + {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Proto|Any CPU.Build.0 = Proto|Any CPU + {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Proto|x86.ActiveCfg = Proto|Any CPU + {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Proto|x86.Build.0 = Proto|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Release|Any CPU.ActiveCfg = Release|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Release|Any CPU.Build.0 = Release|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Release|x86.ActiveCfg = Release|Any CPU @@ -508,6 +688,10 @@ Global {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Debug|Any CPU.Build.0 = Debug|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Debug|x86.ActiveCfg = Debug|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Debug|x86.Build.0 = Debug|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Proto|Any CPU.Build.0 = Proto|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Proto|x86.ActiveCfg = Proto|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Proto|x86.Build.0 = Proto|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|Any CPU.ActiveCfg = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|Any CPU.Build.0 = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.ActiveCfg = Release|Any CPU @@ -516,6 +700,10 @@ Global {59ADCE46-9740-4079-834D-9A03A3494EBC}.Debug|Any CPU.Build.0 = Debug|Any CPU {59ADCE46-9740-4079-834D-9A03A3494EBC}.Debug|x86.ActiveCfg = Debug|Any CPU {59ADCE46-9740-4079-834D-9A03A3494EBC}.Debug|x86.Build.0 = Debug|Any CPU + {59ADCE46-9740-4079-834D-9A03A3494EBC}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {59ADCE46-9740-4079-834D-9A03A3494EBC}.Proto|Any CPU.Build.0 = Proto|Any CPU + {59ADCE46-9740-4079-834D-9A03A3494EBC}.Proto|x86.ActiveCfg = Proto|Any CPU + {59ADCE46-9740-4079-834D-9A03A3494EBC}.Proto|x86.Build.0 = Proto|Any CPU {59ADCE46-9740-4079-834D-9A03A3494EBC}.Release|Any CPU.ActiveCfg = Release|Any CPU {59ADCE46-9740-4079-834D-9A03A3494EBC}.Release|Any CPU.Build.0 = Release|Any CPU {59ADCE46-9740-4079-834D-9A03A3494EBC}.Release|x86.ActiveCfg = Release|Any CPU @@ -524,6 +712,10 @@ Global {E6A45CDF-B408-420F-B475-74611BEFC52B}.Debug|Any CPU.Build.0 = Debug|Any CPU {E6A45CDF-B408-420F-B475-74611BEFC52B}.Debug|x86.ActiveCfg = Debug|Any CPU {E6A45CDF-B408-420F-B475-74611BEFC52B}.Debug|x86.Build.0 = Debug|Any CPU + {E6A45CDF-B408-420F-B475-74611BEFC52B}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {E6A45CDF-B408-420F-B475-74611BEFC52B}.Proto|Any CPU.Build.0 = Proto|Any CPU + {E6A45CDF-B408-420F-B475-74611BEFC52B}.Proto|x86.ActiveCfg = Proto|Any CPU + {E6A45CDF-B408-420F-B475-74611BEFC52B}.Proto|x86.Build.0 = Proto|Any CPU {E6A45CDF-B408-420F-B475-74611BEFC52B}.Release|Any CPU.ActiveCfg = Release|Any CPU {E6A45CDF-B408-420F-B475-74611BEFC52B}.Release|Any CPU.Build.0 = Release|Any CPU {E6A45CDF-B408-420F-B475-74611BEFC52B}.Release|x86.ActiveCfg = Release|Any CPU @@ -532,6 +724,10 @@ Global {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Debug|Any CPU.Build.0 = Debug|Any CPU {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Debug|x86.ActiveCfg = Debug|Any CPU {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Debug|x86.Build.0 = Debug|Any CPU + {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Proto|Any CPU.Build.0 = Proto|Any CPU + {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Proto|x86.ActiveCfg = Proto|Any CPU + {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Proto|x86.Build.0 = Proto|Any CPU {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Release|Any CPU.ActiveCfg = Release|Any CPU {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Release|Any CPU.Build.0 = Release|Any CPU {4239EFEA-E746-446A-BF7A-51FCBAB13946}.Release|x86.ActiveCfg = Release|Any CPU @@ -540,6 +736,10 @@ Global {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Debug|Any CPU.Build.0 = Debug|Any CPU {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Debug|x86.ActiveCfg = Debug|Any CPU {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Debug|x86.Build.0 = Debug|Any CPU + {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Proto|Any CPU.Build.0 = Proto|Any CPU + {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Proto|x86.ActiveCfg = Proto|Any CPU + {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Proto|x86.Build.0 = Proto|Any CPU {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Release|Any CPU.ActiveCfg = Release|Any CPU {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Release|Any CPU.Build.0 = Release|Any CPU {2E60864A-E3FF-4BCC-810F-DC7C34E6B236}.Release|x86.ActiveCfg = Release|Any CPU @@ -548,6 +748,10 @@ Global {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Debug|x86.ActiveCfg = Debug|Any CPU {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Debug|x86.Build.0 = Debug|Any CPU + {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Proto|Any CPU.Build.0 = Proto|Any CPU + {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Proto|x86.ActiveCfg = Proto|Any CPU + {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Proto|x86.Build.0 = Proto|Any CPU {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Release|Any CPU.ActiveCfg = Release|Any CPU {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Release|Any CPU.Build.0 = Release|Any CPU {E7FA3A71-51AF-4FCA-9C2F-7C853E515903}.Release|x86.ActiveCfg = Release|Any CPU @@ -556,6 +760,10 @@ Global {C4586A06-1402-48BC-8E35-A1B8642F895B}.Debug|Any CPU.Build.0 = Debug|Any CPU {C4586A06-1402-48BC-8E35-A1B8642F895B}.Debug|x86.ActiveCfg = Debug|Any CPU {C4586A06-1402-48BC-8E35-A1B8642F895B}.Debug|x86.Build.0 = Debug|Any CPU + {C4586A06-1402-48BC-8E35-A1B8642F895B}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {C4586A06-1402-48BC-8E35-A1B8642F895B}.Proto|Any CPU.Build.0 = Proto|Any CPU + {C4586A06-1402-48BC-8E35-A1B8642F895B}.Proto|x86.ActiveCfg = Proto|Any CPU + {C4586A06-1402-48BC-8E35-A1B8642F895B}.Proto|x86.Build.0 = Proto|Any CPU {C4586A06-1402-48BC-8E35-A1B8642F895B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C4586A06-1402-48BC-8E35-A1B8642F895B}.Release|Any CPU.Build.0 = Release|Any CPU {C4586A06-1402-48BC-8E35-A1B8642F895B}.Release|x86.ActiveCfg = Release|Any CPU @@ -564,6 +772,10 @@ Global {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Debug|Any CPU.Build.0 = Debug|Any CPU {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Debug|x86.ActiveCfg = Debug|Any CPU {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Debug|x86.Build.0 = Debug|Any CPU + {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Proto|Any CPU.ActiveCfg = Release|Any CPU + {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Proto|Any CPU.Build.0 = Release|Any CPU + {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Proto|x86.ActiveCfg = Release|Any CPU + {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Proto|x86.Build.0 = Release|Any CPU {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Release|Any CPU.ActiveCfg = Release|Any CPU {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Release|Any CPU.Build.0 = Release|Any CPU {887630A3-4B1D-40EA-B8B3-2D842E9C40DB}.Release|x86.ActiveCfg = Release|Any CPU @@ -572,6 +784,10 @@ Global {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Debug|Any CPU.Build.0 = Debug|Any CPU {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Debug|x86.ActiveCfg = Debug|Any CPU {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Debug|x86.Build.0 = Debug|Any CPU + {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Proto|Any CPU.Build.0 = Proto|Any CPU + {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Proto|x86.ActiveCfg = Proto|Any CPU + {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Proto|x86.Build.0 = Proto|Any CPU {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Release|Any CPU.ActiveCfg = Release|Any CPU {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Release|Any CPU.Build.0 = Release|Any CPU {FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Release|x86.ActiveCfg = Release|Any CPU @@ -580,10 +796,26 @@ Global {0385564F-07B4-4264-AB8A-17C393E9140C}.Debug|Any CPU.Build.0 = Debug|Any CPU {0385564F-07B4-4264-AB8A-17C393E9140C}.Debug|x86.ActiveCfg = Debug|Any CPU {0385564F-07B4-4264-AB8A-17C393E9140C}.Debug|x86.Build.0 = Debug|Any CPU + {0385564F-07B4-4264-AB8A-17C393E9140C}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {0385564F-07B4-4264-AB8A-17C393E9140C}.Proto|Any CPU.Build.0 = Proto|Any CPU + {0385564F-07B4-4264-AB8A-17C393E9140C}.Proto|x86.ActiveCfg = Proto|Any CPU + {0385564F-07B4-4264-AB8A-17C393E9140C}.Proto|x86.Build.0 = Proto|Any CPU {0385564F-07B4-4264-AB8A-17C393E9140C}.Release|Any CPU.ActiveCfg = Release|Any CPU {0385564F-07B4-4264-AB8A-17C393E9140C}.Release|Any CPU.Build.0 = Release|Any CPU {0385564F-07B4-4264-AB8A-17C393E9140C}.Release|x86.ActiveCfg = Release|Any CPU {0385564F-07B4-4264-AB8A-17C393E9140C}.Release|x86.Build.0 = Release|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Debug|Any CPU.Build.0 = Debug|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Debug|x86.ActiveCfg = Debug|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Debug|x86.Build.0 = Debug|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Proto|Any CPU.Build.0 = Proto|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Proto|x86.ActiveCfg = Proto|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Proto|x86.Build.0 = Proto|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Release|Any CPU.ActiveCfg = Release|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Release|Any CPU.Build.0 = Release|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Release|x86.ActiveCfg = Release|Any CPU + {400FAB03-786E-40CC-85A8-04B0C2869B14}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -650,6 +882,7 @@ Global {35636A82-401A-4C3A-B2AB-EB7DC5E9C268} = {F7876C9B-FB6A-4EFB-B058-D6967DB75FB2} {FF76BD3C-5E0A-4752-B6C3-044F6E15719B} = {35636A82-401A-4C3A-B2AB-EB7DC5E9C268} {0385564F-07B4-4264-AB8A-17C393E9140C} = {F6DAEE9A-8BE1-4C4A-BC83-09215517C7DA} + {400FAB03-786E-40CC-85A8-04B0C2869B14} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {48EDBBBE-C8EE-4E3C-8B19-97184A487B37} diff --git a/build-everything.proj b/build-everything.proj index 04d3252e79f..2a6e2320e80 100644 --- a/build-everything.proj +++ b/build-everything.proj @@ -55,10 +55,12 @@ + + diff --git a/build.cmd b/build.cmd index 5624de77d8a..b24937a8647 100644 --- a/build.cmd +++ b/build.cmd @@ -828,6 +828,9 @@ if "%TEST_NET40_COREUNIT_SUITE%" == "1" ( set OUTPUTARG=--output:"!OUTPUTFILE!" ) + echo "!NUNIT3_CONSOLE!" --verbose --framework:V4.0 --result:"!XMLFILE!;format=nunit3" !OUTPUTARG! !ERRORARG! --work:"!FSCBINPATH!" "!FSCBINPATH!\FSharp.Build.Unittests.dll" !WHERE_ARG_NUNIT! + "!NUNIT3_CONSOLE!" --verbose --framework:V4.0 --result:"!XMLFILE!;format=nunit3" !OUTPUTARG! !ERRORARG! --work:"!FSCBINPATH!" "!FSCBINPATH!\FSharp.Build.Unittests.dll" !WHERE_ARG_NUNIT! + echo "!NUNIT3_CONSOLE!" --verbose --framework:V4.0 --result:"!XMLFILE!;format=nunit3" !OUTPUTARG! !ERRORARG! --work:"!FSCBINPATH!" "!FSCBINPATH!\FSharp.Core.Unittests.dll" !WHERE_ARG_NUNIT! "!NUNIT3_CONSOLE!" --verbose --framework:V4.0 --result:"!XMLFILE!;format=nunit3" !OUTPUTARG! !ERRORARG! --work:"!FSCBINPATH!" "!FSCBINPATH!\FSharp.Core.Unittests.dll" !WHERE_ARG_NUNIT! @@ -851,6 +854,9 @@ if "%TEST_CORECLR_COREUNIT_SUITE%" == "1" ( set OUTPUTFILE=!RESULTSDIR!\test-coreclr-coreunit-output.log set ERRORFILE=!RESULTSDIR!\test-coreclr-coreunit-errors.log + echo "%_dotnetcliexe%" "%~dp0tests\testbin\!BUILD_CONFIG!\coreclr\FSharp.Build.Unittests\FSharp.Build.Unittests.dll" !WHERE_ARG_NUNIT! + "%_dotnetcliexe%" "%~dp0tests\testbin\!BUILD_CONFIG!\coreclr\FSharp.Build.Unittests\FSharp.Build.Unittests.dll" !WHERE_ARG_NUNIT! + echo "%_dotnetcliexe%" "%~dp0tests\testbin\!BUILD_CONFIG!\coreclr\FSharp.Core.Unittests\FSharp.Core.Unittests.dll" !WHERE_ARG_NUNIT! "%_dotnetcliexe%" "%~dp0tests\testbin\!BUILD_CONFIG!\coreclr\FSharp.Core.Unittests\FSharp.Core.Unittests.dll" !WHERE_ARG_NUNIT! diff --git a/build.sh b/build.sh index c0d2edc42b8..6c3323a4f9b 100755 --- a/build.sh +++ b/build.sh @@ -388,7 +388,7 @@ printf "\n" build_status "Done with arguments, starting preparation" -_msbuildexe="xbuild" +_msbuildexe="msbuild" msbuildflags="" # Perform any necessary setup and system configuration prior to running builds. @@ -466,7 +466,7 @@ if [ "$BUILD_PROTO" = '1' ]; then { pushd ./lkg/fsc && eval "$_dotnetexe publish project.json --no-build -o ${_scriptdir}Tools/lkg -r $_architecture" && popd; } || failwith "dotnet publish failed" { pushd ./lkg/fsi && eval "$_dotnetexe publish project.json --no-build -o ${_scriptdir}Tools/lkg -r $_architecture" && popd; } || failwith "dotnet publish failed" - { printeval "$_msbuildexe $msbuildflags src/fsharp-proto-build.proj"; } || failwith "compiler proto build failed" + { printeval "$_msbuildexe $msbuildflags src/fsharp-proto-build.proj /p:Configuration=Proto"; } || failwith "compiler proto build failed" # { printeval "$_ngenexe install Proto/net40/bin/fsc-proto.exe /nologo"; } || failwith "NGen of proto failed" else diff --git a/fcs/.paket/Paket.Restore.targets b/fcs/.paket/Paket.Restore.targets new file mode 100644 index 00000000000..67f745a3671 --- /dev/null +++ b/fcs/.paket/Paket.Restore.targets @@ -0,0 +1,225 @@ + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + true + $(MSBuildThisFileDirectory) + $(MSBuildThisFileDirectory)..\ + $(PaketRootPath)paket-files\paket.restore.cached + $(PaketRootPath)paket.lock + /Library/Frameworks/Mono.framework/Commands/mono + mono + + $(PaketRootPath)paket.exe + $(PaketToolsPath)paket.exe + "$(PaketExePath)" + $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" + $(PaketRootPath)paket.bootstrapper.exe + $(PaketToolsPath)paket.bootstrapper.exe + "$(PaketBootStrapperExePath)" + $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)" + + + + + true + true + + + + + + + true + $(NoWarn);NU1603 + + + + $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)')) + $([System.IO.File]::ReadAllText('$(PaketLockFilePath)')) + true + false + true + + + + + + + + + $(MSBuildProjectDirectory)\obj\$(MSBuildProjectFile).paket.references.cached + + $(MSBuildProjectFullPath).paket.references + + $(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references + + $(MSBuildProjectDirectory)\paket.references + $(MSBuildProjectDirectory)\obj\$(MSBuildProjectFile).$(TargetFramework).paket.resolved + true + references-file-or-cache-not-found + + + + + $([System.IO.File]::ReadAllText('$(PaketReferencesCachedFilePath)')) + $([System.IO.File]::ReadAllText('$(PaketOriginalReferencesFilePath)')) + references-file + false + + + + + false + + + + + true + target-framework '$(TargetFramework)' + + + + + + + + + + + + + + + + + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0]) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1]) + + + %(PaketReferencesFileLinesInfo.PackageVersion) + + + + + $(MSBuildProjectDirectory)/obj/$(MSBuildProjectFile).NuGet.Config + + + + + + + false + + + + + + $(MSBuildProjectDirectory)/$(MSBuildProjectFile) + true + false + true + + + + <_NuspecFiles Include="$(BaseIntermediateOutputPath)*.nuspec"/> + + + + + + + + + + + + + + + diff --git a/fcs/.paket/paket.bootstrapper.exe b/fcs/.paket/paket.bootstrapper.exe deleted file mode 100644 index 64fdf248bfc..00000000000 Binary files a/fcs/.paket/paket.bootstrapper.exe and /dev/null differ diff --git a/fcs/.paket/paket.exe b/fcs/.paket/paket.exe new file mode 100644 index 00000000000..ef3ea32af2a Binary files /dev/null and b/fcs/.paket/paket.exe differ diff --git a/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj b/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj index eb20755c318..cbf108a68e4 100644 --- a/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj +++ b/fcs/FSharp.Compiler.Service.netstandard/FSharp.Compiler.Service.netstandard.fsproj @@ -607,6 +607,12 @@ Service/ExternalSymbol.fs + + + Service/QuickParse.fsi + + + Service/QuickParse.fs Service/service.fsi diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index 07d9840cde2..fa10b3664ea 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -583,6 +583,12 @@ Service/ExternalSymbol.fs + + + Service/QuickParse.fsi + + + Service/QuickParse.fs Service/service.fsi diff --git a/fcs/README.md b/fcs/README.md index 3e21f6322a0..51aa24fbbef 100644 --- a/fcs/README.md +++ b/fcs/README.md @@ -60,9 +60,9 @@ which does things like: Yu can push the packages if you have permissions, either automatically using ``build Release`` or manually set APIKEY=... - .nuget\nuget.exe push Release\FSharp.Compiler.Service.16.0.2.nupkg %APIKEY% -Source https://nuget.org - .nuget\nuget.exe push Release\FSharp.Compiler.Service.MSBuild.v12.16.0.2.nupkg %APIKEY% -Source https://nuget.org - .nuget\nuget.exe push Release\FSharp.Compiler.Service.ProjectCracker.16.0.2.nupkg %APIKEY% -Source https://nuget.org + .nuget\nuget.exe push Release\FSharp.Compiler.Service.16.0.3.nupkg %APIKEY% -Source https://nuget.org + .nuget\nuget.exe push Release\FSharp.Compiler.Service.MSBuild.v12.16.0.3.nupkg %APIKEY% -Source https://nuget.org + .nuget\nuget.exe push Release\FSharp.Compiler.Service.ProjectCracker.16.0.3.nupkg %APIKEY% -Source https://nuget.org ### Use of Paket and FAKE diff --git a/fcs/RELEASE_NOTES.md b/fcs/RELEASE_NOTES.md index dd33909ca89..44eeb9ef347 100644 --- a/fcs/RELEASE_NOTES.md +++ b/fcs/RELEASE_NOTES.md @@ -1,3 +1,6 @@ +#### 16.0.3 + * [File name deduplication not working with ParseAndCheckFileInProject](https://github.com/fsharp/FSharp.Compiler.Service/issues/819) + #### 16.0.2 * [ProjectCracker returns *.fsi files in FSharpProjectOptions.SourceFiles array](https://github.com/fsharp/FSharp.Compiler.Service/pull/812) diff --git a/fcs/build.cmd b/fcs/build.cmd index 312c7ed7382..f7242b03912 100644 --- a/fcs/build.cmd +++ b/fcs/build.cmd @@ -1,8 +1,10 @@ @echo off + +dotnet --version .nuget\NuGet.exe restore -PackagesDirectory packages setlocal cd fcs -.paket\paket.bootstrapper.exe + dotnet restore tools.fsproj if errorlevel 1 ( endlocal diff --git a/fcs/build.sh b/fcs/build.sh old mode 100644 new mode 100755 index 3e7e80e7d88..d6559cfaa8b --- a/fcs/build.sh +++ b/fcs/build.sh @@ -4,6 +4,8 @@ then # use .Net cmd fcs/build.cmd $@ else + dotnet --version + mono .nuget/NuGet.exe restore -PackagesDirectory packages cd fcs @@ -15,12 +17,6 @@ else dotnet restore tools.fsproj - mono .paket/paket.bootstrapper.exe - exit_code=$? - if [ $exit_code -ne 0 ]; then - exit $exit_code - fi - mono .paket/paket.exe restore exit_code=$? if [ $exit_code -ne 0 ]; then diff --git a/fcs/fcs.props b/fcs/fcs.props index e7cce1e0c3a..f1d16e7c8c9 100644 --- a/fcs/fcs.props +++ b/fcs/fcs.props @@ -3,7 +3,7 @@ - 16.0.2 + 16.0.3 $(FSharpSourcesRoot)\..\packages\FSharp.Compiler.Tools.4.1.27\tools diff --git a/fcs/nuget/FSharp.Compiler.Service.MSBuild.v12.nuspec b/fcs/nuget/FSharp.Compiler.Service.MSBuild.v12.nuspec index adf1e3726e2..ae9c17a7819 100644 --- a/fcs/nuget/FSharp.Compiler.Service.MSBuild.v12.nuspec +++ b/fcs/nuget/FSharp.Compiler.Service.MSBuild.v12.nuspec @@ -5,7 +5,7 @@ Adds legacy MSBuild 12.0 support to the F# compiler services package for resolving references such as #r "System, Version=4.1.0.0,..." en-US false - 16.0.2 + 16.0.3 Microsoft Corporation and F# community contributors https://github.com/fsharp/FSharp.Compiler.Service/blob/master/LICENSE https://github.com/fsharp/FSharp.Compiler.Service @@ -14,7 +14,7 @@ F# compiler services for creating IDE tools, language extensions and for F# embedding. - + diff --git a/fcs/nuget/FSharp.Compiler.Service.ProjectCracker.nuspec b/fcs/nuget/FSharp.Compiler.Service.ProjectCracker.nuspec index a19d9341f29..e45bb835728 100644 --- a/fcs/nuget/FSharp.Compiler.Service.ProjectCracker.nuspec +++ b/fcs/nuget/FSharp.Compiler.Service.ProjectCracker.nuspec @@ -5,7 +5,7 @@ The F# compiler services package contains a custom build of the F# compiler that exposes additional functionality for implementing F# language bindings, additional tools based on the compiler or refactoring tools. The package also includes F# interactive service that can be used for embedding F# scripting into your applications. en-US false - 16.0.2 + 16.0.3 Microsoft Corporation and F# community contributors https://github.com/fsharp/FSharp.Compiler.Service/blob/master/LICENSE https://github.com/fsharp/FSharp.Compiler.Service @@ -14,7 +14,7 @@ F# compiler services for creating IDE tools, language extensions and for F# embedding. - + diff --git a/fcs/nuget/FSharp.Compiler.Service.nuspec b/fcs/nuget/FSharp.Compiler.Service.nuspec index fb4b6ac0550..ba4c2e7c3d5 100644 --- a/fcs/nuget/FSharp.Compiler.Service.nuspec +++ b/fcs/nuget/FSharp.Compiler.Service.nuspec @@ -5,7 +5,7 @@ The F# compiler services package contains a custom build of the F# compiler that exposes additional functionality for implementing F# language bindings, additional tools based on the compiler or refactoring tools. The package also includes F# interactive service that can be used for embedding F# scripting into your applications. en-US false - 16.0.2 + 16.0.3 Microsoft Corporation and F# community contributors https://github.com/fsharp/FSharp.Compiler.Service/blob/master/LICENSE https://github.com/fsharp/FSharp.Compiler.Service diff --git a/fcs/samples/EditorService/Program.fs b/fcs/samples/EditorService/Program.fs index 40052ddce7e..5a2cb624f0c 100644 --- a/fcs/samples/EditorService/Program.fs +++ b/fcs/samples/EditorService/Program.fs @@ -2,6 +2,7 @@ open System open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.SourceCodeServices +open Microsoft.FSharp.Compiler.QuickParse // Create an interactive checker instance (ignore notifications) let checker = FSharpChecker.Create() @@ -36,9 +37,11 @@ let tip = parsed.GetToolTipText(2, 7, inputLines.[1], [ "foo" ], identTokenTag) printfn "%A" tip +let partialName = GetPartialLongNameEx(inputLines.[4], 23) + // Get declarations (autocomplete) for a location let decls = - parsed.GetDeclarationListInfo(Some untyped, 5, 23, inputLines.[4], [], "msg", (fun () -> [])) + parsed.GetDeclarationListInfo(Some untyped, 5, inputLines.[4], partialName, (fun () -> [])) |> Async.RunSynchronously for item in decls.Items do diff --git a/netci.groovy b/netci.groovy index ba971aaf9c4..185ea17a197 100644 --- a/netci.groovy +++ b/netci.groovy @@ -12,10 +12,14 @@ def static getBuildJobName(def configuration, def os) { [true, false].each { isPullRequest -> osList.each { os -> - def configurations = ['Debug', 'Release_ci_part1', 'Release_ci_part2', 'Release_ci_part3', 'Release_net40_no_vs' ]; - if (os != 'Windows_NT') { - // Only build one configuration on Linux/... so far - configurations = ['Release']; + def configurations = []; + if (os == 'Windows_NT') { + configurations = ['Debug', 'Release_ci_part1', 'Release_ci_part2', 'Release_ci_part3', 'Release_net40_no_vs', 'Release_fcs' ]; + } + else + { + // Linux + configurations = ['Release', 'Release_fcs' ]; } configurations.each { configuration -> @@ -24,10 +28,28 @@ def static getBuildJobName(def configuration, def os) { // Calculate job name def jobName = getBuildJobName(configuration, os) + def buildPath = ''; + if (os == 'Windows_NT') { + buildPath = ".\\" + } + else { + buildPath = "./" + } def buildCommand = ''; - def buildFlavor= ''; - if (configuration == "Debug") { + + if (configuration == "Release_fcs") { + // Build and test FCS NuGet package + buildPath = "./fcs/" + buildFlavor = "" + if (os == 'Windows_NT') { + build_args = "TestAndNuget" + } + else { + build_args = "Build" + } + } + else if (configuration == "Debug") { buildFlavor = "debug" build_args = "" } @@ -51,10 +73,10 @@ def static getBuildJobName(def configuration, def os) { } if (os == 'Windows_NT') { - buildCommand = ".\\build.cmd ${buildFlavor} ${build_args}" + buildCommand = "${buildPath}build.cmd ${buildFlavor} ${build_args}" } else { - buildCommand = "./build.sh ${buildFlavor} ${build_args}" + buildCommand = "${buildPath}build.sh ${buildFlavor} ${build_args}" } def newJobName = Utilities.getFullJobName(project, jobName, isPullRequest) @@ -64,7 +86,7 @@ def static getBuildJobName(def configuration, def os) { batchFile(""" echo *** Build Visual F# Tools *** -.\\build.cmd ${buildFlavor} ${build_args}""") +${buildPath}build.cmd ${buildFlavor} ${build_args}""") } else { // Shell @@ -79,9 +101,15 @@ echo *** Build Visual F# Tools *** def affinity = configuration == 'Release_net40_no_vs' ? 'latest-or-auto' : (os == 'Windows_NT' ? 'latest-or-auto-dev15-0' : 'latest-or-auto') Utilities.setMachineAffinity(newJob, os, affinity) Utilities.standardJobSetup(newJob, project, isPullRequest, "*/${branch}") - Utilities.addArchival(newJob, "tests/TestResults/*.*", "", skipIfNoTestFiles, false) - Utilities.addArchival(newJob, "${buildFlavor}/**") + + Utilities.addArchival(newJob, "tests/TestResults/*.*", "", skipIfNoTestFiles, false) + if (configuration == "Release_fcs") { + Utilities.addArchival(newJob, "Release/fcs/**") + } + else { + Utilities.addArchival(newJob, "${buildFlavor}/**") + } if (isPullRequest) { Utilities.addGithubPRTriggerForBranch(newJob, branch, "${os} ${configuration} Build") } diff --git a/src/FSharpSource.targets b/src/FSharpSource.targets index 5d09fd3373d..f9e54f501f7 100644 --- a/src/FSharpSource.targets +++ b/src/FSharpSource.targets @@ -363,6 +363,9 @@ + + + $(IntermediateOutputPath)$(MSBuildProjectName).InternalsVisibleTo$(DefaultLanguageSourceExtension) + + + + + false + + + + + + <_PublicKey>002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293 + + + <_InternalsVisibleToAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute"> + <_Parameter1 Condition="'%(InternalsVisibleTo.Key)' != ''">%(InternalsVisibleTo.Identity), PublicKey=%(InternalsVisibleTo.Key) + <_Parameter1 Condition="'%(InternalsVisibleTo.Key)' == ''">%(InternalsVisibleTo.Identity), PublicKey=$(_PublicKey) + + + + + + + + + + + diff --git a/src/assemblyinfo/assemblyinfo.FSharp.Build.dll.fs b/src/assemblyinfo/assemblyinfo.FSharp.Build.dll.fs index 14a0524154e..e31498dae32 100644 --- a/src/assemblyinfo/assemblyinfo.FSharp.Build.dll.fs +++ b/src/assemblyinfo/assemblyinfo.FSharp.Build.dll.fs @@ -9,13 +9,6 @@ open System.Reflection [] do() -#if NO_STRONG_NAMES -[] -#endif -#if STRONG_NAME_AND_DELAY_SIGN_FSHARP_COMPILER_WITH_MSFT_KEY -[] -#endif - // Until dotnet sdk can version assemblies, use this #if BUILD_FROM_SOURCE [] diff --git a/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Interactive.Settings.dll.fs b/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Interactive.Settings.dll.fs index 37dee8dc588..5a1ca9682a0 100644 --- a/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Interactive.Settings.dll.fs +++ b/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Interactive.Settings.dll.fs @@ -11,21 +11,6 @@ open System.Runtime.InteropServices [] [] -#if NO_STRONG_NAMES -[] -[] -#endif - -#if STRONG_NAME_AND_DELAY_SIGN_FSHARP_COMPILER_WITH_MSFT_KEY -[] -[] -#endif - -#if STRONG_NAME_FSHARP_COMPILER_WITH_TEST_KEY -[] -[] -#endif - // Until dotnet sdk can version assemblies, use this #if BUILD_FROM_SOURCE [] diff --git a/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Private.dll.fs b/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Private.dll.fs index c74e002c1b9..80f054f8529 100644 --- a/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Private.dll.fs +++ b/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Private.dll.fs @@ -11,60 +11,6 @@ open System.Runtime.InteropServices [] [] -#if NO_STRONG_NAMES -[] -[] -[] -[] -[] -[] -[] -[] -[] - -// Note: internals visible to unit test DLLs in Retail (and all) builds. -[] -[] -[] -[] -[] -#endif -#if STRONG_NAME_AND_DELAY_SIGN_FSHARP_COMPILER_WITH_MSFT_KEY - -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -#endif -#if STRONG_NAME_FSHARP_COMPILER_WITH_TEST_KEY -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -#endif - // Until dotnet sdk can version assemblies, use this #if BUILD_FROM_SOURCE [] diff --git a/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Service.MSBuild.v12.dll.fs b/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Service.MSBuild.v12.dll.fs deleted file mode 100644 index 70eafeb1227..00000000000 --- a/src/assemblyinfo/assemblyinfo.FSharp.Compiler.Service.MSBuild.v12.dll.fs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.FSharp -open System.Reflection -open System.Runtime.InteropServices - -[] -[] -[] -[] - -[] -[] -do() diff --git a/src/assemblyinfo/assemblyinfo.fsc.exe.fs b/src/assemblyinfo/assemblyinfo.fsc.exe.fs index d9245e545f1..d7adacfd7e1 100644 --- a/src/assemblyinfo/assemblyinfo.fsc.exe.fs +++ b/src/assemblyinfo/assemblyinfo.fsc.exe.fs @@ -11,8 +11,6 @@ open System.Runtime.InteropServices [] [] -[] - // Until dotnet sdk can version assemblies, use this #if BUILD_FROM_SOURCE [] diff --git a/src/buildfromsource/BuildFromSource.targets b/src/buildfromsource/BuildFromSource.targets index de0a43a4d9c..a42e1bd56de 100644 --- a/src/buildfromsource/BuildFromSource.targets +++ b/src/buildfromsource/BuildFromSource.targets @@ -10,9 +10,9 @@ true true false + $(DefineConstants);BUILD_FROM_SOURCE - $(DefineConstants);STRONG_NAME_AND_DELAY_SIGN_FSHARP_COMPILER_WITH_MSFT_KEY $(MSBuildThisFileDirectory)../buildtools/keys/MSFT.snk true $(OtherFlags) --publicsign --keyfile:$(KeyFile) diff --git a/src/buildfromsource/FSharp.Build/FSharp.Build.fsproj b/src/buildfromsource/FSharp.Build/FSharp.Build.fsproj index c65905b2212..0d7c7c06cc3 100644 --- a/src/buildfromsource/FSharp.Build/FSharp.Build.fsproj +++ b/src/buildfromsource/FSharp.Build/FSharp.Build.fsproj @@ -8,7 +8,6 @@ FSharp.Build $(NoWarn);45;55;62;75;1204 true - $(DefineConstants);BUILD_FROM_SOURCE $(OtherFlags) --maxerrors:20 --extraoptimizationloops:1 @@ -23,6 +22,7 @@ + diff --git a/src/buildfromsource/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/buildfromsource/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index e4c513f5e52..cc34966a10c 100644 --- a/src/buildfromsource/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/buildfromsource/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -6,11 +6,11 @@ Library netstandard1.6 FSharp.Compiler.Interactive.Settings - $(NoWarn);45;55;62;75;1204 + $(NoWarn);45;55;62;75;1182;1204 true true - EXTENSIONTYPING;$(DefineConstants);BUILD_FROM_SOURCE - $(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 + EXTENSIONTYPING;$(DefineConstants) + $(OtherFlags) --maxerrors:20 --extraoptimizationloops:1 @@ -18,6 +18,7 @@ + diff --git a/src/buildfromsource/FSharp.Compiler.Interactive.Settings/InternalsVisibleTo.fs b/src/buildfromsource/FSharp.Compiler.Interactive.Settings/InternalsVisibleTo.fs new file mode 100644 index 00000000000..eae3493cd15 --- /dev/null +++ b/src/buildfromsource/FSharp.Compiler.Interactive.Settings/InternalsVisibleTo.fs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp + +[] +[] +[] + +do() diff --git a/src/buildfromsource/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/buildfromsource/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index 1cc973ee6b2..4d5189148f0 100644 --- a/src/buildfromsource/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/buildfromsource/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -8,7 +8,7 @@ FSharp.Compiler.Private $(NoWarn);45;55;62;75;1204 true - $(DefineConstants);EXTENSIONTYPING;COMPILER;BUILD_FROM_SOURCE + $(DefineConstants);EXTENSIONTYPING;COMPILER $(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 @@ -23,6 +23,7 @@ assemblyinfo.FSharp.Compiler.Private.dll.fs + FSComp.txt @@ -564,6 +565,12 @@ Service/ExternalSymbol.fs + + + Service/QuickParse.fsi + + + Service/QuickParse.fs Service/service.fsi diff --git a/src/buildfromsource/FSharp.Compiler.Private/InternalsVisibleTo.fs b/src/buildfromsource/FSharp.Compiler.Private/InternalsVisibleTo.fs new file mode 100644 index 00000000000..f16c3af63df --- /dev/null +++ b/src/buildfromsource/FSharp.Compiler.Private/InternalsVisibleTo.fs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp + +[] +[] +[] +[] +[] +[] +[] +[] + +do() diff --git a/src/buildfromsource/FSharp.Compiler.nuget/FSharp.Compiler.nuget.fsproj b/src/buildfromsource/FSharp.Compiler.nuget/FSharp.Compiler.nuget.fsproj index 29a35faa0b1..70d5835c025 100644 --- a/src/buildfromsource/FSharp.Compiler.nuget/FSharp.Compiler.nuget.fsproj +++ b/src/buildfromsource/FSharp.Compiler.nuget/FSharp.Compiler.nuget.fsproj @@ -8,7 +8,6 @@ Microsoft.FSharp.Compiler $(NoWarn);45;55;62;75;1204 true - $(DefineConstants);BUILD_FROM_SOURCE $(OtherFlags) --warnon:1182 --maxerrors:20 diff --git a/src/buildfromsource/FSharp.Core/FSharp.Core.fsproj b/src/buildfromsource/FSharp.Core/FSharp.Core.fsproj index a6f12306911..a56ae2a3547 100644 --- a/src/buildfromsource/FSharp.Core/FSharp.Core.fsproj +++ b/src/buildfromsource/FSharp.Core/FSharp.Core.fsproj @@ -9,7 +9,7 @@ $(NoWarn);45;55;62;75;1204 true true - $(DefineConstants);FSHARP_CORE;BUILD_FROM_SOURCE + $(DefineConstants);FSHARP_CORE $(OtherFlags) --warnon:1182 --compiling-fslib --compiling-fslib-40 --maxerrors:20 --extraoptimizationloops:1 diff --git a/src/buildfromsource/Fsc/Fsc.fsproj b/src/buildfromsource/Fsc/Fsc.fsproj index e17e6da9e44..c40121222e6 100644 --- a/src/buildfromsource/Fsc/Fsc.fsproj +++ b/src/buildfromsource/Fsc/Fsc.fsproj @@ -9,7 +9,7 @@ fsc $(NoWarn);45;55;62;75;1204 true - $(DefineConstants);BUILD_FROM_SOURCE;EXTENSIONTYPING;COMPILER + $(DefineConstants);EXTENSIONTYPING;COMPILER $(OtherFlags) --maxerrors:20 --extraoptimizationloops:1 diff --git a/src/fsharp/ErrorResolutionHints.fs b/src/fsharp/ErrorResolutionHints.fs index 4b3e47617c1..64ef837c85f 100644 --- a/src/fsharp/ErrorResolutionHints.fs +++ b/src/fsharp/ErrorResolutionHints.fs @@ -43,7 +43,11 @@ let FilterPredictions (idText:string) (suggestionF:ErrorLogger.Suggestions) = if allSuggestions.Contains idText then [] else // some other parsing error occurred allSuggestions |> Seq.choose (fun suggestion -> - if IsOperatorName suggestion then None else + // Because beginning a name with _ is used both to indicate an unused + // value as well as to formally squelch the associated compiler + // error/warning (FS1182), we remove such names from the suggestions, + // both to prevent accidental usages as well as to encourage good taste + if IsOperatorName suggestion || suggestion.StartsWith "_" then None else let suggestion:string = demangle suggestion let suggestedText = suggestion.ToUpperInvariant() let similarity = EditDistance.JaroWinklerDistance uppercaseText suggestedText diff --git a/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj b/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj index c5c361ca1d2..a6505441b5b 100644 --- a/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj +++ b/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj @@ -40,6 +40,9 @@ FSharpEmbedResXSource.fs + + WriteCodeFragment.fs + Microsoft.FSharp-proto.targets Microsoft.FSharp-proto.targets diff --git a/src/fsharp/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj b/src/fsharp/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj new file mode 100644 index 00000000000..f81d227e8d6 --- /dev/null +++ b/src/fsharp/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj @@ -0,0 +1,77 @@ + + + + + $(MSBuildProjectDirectory)\..\.. + {400FAB03-786E-40CC-85A8-04B0C2869B14} + true + false + + + + Debug + AnyCPU + 2.0 + true + true + Library + false + FSharp.Build.UnitTests + netcore + + + $(DefineConstants);EXTENSIONTYPING;$(TargetDotnetProfile.ToLower()) + + + true + false + $(DefineConstants);DEBUG;TRACE + prompt + 3 + + + true + $(DefineConstants);TRACE + prompt + 3 + + + + true + True + $(NUnitLibDir)\nunit.framework.dll + + + $(FSharpSourcesRoot)\..\packages\Microsoft.VisualFSharp.Msbuild.15.0.1.0.1\lib\net45\Microsoft.Build.Framework.dll + + + $(FSharpSourcesRoot)\..\packages\Microsoft.VisualFSharp.Msbuild.15.0.1.0.1\lib\net45\Microsoft.Build.dll + + + $(FSharpSourcesRoot)\..\packages\Microsoft.VisualFSharp.Msbuild.15.0.1.0.1\lib\net45\Microsoft.Build.Utilities.Core.dll + + + $(FSharpSourcesRoot)\..\packages\Microsoft.VisualFSharp.Msbuild.15.0.1.0.1\lib\net45\Microsoft.Build.Tasks.Core.dll + + + + + {702A7979-BCF9-4C41-853E-3ADFC9897890} + FSharp.Build + + + {DED3BBD7-53F4-428A-8C9F-27968E768605} + FSharp.Core + + + + + + + + + + + + + diff --git a/src/fsharp/FSharp.Build.UnitTests/Program.fs b/src/fsharp/FSharp.Build.UnitTests/Program.fs new file mode 100644 index 00000000000..d0397a7de09 --- /dev/null +++ b/src/fsharp/FSharp.Build.UnitTests/Program.fs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module Program + +open System +open System.Reflection +open NUnitLite +open NUnit.Common + +type HelperType() = inherit System.Object() + +[] +let main argv = + AutoRun(typeof.GetTypeInfo().Assembly).Execute(argv, new ExtendedTextWrapper(Console.Out), Console.In) diff --git a/src/fsharp/FSharp.Build.UnitTests/WriteCodeFragmentTests.fs b/src/fsharp/FSharp.Build.UnitTests/WriteCodeFragmentTests.fs new file mode 100644 index 00000000000..70800400d27 --- /dev/null +++ b/src/fsharp/FSharp.Build.UnitTests/WriteCodeFragmentTests.fs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Build.UnitTests + +open Microsoft.Build.Framework +open Microsoft.Build.Utilities +open Microsoft.FSharp.Build +open NUnit.Framework + +[] +type WriteCodeFragmentTests()= + + let verifyAttribute (attributeName:string) (parameters:(string*string) list) (expectedAttributeText:string) = + let taskItem = TaskItem(attributeName) + parameters |> List.iter (fun (key, value) -> taskItem.SetMetadata(key, value)) + let actualAttributeText = WriteCodeFragment.GenerateAttribute (taskItem :> ITaskItem) + let fullExpectedAttributeText = "[]" + Assert.AreEqual(fullExpectedAttributeText, actualAttributeText) + + [] + member this.``No parameters``() = + verifyAttribute "SomeAttribute" [] "SomeAttribute()" + + [] + member this.``Skipped and out of order positional parameters``() = + verifyAttribute "SomeAttribute" [("_Parameter3", "3"); ("_Parameter5", "5"); ("_Parameter2", "2")] "SomeAttribute(null, \"2\", \"3\", null, \"5\")" + + [] + member this.``Named parameters``() = + verifyAttribute "SomeAttribute" [("One", "1"); ("Two", "2")] "SomeAttribute(One = \"1\", Two = \"2\")" + + [] + member this.``Named and positional parameters``() = + verifyAttribute "SomeAttribute" [("One", "1"); ("_Parameter2", "2.2"); ("Two", "2")] "SomeAttribute(null, \"2.2\", One = \"1\", Two = \"2\")" + + [] + member this.``Escaped string parameters``() = + verifyAttribute "SomeAttribute" [("_Parameter1", "\"uno\"")] "SomeAttribute(\"\\\"uno\\\"\")" + // this should look like: SomeAttribute("\"uno\"") diff --git a/src/fsharp/FSharp.Build.UnitTests/project.json b/src/fsharp/FSharp.Build.UnitTests/project.json new file mode 100644 index 00000000000..557b06140e2 --- /dev/null +++ b/src/fsharp/FSharp.Build.UnitTests/project.json @@ -0,0 +1,33 @@ +{ + "version": "1.0.0-*", + "name": "FSharp.Build.UnitTests", + "buildOptions": { + "debugType": "portable", + "emitEntryPoint": true + }, + "dependencies": { + "nunit": "3.5.0", + "nunitlite": "3.5.0", + "Microsoft.Build": "15.1.548", + "Microsoft.Build.Framework": "15.1.548", + "Microsoft.Build.Tasks.Core": "15.1.548", + "Microsoft.Build.Utilities.Core": "15.1.548" + }, + "runtimes": { + "win7-x86": {}, + "win7-x64": {}, + "osx.10.11-x64": {}, + "ubuntu.14.04-x64": {} + }, + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.1" + } + }, + "imports": [ "netstandard1.1", "netstandard1.6", "portable-net45+win8+wp8+wpa81" ] + } + } +} diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 30aeb96da5b..5c8982e34c4 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -22,9 +22,12 @@ + + + + - @@ -32,6 +35,7 @@ + diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets index fb0957e115f..919c159d4b5 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets @@ -21,10 +21,11 @@ this file. $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - + + + + + true diff --git a/src/fsharp/FSharp.Build/WriteCodeFragment.fs b/src/fsharp/FSharp.Build/WriteCodeFragment.fs new file mode 100644 index 00000000000..ee8eaab2830 --- /dev/null +++ b/src/fsharp/FSharp.Build/WriteCodeFragment.fs @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Build + +open System +open System.Collections +open System.Collections.Generic +open System.Globalization +open System.IO +open System.Linq +open System.Text +open Microsoft.Build.Framework +open Microsoft.Build.Utilities + +type WriteCodeFragment() = + let mutable _buildEngine : IBuildEngine = null + let mutable _hostObject : ITaskHost = null + let mutable _language : string = "" + let mutable _assemblyAttributes : ITaskItem[] = [||] + let mutable _outputDirectory : ITaskItem = null + let mutable _outputFile : ITaskItem = null + + static let escapeString (str:string) = + let sb = str.ToCharArray() |> Seq.fold (fun (sb:StringBuilder) (c:char) -> + match c with + | '\n' | '\u2028' | '\u2028' -> sb.Append("\\n") + | '\r' -> sb.Append("\\r") + | '\t' -> sb.Append("\\t") + | '\'' -> sb.Append("\\'") + | '\\' -> sb.Append("\\\\") + | '"' -> sb.Append("\\\"") + | '\u0000' -> sb.Append("\\0") + | _ -> sb.Append(c)) (StringBuilder().Append("\"")) + sb.Append("\"").ToString() + + static member GenerateAttribute (item:ITaskItem) = + let attributeName = item.ItemSpec + let args = + // mimicking the behavior from https://github.com/Microsoft/msbuild/blob/70ce7e9ccb891b63f0859f1f7f0b955693ed3742/src/Tasks/WriteCodeFragment.cs#L355-L415 + // Split parameters into unnamed positional (e.g., key is "_Parameter1", etc.) and proper named parameters. + let customMetadata = item.CloneCustomMetadata() + let parameterPairs = + // normalize everything to strings + seq { for entry in customMetadata -> entry :?> DictionaryEntry } + |> Seq.toList + |> List.map (fun entry -> + let key = entry.Key :?> string + let value = match entry.Value with + | null -> "null" + | :? string as value -> escapeString value + | value -> value.ToString() + (key, value)) + let orderedParameters, namedParameters = parameterPairs |> List.partition (fun (key, _) -> key.StartsWith("_Parameter")) + let orderedParametersWithIndex = + orderedParameters + |> List.map (fun (key, value) -> + let indexString = key.Substring("_Parameter".Length) + match Int32.TryParse indexString with + | (true, index) -> (index, value) + | (false, _) -> failwith (sprintf "Unable to parse '%s' as an index" indexString)) + |> List.sortBy fst + // assign ordered parameters to array + let orderedParametersArray = + if List.isEmpty orderedParametersWithIndex then [||] + else Array.create (List.last orderedParametersWithIndex |> fst) "null" + List.iter (fun (index, value) -> orderedParametersArray.[index - 1] <- value) orderedParametersWithIndex + // construct ordered parameter lists + let combinedOrderedParameters = String.Join(", ", orderedParametersArray) + let combinedNamedParameters = String.Join(", ", List.map (fun (key, value) -> sprintf "%s = %s" key value) namedParameters) + // construct the final argument string; positional arguments followed by named + match (combinedOrderedParameters.Length, combinedNamedParameters.Length) with + | (0, 0) -> "" // no arguments + | (0, _) -> combinedNamedParameters // only named arguments + | (_, 0) -> combinedOrderedParameters // only positional arguments + | (_, _) -> combinedOrderedParameters + ", " + combinedNamedParameters // both positional and named arguments + sprintf "[]" attributeName args + + // adding this property to maintain API equivalence with the MSBuild task + member this.Language + with get() = _language + and set(value) = _language <- value + + member this.AssemblyAttributes + with get() = _assemblyAttributes + and set(value) = _assemblyAttributes <- value + + member this.OutputDirectory + with get() = _outputDirectory + and set(value) = _outputDirectory <- value + + [] + member this.OutputFile + with get() = _outputFile + and set(value) = _outputFile <- value + + interface ITask with + member this.BuildEngine + with get() = _buildEngine + and set(value) = _buildEngine <- value + member this.HostObject + with get() = _hostObject + and set(value) = _hostObject <- value + member this.Execute() = + try + if isNull _outputFile && isNull _outputDirectory then failwith "Output location must be specified" + if _language.ToLowerInvariant() <> "f#" then failwith "Language name must be F#" + let boilerplate = @"// + +namespace FSharp + +open System +open System.Reflection" + let sb = StringBuilder().AppendLine(boilerplate).AppendLine() + let code = Array.fold (fun (sb:StringBuilder) (item:ITaskItem) -> sb.AppendLine(WriteCodeFragment.GenerateAttribute item)) sb _assemblyAttributes + code.AppendLine().AppendLine("do()") |> ignore + let outputFileItem = + if not (isNull _outputFile) && not (isNull _outputDirectory) && not (Path.IsPathRooted(_outputFile.ItemSpec)) then + TaskItem(Path.Combine(_outputDirectory.ItemSpec, _outputFile.ItemSpec)) :> ITaskItem + elif isNull _outputFile then + let tempFile = Path.Combine(Path.GetTempPath(), sprintf "tmp%s.fs" (Guid.NewGuid().ToString("N"))) + TaskItem(tempFile) :> ITaskItem + else + _outputFile + File.WriteAllText(_outputFile.ItemSpec, code.ToString()) + _outputFile <- outputFileItem + true + with e -> + printf "Error writing code fragment: %s" (e.ToString()) + false diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj index bafa11f9320..257443d115b 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/FSharp.Compiler.Interactive.Settings.fsproj @@ -15,9 +15,14 @@ 512 + + + + + + - diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index acfb28e533b..4b72bcf00f0 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -48,6 +48,26 @@ + + + + + + + + + + + + + + + + + + + + $(FSharpSourcesRoot)\..\loc\lcl\{Lang}\$(AssemblyName).dll.lcl @@ -600,6 +620,12 @@ Service/ExternalSymbol.fs + + Service/QuickParse.fsi + + + Service/QuickParse.fs + Service/service.fsi @@ -630,9 +656,6 @@ InteractiveSession\fsi.fs - - Misc/InternalsVisibleTo.fs - Misc/MSBuildReferenceResolver.fs diff --git a/src/fsharp/FSharp.Compiler.Private/InternalsVisibleTo.fs b/src/fsharp/FSharp.Compiler.Private/InternalsVisibleTo.fs deleted file mode 100644 index 42c52dc5c72..00000000000 --- a/src/fsharp/FSharp.Compiler.Private/InternalsVisibleTo.fs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.FSharp -open System.Reflection -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] - -do() - diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/AssemblyInfo.fs b/src/fsharp/FSharp.Compiler.Server.Shared/AssemblyInfo.fs index 677757317ad..c877e145a39 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/AssemblyInfo.fs +++ b/src/fsharp/FSharp.Compiler.Server.Shared/AssemblyInfo.fs @@ -4,15 +4,6 @@ namespace Microsoft.FSharp open System.Reflection open System.Runtime.InteropServices -#if NO_STRONG_NAMES -[] -[] -[] -#endif -[] -[] -[] -do() [] [] diff --git a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj index 393ec74def9..ad31f08f033 100644 --- a/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj +++ b/src/fsharp/FSharp.Compiler.Server.Shared/FSharp.Compiler.Server.Shared.fsproj @@ -14,6 +14,11 @@ FSharp.Compiler.Server.Shared v4.6 + + + + + diff --git a/src/fsharp/FSharp.Core/SR.fs b/src/fsharp/FSharp.Core/SR.fs index 278eb5d88fd..4fb66a6de9c 100644 --- a/src/fsharp/FSharp.Core/SR.fs +++ b/src/fsharp/FSharp.Core/SR.fs @@ -77,7 +77,7 @@ module internal SR = let notARecordType = "notARecordType" let nullsNotAllowedInArray = "nullsNotAllowedInArray" let objIsNotARecord = "objIsNotARecord" - let keyNotFoundAlt = "keyNotFoundAltMessage" + let keyNotFoundAlt = "keyNotFoundAlt" let firstClassUsesOfSplice = "firstClassUsesOfSplice" let printfNotAFunType = "printfNotAFunType" let printfMissingFormatSpecifier = "printfMissingFormatSpecifier" diff --git a/src/fsharp/FSharp.Core/quotations.fs b/src/fsharp/FSharp.Core/quotations.fs index a520286e0cf..8c78edd8e03 100644 --- a/src/fsharp/FSharp.Core/quotations.fs +++ b/src/fsharp/FSharp.Core/quotations.fs @@ -643,8 +643,8 @@ module Patterns = | WhileLoopOp,_ | VarSetOp,_ | AddressSetOp,_ -> typeof - | AddressOfOp,_ -> raise <| System.InvalidOperationException (SR.GetString(SR.QcannotTakeAddress)) - | (QuoteOp _ | SequentialOp | TryWithOp | TryFinallyOp | IfThenElseOp | AppOp),_ -> failwith "unreachable" + | AddressOfOp,[expr]-> (typeOf expr).MakeByRefType() + | (AddressOfOp | QuoteOp _ | SequentialOp | TryWithOp | TryFinallyOp | IfThenElseOp | AppOp),_ -> failwith "unreachable" //-------------------------------------------------------------------------- diff --git a/src/fsharp/Fsc/Fsc.fsproj b/src/fsharp/Fsc/Fsc.fsproj index 5e820e75eab..9775469cf1c 100644 --- a/src/fsharp/Fsc/Fsc.fsproj +++ b/src/fsharp/Fsc/Fsc.fsproj @@ -32,8 +32,11 @@ - - + + + + + Resources/assemblyinfo.fsc.exe.fs diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index bf05dcadab2..2387b0365c3 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -1299,7 +1299,7 @@ module InfoMemberPrinting = // Container(argName1:argType1, ..., argNameN:argTypeN) : retType // Container.Method(argName1:argType1, ..., argNameN:argTypeN) : retType let private layoutMethInfoCSharpStyle amap m denv (minfo:MethInfo) minst = - let retTy = minfo.GetFSharpReturnTy(amap, m, minst) + let retTy = if minfo.IsConstructor then minfo.EnclosingType else minfo.GetFSharpReturnTy(amap, m, minst) let layout = if minfo.IsExtensionMember then LeftL.leftParen ^^ wordL (tagKeyword (FSComp.SR.typeInfoExtension())) ^^ RightL.rightParen diff --git a/src/fsharp/vs/IncrementalBuild.fs b/src/fsharp/vs/IncrementalBuild.fs index 89c315001a9..44056bea56d 100755 --- a/src/fsharp/vs/IncrementalBuild.fs +++ b/src/fsharp/vs/IncrementalBuild.fs @@ -1622,6 +1622,9 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput member builder.GetCheckResultsAfterLastFileInProject (ctok: CompilationThreadToken) = builder.GetCheckResultsBeforeSlotInProject(ctok, builder.GetSlotsCount()) + member builder.DeduplicateParsedInputModuleNameInProject (input) = + DeduplicateParsedInputModuleName moduleNamesDict input + member __.GetCheckResultsAndImplementationsForProject(ctok: CompilationThreadToken) = cancellable { let cache = TimeStampCache(defaultTimeStamp) diff --git a/src/fsharp/vs/IncrementalBuild.fsi b/src/fsharp/vs/IncrementalBuild.fsi index cca9dba7f90..47ec0a7b624 100755 --- a/src/fsharp/vs/IncrementalBuild.fsi +++ b/src/fsharp/vs/IncrementalBuild.fsi @@ -142,6 +142,8 @@ type internal IncrementalBuilder = // TODO: make this an Eventually (which can be scheduled) or an Async (which can be cancelled) member GetCheckResultsAndImplementationsForProject : CompilationThreadToken -> Cancellable + member DeduplicateParsedInputModuleNameInProject: Ast.ParsedInput -> Ast.ParsedInput + /// Get the logical time stamp that is associated with the output of the project if it were gully built immediately member GetLogicalTimeStampForProject: TimeStampCache * CompilationThreadToken -> DateTime diff --git a/vsintegration/src/FSharp.LanguageService/QuickParse.fs b/src/fsharp/vs/QuickParse.fs similarity index 64% rename from vsintegration/src/FSharp.LanguageService/QuickParse.fs rename to src/fsharp/vs/QuickParse.fs index 3dcb71b968c..1530759307b 100644 --- a/vsintegration/src/FSharp.LanguageService/QuickParse.fs +++ b/src/fsharp/vs/QuickParse.fs @@ -1,11 +1,27 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. -namespace Microsoft.VisualStudio.FSharp.LanguageService +namespace Microsoft.FSharp.Compiler open System -open System.Globalization open Microsoft.FSharp.Compiler.SourceCodeServices +/// Qualified long name. +type PartialLongName = + { /// Qualifying idents, prior to the last dot, not including the last part. + QualifyingIdents: string list + + /// Last part of long ident. + PartialIdent: string + + /// The column number at the end of full partial name. + EndColumn: int + + /// Position of the last dot. + LastDotPos: int option } + + /// Empty patial long name. + static member Empty(endColumn: int) = { QualifyingIdents = []; PartialIdent = ""; EndColumn = endColumn; LastDotPos = None } + /// Methods for cheaply and innacurately parsing F#. /// /// These methods are very old and are mostly to do with extracting "long identifier islands" @@ -22,15 +38,15 @@ open Microsoft.FSharp.Compiler.SourceCodeServices /// It's also surprising how hard even the job of getting long identifier islands can be. For example the code /// below is inaccurate for long identifier chains involving ``...`` identifiers. And there are special cases /// for active pattern names and so on. -module internal QuickParse = - open Microsoft.FSharp.Compiler.SourceCodeServices.PrettyNaming - - let magicalAdjustmentConstant = 1 // 0 puts us immediately *before* the last character; 1 puts us after the last character +module QuickParse = + open PrettyNaming + /// Puts us after the last character. + let MagicalAdjustmentConstant = 1 // Adjusts the token tag for the given identifier // - if we're inside active pattern name (at the bar), correct the token TAG to be an identifier - let CorrectIdentifierToken (s:string) tokenTag = - if s.EndsWith "|" then Microsoft.FSharp.Compiler.Parser.tagOfToken (Microsoft.FSharp.Compiler.Parser.token.IDENT s) + let CorrectIdentifierToken (tokenText: string) (tokenTag: int) = + if tokenText.EndsWith "|" then Microsoft.FSharp.Compiler.Parser.tagOfToken (Microsoft.FSharp.Compiler.Parser.token.IDENT tokenText) else tokenTag let rec isValidStrippedName (name:string) idx = @@ -42,7 +58,7 @@ module internal QuickParse = // Extracts the 'core' part without surrounding bars and checks whether it contains some identifier // (Note, this doesn't have to be precise, because this is checked by backround compiler, // but it has to be good enough to distinguish operators and active pattern names) - let private isValidActivePatternName (name:string) = + let private isValidActivePatternName (name: string) = // Strip the surrounding bars (e.g. from "|xyz|_|") to get "xyz" match name.StartsWith("|", System.StringComparison.Ordinal), @@ -52,40 +68,17 @@ module internal QuickParse = | true, _, true when name.Length > 2 -> isValidStrippedName (name.Substring(1, name.Length - 2)) 0 | _ -> false - /// Given a string and a position in that string, find an identifier as - /// expected by `GotoDefinition`. This will work when the cursor is - /// immediately before the identifier, within the identifier, or immediately - /// after the identifier. - /// - /// 'tolerateJustAfter' indicates that we tolerate being one character after the identifier, used - /// for goto-definition - - /// In general, only identifiers composed from upper/lower letters and '.' are supported, but there - /// are a couple of explicitly handled exceptions to allow some common scenarios: - /// - When the name contains only letters and '|' symbol, it may be an active pattern, so we - /// treat it as a valid identifier - e.g. let ( |Identitiy| ) a = a - /// (but other identifiers that include '|' are not allowed - e.g. '||' operator) - /// - It searches for double tick (``) to see if the identifier could be something like ``a b`` - - /// REVIEW: Also support, e.g., operators, performing the necessary mangling. - /// (i.e., I would like that the name returned here can be passed as-is - /// (post `.`-chopping) to `GetDeclarationLocation.) - - /// In addition, return the position where a `.` would go if we were making - /// a call to `DeclItemsForNamesAtPosition` for intellisense. This will - /// allow us to use find the correct qualified items rather than resorting - /// to the more expensive and less accurate environment lookup. - let GetCompleteIdentifierIslandImpl (s : string) (p : int) : (string*int*bool) option = - if p < 0 || isNull s || p >= s.Length then None + let GetCompleteIdentifierIslandImpl (lineStr: string) (index: int) : (string * int * bool) option = + if index < 0 || isNull lineStr || index >= lineStr.Length then None else let fixup = match () with // at a valid position, on a valid character - | _ when (p < s.Length) && (s.[p] = '|' || IsIdentifierPartCharacter s.[p]) -> Some p + | _ when (index < lineStr.Length) && (lineStr.[index] = '|' || IsIdentifierPartCharacter lineStr.[index]) -> Some index | _ -> None // not on a word or '.' - let (|Char|_|) p = if p >=0 && p < s.Length then Some(s.[p]) else None + let (|Char|_|) p = if p >=0 && p < lineStr.Length then Some(lineStr.[p]) else None let (|IsLongIdentifierPartChar|_|) c = if IsLongIdentifierPartCharacter c then Some () else None let (|IsIdentifierPartChar|_|) c = if IsIdentifierPartCharacter c then Some () else None @@ -105,7 +98,7 @@ module internal QuickParse = let tickColsOpt = let rec walkOutsideBackticks i = - if i >= s.Length then None + if i >= lineStr.Length then None else match i, i + 1 with | Char '`', Char '`' -> @@ -113,19 +106,19 @@ module internal QuickParse = // if pos = i then it will be included in backticked range ($``identifier``) walkInsideBackticks (i + 2) i | _, _ -> - if i >= p then None + if i >= index then None else // we still not reached position p - continue walking walkOutsideBackticks (i + 1) and walkInsideBackticks i start = - if i >= s.Length then None // non-closed backticks + if i >= lineStr.Length then None // non-closed backticks else match i, i + 1 with | Char '`', Char '`' -> // found closing pair of backticks // if target position is between start and current pos + 1 (entire range of escaped identifier including backticks) - return success // else climb outside and continue walking - if p >= start && p < (i + 2) then Some (start, i) + if index >= start && index < (i + 2) then Some (start, i) else walkOutsideBackticks (i + 2) | _, _ -> walkInsideBackticks (i + 1) start @@ -134,43 +127,66 @@ module internal QuickParse = match tickColsOpt with | Some (prevTickTick, idxTickTick) -> // inside ``identifier`` (which can contain any characters!) so we try returning its location - let pos = idxTickTick + 1 + magicalAdjustmentConstant - let ident = s.Substring(prevTickTick, idxTickTick - prevTickTick + 2) + let pos = idxTickTick + 1 + MagicalAdjustmentConstant + let ident = lineStr.Substring(prevTickTick, idxTickTick - prevTickTick + 2) Some(ident, pos, true) | _ -> // find location of an ordinary identifier fixup |> Option.bind (fun p -> let l = searchLeft p let r = searchRight p - let ident = s.Substring (l, r - l + 1) + let ident = lineStr.Substring (l, r - l + 1) if ident.IndexOf('|') <> -1 && not(isValidActivePatternName(ident)) then None else - let pos = r + magicalAdjustmentConstant + let pos = r + MagicalAdjustmentConstant Some(ident, pos, false) ) - let GetCompleteIdentifierIsland (tolerateJustAfter:bool) (s : string) (p : int) : (string*int*bool) option = - if String.IsNullOrEmpty s then None + /// Given a string and a position in that string, find an identifier as + /// expected by `GotoDefinition`. This will work when the cursor is + /// immediately before the identifier, within the identifier, or immediately + /// after the identifier. + /// + /// 'tolerateJustAfter' indicates that we tolerate being one character after the identifier, used + /// for goto-definition + /// + /// In general, only identifiers composed from upper/lower letters and '.' are supported, but there + /// are a couple of explicitly handled exceptions to allow some common scenarios: + /// - When the name contains only letters and '|' symbol, it may be an active pattern, so we + /// treat it as a valid identifier - e.g. let ( |Identitiy| ) a = a + /// (but other identifiers that include '|' are not allowed - e.g. '||' operator) + /// - It searches for double tick (``) to see if the identifier could be something like ``a b`` + /// + /// REVIEW: Also support, e.g., operators, performing the necessary mangling. + /// (i.e., I would like that the name returned here can be passed as-is + /// (post `.`-chopping) to `GetDeclarationLocation.) + /// + /// In addition, return the position where a `.` would go if we were making + /// a call to `DeclItemsForNamesAtPosition` for intellisense. This will + /// allow us to use find the correct qualified items rather than resorting + /// to the more expensive and less accurate environment lookup. + let GetCompleteIdentifierIsland (tolerateJustAfter: bool) (lineStr: string) (index: int) : (string * int * bool) option = + if String.IsNullOrEmpty lineStr then None else - let directResult = GetCompleteIdentifierIslandImpl s p + let directResult = GetCompleteIdentifierIslandImpl lineStr index if tolerateJustAfter && directResult = None then - GetCompleteIdentifierIslandImpl s (p-1) + GetCompleteIdentifierIslandImpl lineStr (index - 1) else directResult - let private defaultName = [],"" + let private defaultName = [], "" /// Get the partial long name of the identifier to the left of index. - let GetPartialLongName(line:string,index) = - if isNull line then defaultName + let GetPartialLongName(lineStr: string, index: int) = + if isNull lineStr then defaultName elif index < 0 then defaultName - elif index >= line.Length then defaultName + elif index >= lineStr.Length then defaultName else - let IsIdentifierPartCharacter pos = IsIdentifierPartCharacter line.[pos] - let IsLongIdentifierPartCharacter pos = IsLongIdentifierPartCharacter line.[pos] - let IsDot pos = line.[pos] = '.' + let IsIdentifierPartCharacter pos = IsIdentifierPartCharacter lineStr.[pos] + let IsLongIdentifierPartCharacter pos = IsLongIdentifierPartCharacter lineStr.[pos] + let IsDot pos = lineStr.[pos] = '.' let rec InLeadingIdentifier(pos,right,(prior,residue)) = - let PushName() = ((line.Substring(pos+1,right-pos-1))::prior),residue + let PushName() = ((lineStr.Substring(pos+1,right-pos-1))::prior),residue if pos < 0 then PushName() elif IsIdentifierPartCharacter pos then InLeadingIdentifier(pos-1,right,(prior,residue)) elif IsDot pos then InLeadingIdentifier(pos-1,pos,PushName()) @@ -178,132 +194,150 @@ module internal QuickParse = let rec InName(pos,startResidue,right) = let NameAndResidue() = - [line.Substring(pos+1,startResidue-pos-1)],(line.Substring(startResidue+1,right-startResidue)) - if pos < 0 then [line.Substring(pos+1,startResidue-pos-1)],(line.Substring(startResidue+1,right-startResidue)) + [lineStr.Substring(pos+1,startResidue-pos-1)],(lineStr.Substring(startResidue+1,right-startResidue)) + if pos < 0 then [lineStr.Substring(pos+1,startResidue-pos-1)],(lineStr.Substring(startResidue+1,right-startResidue)) elif IsIdentifierPartCharacter pos then InName(pos-1,startResidue,right) elif IsDot pos then InLeadingIdentifier(pos-1,pos,NameAndResidue()) else NameAndResidue() let rec InResidue(pos,right) = - if pos < 0 then [],line.Substring(pos+1,right-pos) + if pos < 0 then [],lineStr.Substring(pos+1,right-pos) elif IsDot pos then InName(pos-1,pos,right) elif IsLongIdentifierPartCharacter pos then InResidue(pos-1, right) - else [],line.Substring(pos+1,right-pos) + else [],lineStr.Substring(pos+1,right-pos) let result = InResidue(index,index) result type private EatCommentCallContext = - | SkipWhiteSpaces of string * string list * bool - | StartIdentifier of string list * bool + | SkipWhiteSpaces of ident: string * current: string list * throwAwayNext: bool + | StartIdentifier of current: string list * throwAway: bool /// Get the partial long name of the identifier to the left of index. - /// For example, for `System.DateTime.Now` it returns ([|"System"; "DateTime"|], "Now"). - let GetPartialLongNameEx(line:string,index) : (string list * string) = - if isNull line then defaultName - elif index < 0 then defaultName - elif index >= line.Length then defaultName + /// For example, for `System.DateTime.Now` it returns PartialLongName ([|"System"; "DateTime"|], "Now", Some 32), where "32" pos of the last dot. + let GetPartialLongNameEx(lineStr: string, index: int) : PartialLongName = + if isNull lineStr then PartialLongName.Empty(index) + elif index < 0 then PartialLongName.Empty(index) + elif index >= lineStr.Length then PartialLongName.Empty(index) else - let IsIdentifierPartCharacter pos = IsIdentifierPartCharacter line.[pos] + let IsIdentifierPartCharacter pos = IsIdentifierPartCharacter lineStr.[pos] let IsIdentifierStartCharacter pos = IsIdentifierPartCharacter pos - let IsDot pos = line.[pos] = '.' - let IsTick pos = line.[pos] = '`' - let IsEndOfComment pos = pos < index - 1 && line.[pos] = '*' && line.[pos + 1] = ')' - let IsStartOfComment pos = pos < index - 1 && line.[pos] = '(' && line.[pos + 1] = '*' - let IsWhitespace pos = Char.IsWhiteSpace(line.[pos]) + let IsDot pos = lineStr.[pos] = '.' + let IsTick pos = lineStr.[pos] = '`' + let IsEndOfComment pos = pos < index - 1 && lineStr.[pos] = '*' && lineStr.[pos + 1] = ')' + let IsStartOfComment pos = pos < index - 1 && lineStr.[pos] = '(' && lineStr.[pos + 1] = '*' + let IsWhitespace pos = Char.IsWhiteSpace(lineStr.[pos]) - let rec SkipWhitespaceBeforeDotIdentifier(pos, ident, current,throwAwayNext) = - if pos > index then defaultName // we're in whitespace after an identifier, if this is where the cursor is, there is no PLID here - elif IsWhitespace pos then SkipWhitespaceBeforeDotIdentifier(pos+1,ident,current,throwAwayNext) - elif IsDot pos then AtStartOfIdentifier(pos+1,ident::current,throwAwayNext) - elif IsStartOfComment pos then EatComment(1, pos + 1, EatCommentCallContext.SkipWhiteSpaces(ident, current, throwAwayNext)) - else AtStartOfIdentifier(pos,[],false) // Throw away what we have and start over. + let rec SkipWhitespaceBeforeDotIdentifier(pos, ident, current, throwAwayNext, lastDotPos) = + if pos > index then PartialLongName.Empty(index) // we're in whitespace after an identifier, if this is where the cursor is, there is no PLID here + elif IsWhitespace pos then SkipWhitespaceBeforeDotIdentifier(pos+1,ident,current,throwAwayNext,lastDotPos) + elif IsDot pos then AtStartOfIdentifier(pos+1,ident::current,throwAwayNext, Some pos) + elif IsStartOfComment pos then EatComment(1, pos + 1, EatCommentCallContext.SkipWhiteSpaces(ident, current, throwAwayNext), lastDotPos) + else AtStartOfIdentifier(pos,[],false,None) // Throw away what we have and start over. - and EatComment (nesting, pos, callContext) = - if pos > index then defaultName else + and EatComment (nesting, pos, callContext,lastDotPos) = + if pos > index then PartialLongName.Empty(index) else if IsStartOfComment pos then // track balance of closing '*)' - EatComment(nesting + 1, pos + 2, callContext) + EatComment(nesting + 1, pos + 2, callContext,lastDotPos) else if IsEndOfComment pos then if nesting = 1 then // all right, we are at the end of comment, jump outside match callContext with | EatCommentCallContext.SkipWhiteSpaces(ident, current, throwAway) -> - SkipWhitespaceBeforeDotIdentifier(pos + 2, ident, current, throwAway) + SkipWhitespaceBeforeDotIdentifier(pos + 2, ident, current, throwAway,lastDotPos) | EatCommentCallContext.StartIdentifier(current, throwAway) -> - AtStartOfIdentifier(pos + 2, current, throwAway) + AtStartOfIdentifier(pos + 2, current, throwAway,lastDotPos) else // reduce level of nesting and continue - EatComment(nesting - 1, pos + 2, callContext) + EatComment(nesting - 1, pos + 2, callContext, lastDotPos) else // eat next char - EatComment(nesting, pos + 1, callContext) + EatComment(nesting, pos + 1, callContext, lastDotPos) - and InUnquotedIdentifier(left:int,pos:int,current,throwAwayNext) = + and InUnquotedIdentifier(left:int,pos:int,current,throwAwayNext,lastDotPos) = if pos > index then - if throwAwayNext then defaultName else current,line.Substring(left,pos-left) + if throwAwayNext then + PartialLongName.Empty(index) + else + { QualifyingIdents = current + PartialIdent = lineStr.Substring(left,pos-left) + EndColumn = index + LastDotPos = lastDotPos } else - if IsIdentifierPartCharacter pos then InUnquotedIdentifier(left,pos+1,current,throwAwayNext) + if IsIdentifierPartCharacter pos then InUnquotedIdentifier(left,pos+1,current,throwAwayNext,lastDotPos) elif IsDot pos then - let ident = line.Substring(left,pos-left) - AtStartOfIdentifier(pos+1,ident::current,throwAwayNext) + let ident = lineStr.Substring(left,pos-left) + AtStartOfIdentifier(pos+1,ident::current,throwAwayNext, Some pos) elif IsWhitespace pos || IsStartOfComment pos then - let ident = line.Substring(left,pos-left) - SkipWhitespaceBeforeDotIdentifier(pos, ident, current,throwAwayNext) - else AtStartOfIdentifier(pos,[],false) // Throw away what we have and start over. + let ident = lineStr.Substring(left,pos-left) + SkipWhitespaceBeforeDotIdentifier(pos, ident, current, throwAwayNext, lastDotPos) + else AtStartOfIdentifier(pos,[],false,None) // Throw away what we have and start over. - and InQuotedIdentifier(left:int,pos:int, current,throwAwayNext) = + and InQuotedIdentifier(left:int,pos:int, current,throwAwayNext,lastDotPos) = if pos > index then - if throwAwayNext then defaultName else current,line.Substring(left,pos-left) + if throwAwayNext then + PartialLongName.Empty(index) + else + { QualifyingIdents = current + PartialIdent = lineStr.Substring(left,pos-left) + EndColumn = index + LastDotPos = lastDotPos } else - let remainingLength = line.Length - pos + let remainingLength = lineStr.Length - pos if IsTick pos && remainingLength > 1 && IsTick(pos+1) then - let ident = line.Substring(left, pos-left) - SkipWhitespaceBeforeDotIdentifier(pos+2,ident,current,throwAwayNext) - else InQuotedIdentifier(left,pos+1,current,throwAwayNext) + let ident = lineStr.Substring(left, pos-left) + SkipWhitespaceBeforeDotIdentifier(pos+2,ident,current,throwAwayNext,lastDotPos) + else InQuotedIdentifier(left,pos+1,current,throwAwayNext,lastDotPos) - and AtStartOfIdentifier(pos:int, current, throwAwayNext) = + and AtStartOfIdentifier(pos:int, current, throwAwayNext, lastDotPos: int option) = if pos > index then - if throwAwayNext then defaultName else current,"" + if throwAwayNext then + PartialLongName.Empty(index) + else + { QualifyingIdents = current + PartialIdent = "" + EndColumn = index + LastDotPos = lastDotPos } else - if IsWhitespace pos then AtStartOfIdentifier(pos+1,current,throwAwayNext) + if IsWhitespace pos then AtStartOfIdentifier(pos+1,current,throwAwayNext, lastDotPos) else - let remainingLength = line.Length - pos - if IsTick pos && remainingLength > 1 && IsTick(pos+1) then InQuotedIdentifier(pos+2,pos+2,current,throwAwayNext) - elif IsStartOfComment pos then EatComment(1, pos + 1, EatCommentCallContext.StartIdentifier(current, throwAwayNext)) - elif IsIdentifierStartCharacter pos then InUnquotedIdentifier(pos,pos+1,current,throwAwayNext) + let remainingLength = lineStr.Length - pos + if IsTick pos && remainingLength > 1 && IsTick(pos+1) then InQuotedIdentifier(pos+2,pos+2,current,throwAwayNext,lastDotPos) + elif IsStartOfComment pos then EatComment(1, pos + 1, EatCommentCallContext.StartIdentifier(current, throwAwayNext), lastDotPos) + elif IsIdentifierStartCharacter pos then InUnquotedIdentifier(pos,pos+1,current,throwAwayNext,lastDotPos) elif IsDot pos then if pos = 0 then // dot on first char of line, currently treat it like empty identifier to the left - AtStartOfIdentifier(pos+1,""::current,throwAwayNext) + AtStartOfIdentifier(pos+1,""::current,throwAwayNext, Some pos) elif not (pos > 0 && (IsIdentifierPartCharacter(pos-1) || IsWhitespace(pos-1))) then // it's not dots as part.of.a.long.ident, it's e.g. the range operator (..), or some other multi-char operator ending in dot - if line.[pos-1] = ')' then + if lineStr.[pos-1] = ')' then // one very problematic case is someCall(args).Name // without special logic, we will decide that ). is an operator and parse Name as the plid // but in fact this is an expression tail, and we don't want a plid, rather we need to use expression typings at that location // so be sure not to treat the name here as a plid - AtStartOfIdentifier(pos+1,[],true) // Throw away what we have, and the next apparent plid, and start over. + AtStartOfIdentifier(pos+1,[],true,None) // Throw away what we have, and the next apparent plid, and start over. else - AtStartOfIdentifier(pos+1,[],false) // Throw away what we have and start over. + AtStartOfIdentifier(pos+1,[],false,None) // Throw away what we have and start over. else - AtStartOfIdentifier(pos+1,""::current,throwAwayNext) - else AtStartOfIdentifier(pos+1,[],throwAwayNext) - let plid, residue = AtStartOfIdentifier(0,[],false) - let plid = List.rev plid - match plid with - | s::_rest when s.Length > 0 && Char.IsDigit(s.[0]) -> defaultName // "2.0" is not a longId (this might not be right for ``2.0`` but good enough for common case) - | _ -> plid, residue + AtStartOfIdentifier(pos+1,""::current,throwAwayNext, Some pos) + else AtStartOfIdentifier(pos+1,[],throwAwayNext, None) + let partialLongName = AtStartOfIdentifier(0, [], false, None) + + match List.rev partialLongName.QualifyingIdents with + | s :: _ when s.Length > 0 && Char.IsDigit(s.[0]) -> PartialLongName.Empty(index) // "2.0" is not a longId (this might not be right for ``2.0`` but good enough for common case) + | plid -> { partialLongName with QualifyingIdents = plid } - let TokenNameEquals (tokenInfo : FSharpTokenInfo) token2 = + let TokenNameEquals (tokenInfo: FSharpTokenInfo) (token2: string) = String.Compare(tokenInfo .TokenName, token2, StringComparison.OrdinalIgnoreCase) = 0 // The prefix of the sequence of token names to look for in TestMemberOrOverrideDeclaration, in reverse order let private expected = [ [|"dot"|]; [|"ident"|]; [|"member"; "override"|] ] /// Tests whether the user is typing something like "member x." or "override (*comment*) x." - let internal TestMemberOrOverrideDeclaration (tokens:FSharpTokenInfo[]) = + let TestMemberOrOverrideDeclaration (tokens: FSharpTokenInfo[]) = let filteredReversed = tokens |> Array.filter (fun tok -> diff --git a/src/fsharp/vs/QuickParse.fsi b/src/fsharp/vs/QuickParse.fsi new file mode 100644 index 00000000000..78bfa2b39f3 --- /dev/null +++ b/src/fsharp/vs/QuickParse.fsi @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Compiler + +open System +open Microsoft.FSharp.Compiler.SourceCodeServices + +/// Qualified long name. +#if COMPILER_PUBLIC_API +type PartialLongName = +#else +type internal PartialLongName = +#endif + { /// Qualifying idents, prior to the last dot, not including the last part. + QualifyingIdents: string list + + /// Last part of long ident. + PartialIdent: string + + /// The column number at the end of full partial name. + EndColumn: int + + /// Position of the last dot. + LastDotPos: int option } + + /// Empty patial long name. + static member Empty: endColumn: int -> PartialLongName + +/// Methods for cheaply and innacurately parsing F#. +/// +/// These methods are very old and are mostly to do with extracting "long identifier islands" +/// A.B.C +/// from F# source code, an approach taken from pre-F# VS samples for implementing intelliense. +/// +/// This code should really no longer be needed since the language service has access to +/// parsed F# source code ASTs. However, the long identifiers are still passed back to GetDeclarations and friends in the +/// F# Compiler Service and it's annoyingly hard to remove their use completely. +/// +/// In general it is unlikely much progress will be made by fixing this code - it will be better to +/// extract more information from the F# ASTs. +/// +/// It's also surprising how hard even the job of getting long identifier islands can be. For example the code +/// below is inaccurate for long identifier chains involving ``...`` identifiers. And there are special cases +/// for active pattern names and so on. +#if COMPILER_PUBLIC_API +module QuickParse = +#else +module internal QuickParse = +#endif + /// Puts us after the last character. + val MagicalAdjustmentConstant : int + + // Adjusts the token tag for the given identifier + // - if we're inside active pattern name (at the bar), correct the token TAG to be an identifier + val CorrectIdentifierToken : tokenText: string -> tokenTag: int -> int + + /// Given a string and a position in that string, find an identifier as + /// expected by `GotoDefinition`. This will work when the cursor is + /// immediately before the identifier, within the identifier, or immediately + /// after the identifier. + /// + /// 'tolerateJustAfter' indicates that we tolerate being one character after the identifier, used + /// for goto-definition + /// + /// In general, only identifiers composed from upper/lower letters and '.' are supported, but there + /// are a couple of explicitly handled exceptions to allow some common scenarios: + /// - When the name contains only letters and '|' symbol, it may be an active pattern, so we + /// treat it as a valid identifier - e.g. let ( |Identitiy| ) a = a + /// (but other identifiers that include '|' are not allowed - e.g. '||' operator) + /// - It searches for double tick (``) to see if the identifier could be something like ``a b`` + /// + /// REVIEW: Also support, e.g., operators, performing the necessary mangling. + /// (i.e., I would like that the name returned here can be passed as-is + /// (post `.`-chopping) to `GetDeclarationLocation.) + /// + /// In addition, return the position where a `.` would go if we were making + /// a call to `DeclItemsForNamesAtPosition` for intellisense. This will + /// allow us to use find the correct qualified items rather than resorting + /// to the more expensive and less accurate environment lookup. + val GetCompleteIdentifierIsland : tolerateJustAfter: bool -> tokenText: string -> index: int -> (string * int * bool) option + + /// Get the partial long name of the identifier to the left of index. + val GetPartialLongName : lineStr: string * index: int -> (string list * string) + + /// Get the partial long name of the identifier to the left of index. + /// For example, for `System.DateTime.Now` it returns PartialLongName ([|"System"; "DateTime"|], "Now", Some 32), where "32" pos of the last dot. + val GetPartialLongNameEx : lineStr: string * index: int -> PartialLongName + + /// Tests whether the user is typing something like "member x." or "override (*comment*) x." + val TestMemberOrOverrideDeclaration : tokens: FSharpTokenInfo[] -> bool \ No newline at end of file diff --git a/src/fsharp/vs/service.fs b/src/fsharp/vs/service.fs index 5c2fc8f5445..3d86ffa63cf 100644 --- a/src/fsharp/vs/service.fs +++ b/src/fsharp/vs/service.fs @@ -140,7 +140,7 @@ type SemanticClassificationType = | TypeArgument | Operator | Disposable - + /// A TypeCheckInfo represents everything we get back from the typecheck of a file. /// It acts like an in-memory database about the file. /// It is effectively immutable and not updated: when we re-typecheck we just drop the previous @@ -216,7 +216,7 @@ type TypeCheckInfo | None -> true if contained then - match !bestAlmostIncludedSoFar with + match !bestAlmostIncludedSoFar with | Some (rightm:range,_,_) -> if posGt possm.End rightm.End || (posEq possm.End rightm.End && posGt possm.Start rightm.Start) then @@ -567,14 +567,17 @@ type TypeCheckInfo | Item.Value _ -> CompletionItemKind.Field | _ -> CompletionItemKind.Other + let getNamespace (idents: Idents) = + if idents.Length > 1 then Some idents.[..idents.Length - 2] else None + let unresolved = unresolvedEntity |> Option.map (fun x -> - let ns = - match x.TopRequireQualifiedAccessParent with - | Some parent when not (Array.isEmpty parent) -> - parent.[..parent.Length - 2] - | _ -> x.CleanedIdents.[..x.CleanedIdents.Length - 2] + let ns = + x.TopRequireQualifiedAccessParent + |> Option.bind getNamespace + |> Option.orElseWith (fun () -> getNamespace x.CleanedIdents) + |> Option.defaultValue [||] let displayName = x.CleanedIdents |> Array.skip ns.Length |> String.concat "." @@ -591,7 +594,7 @@ type TypeCheckInfo let DefaultCompletionItem item = CompletionItem None None item let getItem (x: ItemWithInst) = x.Item - let GetDeclaredItems (parseResultsOpt: FSharpParseFileResults option, lineStr: string, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, line, loc, + let GetDeclaredItems (parseResultsOpt: FSharpParseFileResults option, lineStr: string, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, lastDotPos, line, loc, filterCtors, resolveOverloads, hasTextChangedSinceLastTypecheck, isInRangeOperator, allSymbols: unit -> AssemblySymbol list) = // Are the last two chars (except whitespaces) = ".." @@ -612,18 +615,12 @@ type TypeCheckInfo // deals with cases when we have spaces between dot and\or identifier, like A . $ // if this is our case - then we need to locate end position of the name skipping whitespaces // this allows us to handle cases like: let x . $ = 1 - - // colAtEndOfNamesAndResidue is 1-based so at first we need to convert it to 0-based - // - // TODO: this code would be a lot simpler if we just passed in colAtEndOfNames in - // the first place. colAtEndOfNamesAndResidue serves no purpose. The cracking below is - // inaccurate and incomplete in any case since it only works on a single line. - match FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1) with + match lastDotPos |> Option.orElseWith (fun _ -> FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1)) with | Some p when lineStr.[p] = '.' -> match FindFirstNonWhitespacePosition lineStr (p - 1) with | Some colAtEndOfNames -> - let colAtEndOfNames = colAtEndOfNames + 1 // convert 0-based to 1-based - GetPreciseItemsFromNameResolution(line, colAtEndOfNames, Some(residue), filterCtors,resolveOverloads, hasTextChangedSinceLastTypecheck) + let colAtEndOfNames = colAtEndOfNames + 1 // convert 0-based to 1-based + GetPreciseItemsFromNameResolution(line, colAtEndOfNames, Some(residue), filterCtors,resolveOverloads, hasTextChangedSinceLastTypecheck) | None -> NameResResult.Empty | _ -> NameResResult.Empty @@ -647,7 +644,7 @@ type TypeCheckInfo match NameResolution.TryToResolveLongIdentAsType ncenv nenv m plid with | Some x -> Some x | None -> - match FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1) with + match lastDotPos |> Option.orElseWith (fun _ -> FindFirstNonWhitespacePosition lineStr (colAtEndOfNamesAndResidue - 1)) with | Some p when lineStr.[p] = '.' -> match FindFirstNonWhitespacePosition lineStr (p - 1) with | Some colAtEndOfNames -> @@ -769,7 +766,7 @@ type TypeCheckInfo /// Get the auto-complete items at a particular location. let GetDeclItemsForNamesAtPosition(ctok: CompilationThreadToken, parseResultsOpt: FSharpParseFileResults option, origLongIdentOpt: string list option, - residueOpt:string option, line:int, lineStr:string, colAtEndOfNamesAndResidue, filterCtors, resolveOverloads, + residueOpt:string option, lastDotPos: int option, line:int, lineStr:string, colAtEndOfNamesAndResidue, filterCtors, resolveOverloads, getAllSymbols: unit -> AssemblySymbol list, hasTextChangedSinceLastTypecheck: (obj * range -> bool)) : (CompletionItem list * DisplayEnv * CompletionContext option * range) option = RequireCompilationThread ctok // the operations in this method need the reactor thread @@ -812,7 +809,7 @@ type TypeCheckInfo match GetClassOrRecordFieldsEnvironmentLookupResolutions(mkPos line loc, plid) |> toCompletionItems with | [],_,_ -> // no record fields found, return completion list as if we were outside any computation expression - GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, line, loc, filterCtors,resolveOverloads, hasTextChangedSinceLastTypecheck, false, fun() -> []) + GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, lastDotPos, line, loc, filterCtors,resolveOverloads, hasTextChangedSinceLastTypecheck, false, fun() -> []) | result -> Some(result) // Completion at ' { XXX = ... with ... } " @@ -835,7 +832,7 @@ type TypeCheckInfo let results = GetNamedParametersAndSettableFields endPos hasTextChangedSinceLastTypecheck let declaredItems = - GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, line, loc, filterCtors, resolveOverloads, + GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, lastDotPos, line, loc, filterCtors, resolveOverloads, hasTextChangedSinceLastTypecheck, false, getAllSymbols) match results with @@ -858,7 +855,7 @@ type TypeCheckInfo | _ -> declaredItems | Some(CompletionContext.AttributeApplication) -> - GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, line, loc, filterCtors, resolveOverloads, hasTextChangedSinceLastTypecheck, false, getAllSymbols) + GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, lastDotPos, line, loc, filterCtors, resolveOverloads, hasTextChangedSinceLastTypecheck, false, getAllSymbols) |> Option.map (fun (items, denv, m) -> items |> List.filter (fun cItem -> @@ -868,14 +865,14 @@ type TypeCheckInfo | _ -> false), denv, m) | Some(CompletionContext.OpenDeclaration) -> - GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, line, loc, filterCtors, resolveOverloads, hasTextChangedSinceLastTypecheck, false, getAllSymbols) + GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, lastDotPos, line, loc, filterCtors, resolveOverloads, hasTextChangedSinceLastTypecheck, false, getAllSymbols) |> Option.map (fun (items, denv, m) -> items |> List.filter (fun x -> match x.Item with Item.ModuleOrNamespaces _ -> true | _ -> false), denv, m) // Other completions | cc -> let isInRangeOperator = (match cc with Some (CompletionContext.RangeOperator) -> true | _ -> false) - GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, line, loc, filterCtors,resolveOverloads, hasTextChangedSinceLastTypecheck, isInRangeOperator, getAllSymbols) + GetDeclaredItems (parseResultsOpt, lineStr, origLongIdentOpt, colAtEndOfNamesAndResidue, residueOpt, lastDotPos, line, loc, filterCtors,resolveOverloads, hasTextChangedSinceLastTypecheck, isInRangeOperator, getAllSymbols) res |> Option.map (fun (items, denv, m) -> items, denv, completionContext, m) @@ -900,13 +897,17 @@ type TypeCheckInfo (fun msg -> Trace.TraceInformation(sprintf "FCS: recovering from error in IsRelativeNameResolvable: '%s'" msg) false) + + /// Determines if a long ident is resolvable at a specific point. + member scope.IsRelativeNameResolvableFromSymbol(cursorPos: pos, plid: string list, symbol: FSharpSymbol) : bool = + scope.IsRelativeNameResolvable(cursorPos, plid, symbol.Item) /// Get the auto-complete items at a location - member __.GetDeclarations (ctok, parseResultsOpt, line, lineStr, colAtEndOfNamesAndResidue, qualifyingNames, partialName, getAllSymbols, hasTextChangedSinceLastTypecheck) = + member __.GetDeclarations (ctok, parseResultsOpt, line, lineStr, partialName, getAllSymbols, hasTextChangedSinceLastTypecheck) = let isInterfaceFile = SourceFileImpl.IsInterfaceFile mainInputFileName ErrorScope.Protect Range.range0 - (fun () -> - match GetDeclItemsForNamesAtPosition(ctok, parseResultsOpt, Some qualifyingNames, Some partialName, line, lineStr, colAtEndOfNamesAndResidue, ResolveTypeNamesToCtors, ResolveOverloads.Yes, getAllSymbols, hasTextChangedSinceLastTypecheck) with + (fun () -> + match GetDeclItemsForNamesAtPosition(ctok, parseResultsOpt, Some partialName.QualifyingIdents, Some partialName.PartialIdent, partialName.LastDotPos, line, lineStr, partialName.EndColumn + 1, ResolveTypeNamesToCtors, ResolveOverloads.Yes, getAllSymbols, hasTextChangedSinceLastTypecheck) with | None -> FSharpDeclarationListInfo.Empty | Some (items, denv, ctx, m) -> let items = if isInterfaceFile then items |> List.filter (fun x -> IsValidSignatureFileItem x.Item) else items @@ -922,11 +923,11 @@ type TypeCheckInfo FSharpDeclarationListInfo.Error msg) /// Get the symbols for auto-complete items at a location - member __.GetDeclarationListSymbols (ctok, parseResultsOpt, line, lineStr, colAtEndOfNamesAndResidue, qualifyingNames, partialName, hasTextChangedSinceLastTypecheck) = + member __.GetDeclarationListSymbols (ctok, parseResultsOpt, line, lineStr, partialName, hasTextChangedSinceLastTypecheck) = let isInterfaceFile = SourceFileImpl.IsInterfaceFile mainInputFileName ErrorScope.Protect Range.range0 (fun () -> - match GetDeclItemsForNamesAtPosition(ctok, parseResultsOpt, Some qualifyingNames, Some partialName, line, lineStr, colAtEndOfNamesAndResidue, ResolveTypeNamesToCtors, ResolveOverloads.Yes, (fun () -> []), hasTextChangedSinceLastTypecheck) with + match GetDeclItemsForNamesAtPosition(ctok, parseResultsOpt, Some partialName.QualifyingIdents, Some partialName.PartialIdent, partialName.LastDotPos, line, lineStr, partialName.EndColumn + 1, ResolveTypeNamesToCtors, ResolveOverloads.Yes, (fun () -> []), hasTextChangedSinceLastTypecheck) with | None -> List.Empty | Some (items, denv, _, m) -> let items = if isInterfaceFile then items |> List.filter (fun x -> IsValidSignatureFileItem x.Item) else items @@ -1028,7 +1029,7 @@ type TypeCheckInfo let Compute() = ErrorScope.Protect Range.range0 (fun () -> - match GetDeclItemsForNamesAtPosition(ctok, None,Some(names),None,line,lineStr,colAtEndOfNames,ResolveTypeNamesToCtors,ResolveOverloads.Yes,(fun() -> []),fun _ -> false) with + match GetDeclItemsForNamesAtPosition(ctok, None,Some(names),None,None,line,lineStr,colAtEndOfNames,ResolveTypeNamesToCtors,ResolveOverloads.Yes,(fun() -> []),fun _ -> false) with | None -> FSharpToolTipText [] | Some(items, denv, _, m) -> FSharpToolTipText(items |> List.map (fun x -> FormatStructuredDescriptionOfItem false infoReader m denv x.ItemWithInst))) @@ -1048,7 +1049,7 @@ type TypeCheckInfo member __.GetF1Keyword (ctok, line, lineStr, colAtEndOfNames, names) : string option = ErrorScope.Protect Range.range0 (fun () -> - match GetDeclItemsForNamesAtPosition(ctok, None, Some names, None, line, lineStr, colAtEndOfNames, ResolveTypeNamesToCtors, ResolveOverloads.No,(fun() -> []), fun _ -> false) with // F1 Keywords do not distinguish between overloads + match GetDeclItemsForNamesAtPosition(ctok, None, Some names, None, None, line, lineStr, colAtEndOfNames, ResolveTypeNamesToCtors, ResolveOverloads.No,(fun() -> []), fun _ -> false) with // F1 Keywords do not distinguish between overloads | None -> None | Some (items: CompletionItem list, _,_, _) -> match items with @@ -1080,7 +1081,7 @@ type TypeCheckInfo member __.GetMethods (ctok, line, lineStr, colAtEndOfNames, namesOpt) = ErrorScope.Protect Range.range0 (fun () -> - match GetDeclItemsForNamesAtPosition(ctok, None,namesOpt,None,line,lineStr,colAtEndOfNames,ResolveTypeNamesToCtors,ResolveOverloads.No,(fun() -> []),fun _ -> false) with + match GetDeclItemsForNamesAtPosition(ctok, None,namesOpt,None,None,line,lineStr,colAtEndOfNames,ResolveTypeNamesToCtors,ResolveOverloads.No,(fun() -> []),fun _ -> false) with | None -> FSharpMethodGroup("",[| |]) | Some (items, denv, _, m) -> FSharpMethodGroup.Create(infoReader, m, denv, items |> List.map (fun x -> x.ItemWithInst))) (fun msg -> @@ -1090,7 +1091,7 @@ type TypeCheckInfo member __.GetMethodsAsSymbols (ctok, line, lineStr, colAtEndOfNames, names) = ErrorScope.Protect Range.range0 (fun () -> - match GetDeclItemsForNamesAtPosition (ctok, None,Some(names), None, line, lineStr, colAtEndOfNames, ResolveTypeNamesToCtors, ResolveOverloads.No,(fun() -> []),fun _ -> false) with + match GetDeclItemsForNamesAtPosition (ctok, None,Some(names), None, None,line, lineStr, colAtEndOfNames, ResolveTypeNamesToCtors, ResolveOverloads.No,(fun() -> []),fun _ -> false) with | None | Some ([],_,_,_) -> None | Some (items, denv, _, m) -> let allItems = items |> List.collect (fun item -> SymbolHelpers.FlattenItems g m item.Item) @@ -1104,7 +1105,7 @@ type TypeCheckInfo member scope.GetDeclarationLocation (ctok, line, lineStr, colAtEndOfNames, names, preferFlag) = ErrorScope.Protect Range.range0 (fun () -> - match GetDeclItemsForNamesAtPosition (ctok, None,Some(names), None, line, lineStr, colAtEndOfNames, ResolveTypeNamesToCtors,ResolveOverloads.Yes,(fun() -> []), fun _ -> false) with + match GetDeclItemsForNamesAtPosition (ctok, None,Some(names), None, None, line, lineStr, colAtEndOfNames, ResolveTypeNamesToCtors,ResolveOverloads.Yes,(fun() -> []), fun _ -> false) with | None | Some ([], _, _, _) -> FSharpFindDeclResult.DeclNotFound (FSharpFindDeclFailureReason.Unknown "") | Some (item :: _, _, _, _) -> @@ -1209,7 +1210,7 @@ type TypeCheckInfo member scope.GetSymbolUseAtLocation (ctok, line, lineStr, colAtEndOfNames, names) = ErrorScope.Protect Range.range0 (fun () -> - match GetDeclItemsForNamesAtPosition (ctok, None,Some(names), None, line, lineStr, colAtEndOfNames, ResolveTypeNamesToCtors, ResolveOverloads.Yes,(fun() -> []), fun _ -> false) with + match GetDeclItemsForNamesAtPosition (ctok, None,Some(names), None, None, line, lineStr, colAtEndOfNames, ResolveTypeNamesToCtors, ResolveOverloads.Yes,(fun() -> []), fun _ -> false) with | None | Some ([], _, _, _) -> None | Some (item :: _, denv, _, m) -> let symbol = FSharpSymbol.Create(g, thisCcu, tcImports, item.Item) @@ -1396,7 +1397,7 @@ type FSharpParsingOptions = } static member FromTcConfigBuidler(tcConfigB: TcConfigBuilder, sourceFiles) = - { + { SourceFiles = sourceFiles ConditionalCompilationDefines = tcConfigB.conditionalCompilationDefines ErrorSeverityOptions = tcConfigB.errorSeverityOptions @@ -1724,7 +1725,7 @@ type FSharpProjectOptions = member x.ProjectOptions = x.OtherOptions /// Whether the two parse options refer to the same project. static member UseSameProjectFileName(options1,options2) = - options1.ProjectFileName = options2.ProjectFileName + options1.ProjectFileName = options2.ProjectFileName /// Compare two options sets with respect to the parts of the options that are important to building. static member AreSameForChecking(options1,options2) = @@ -1737,7 +1738,9 @@ type FSharpProjectOptions = options1.UnresolvedReferences = options2.UnresolvedReferences && options1.OriginalLoadReferences = options2.OriginalLoadReferences && options1.ReferencedProjects.Length = options2.ReferencedProjects.Length && - Array.forall2 (fun (n1,a) (n2,b) -> n1 = n2 && FSharpProjectOptions.AreSameForChecking(a,b)) options1.ReferencedProjects options2.ReferencedProjects && + Array.forall2 (fun (n1,a) (n2,b) -> + n1 = n2 && + FSharpProjectOptions.AreSameForChecking(a,b)) options1.ReferencedProjects options2.ReferencedProjects && options1.LoadTime = options2.LoadTime /// Compute the project directory. @@ -1885,16 +1888,16 @@ type FSharpCheckFileResults(filename: string, errors: FSharpErrorInfo[], scopeOp member info.HasFullTypeCheckInfo = details.IsSome /// Intellisense autocompletions - member info.GetDeclarationListInfo(parseResultsOpt, line, colAtEndOfNamesAndResidue, lineStr, qualifyingNames, partialName, getAllEntities, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = + member info.GetDeclarationListInfo(parseResultsOpt, line, lineStr, partialName, getAllEntities, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" let hasTextChangedSinceLastTypecheck = defaultArg hasTextChangedSinceLastTypecheck (fun _ -> false) reactorOp userOpName "GetDeclarations" FSharpDeclarationListInfo.Empty (fun ctok scope -> - scope.GetDeclarations(ctok, parseResultsOpt, line, lineStr, colAtEndOfNamesAndResidue, qualifyingNames, partialName, getAllEntities, hasTextChangedSinceLastTypecheck)) + scope.GetDeclarations(ctok, parseResultsOpt, line, lineStr, partialName, getAllEntities, hasTextChangedSinceLastTypecheck)) - member info.GetDeclarationListSymbols(parseResultsOpt, line, colAtEndOfNamesAndResidue, lineStr, qualifyingNames, partialName, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = + member info.GetDeclarationListSymbols(parseResultsOpt, line, lineStr, partialName, ?hasTextChangedSinceLastTypecheck, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" let hasTextChangedSinceLastTypecheck = defaultArg hasTextChangedSinceLastTypecheck (fun _ -> false) - reactorOp userOpName "GetDeclarationListSymbols" List.empty (fun ctok scope -> scope.GetDeclarationListSymbols(ctok, parseResultsOpt, line, lineStr, colAtEndOfNamesAndResidue, qualifyingNames, partialName, hasTextChangedSinceLastTypecheck)) + reactorOp userOpName "GetDeclarationListSymbols" List.empty (fun ctok scope -> scope.GetDeclarationListSymbols(ctok, parseResultsOpt, line, lineStr, partialName, hasTextChangedSinceLastTypecheck)) /// Resolve the names at the given location to give a data tip member info.GetStructuredToolTipText(line, colAtEndOfNames, lineStr, names, tokenTag, ?userOpName: string) = @@ -2012,6 +2015,12 @@ type FSharpCheckFileResults(filename: string, errors: FSharpErrorInfo[], scopeOp reactorOp userOpName "IsRelativeNameResolvable" true (fun ctok scope -> RequireCompilationThread ctok scope.IsRelativeNameResolvable(pos, plid, item)) + + member info.IsRelativeNameResolvableFromSymbol(pos: pos, plid: string list, symbol: FSharpSymbol, ?userOpName: string) = + let userOpName = defaultArg userOpName "Unknown" + reactorOp userOpName "IsRelativeNameResolvableFromSymbol" true (fun ctok scope -> + RequireCompilationThread ctok + scope.IsRelativeNameResolvableFromSymbol(pos, plid, symbol)) member info.ImplementationFiles = if not keepAssemblyContents then invalidOp "The 'keepAssemblyContents' flag must be set to true on the FSharpChecker in order to access the checked contents of assemblies" @@ -2043,11 +2052,11 @@ module Helpers = // Look for DLLs in the location of the service DLL first. let defaultFSharpBinariesDir = FSharpEnvironment.BinFolderOfDefaultFSharpCompiler(Some(typeof.Assembly.Location)).Value - + /// Determine whether two (fileName,options) keys are identical w.r.t. affect on checking - let AreSameForChecking2((fileName1: string, options1: FSharpProjectOptions), (fileName2, o2)) = + let AreSameForChecking2((fileName1: string, options1: FSharpProjectOptions), (fileName2, options2)) = (fileName1 = fileName2) - && FSharpProjectOptions.AreSameForChecking(options1,o2) + && FSharpProjectOptions.AreSameForChecking(options1,options2) /// Determine whether two (fileName,options) keys should be identical w.r.t. resource usage let AreSubsumable2((fileName1:string,o1:FSharpProjectOptions),(fileName2:string,o2:FSharpProjectOptions)) = @@ -2380,8 +2389,8 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC | Some res -> return res | None -> foregroundParseCount <- foregroundParseCount + 1 - let parseErrors, inputOpt, anyErrors = Parser.parseFile(source, filename, options, userOpName) - let res = FSharpParseFileResults(parseErrors, inputOpt, anyErrors, options.SourceFiles) + let parseErrors, parseTreeOpt, anyErrors = Parser.parseFile(source, filename, options, userOpName) + let res = FSharpParseFileResults(parseErrors, parseTreeOpt, anyErrors, options.SourceFiles) parseCacheLock.AcquireLock(fun ltok -> parseFileCache.Set(ltok, (filename, source, options), res)) return res } @@ -2395,9 +2404,9 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC match builderOpt with | None -> return FSharpParseFileResults(List.toArray creationErrors, None, true, [| |]) | Some builder -> - let! inputOpt,_,_,parseErrors = builder.GetParseResultsForFile (ctok, filename) + let! parseTreeOpt,_,_,parseErrors = builder.GetParseResultsForFile (ctok, filename) let errors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (builder.TcConfig.errorSeverityOptions, false, filename, parseErrors) |] - return FSharpParseFileResults(errors = errors, input = inputOpt, parseHadErrors = false, dependencyFiles = builder.AllDependenciesDeprecated) + return FSharpParseFileResults(errors = errors, input = parseTreeOpt, parseHadErrors = false, dependencyFiles = builder.AllDependenciesDeprecated) } ) @@ -2541,7 +2550,9 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC | _ -> Trace.TraceInformation("FCS: {0}.{1} ({2})", userOpName, "CheckFileInProject.CacheMiss", filename) let! tcPrior = execWithReactorAsync <| fun ctok -> builder.GetCheckResultsBeforeFileInProject (ctok, filename) - let! checkAnswer = bc.CheckOneFileImpl(parseResults, source, filename, options, textSnapshotInfo, fileVersion, builder, tcPrior, creationErrors, userOpName) + let parseTreeOpt = parseResults.ParseTree |> Option.map builder.DeduplicateParsedInputModuleNameInProject + let parseResultsAterDeDuplication = FSharpParseFileResults(parseResults.Errors, parseTreeOpt, parseResults.ParseHadErrors, parseResults.DependencyFiles) + let! checkAnswer = bc.CheckOneFileImpl(parseResultsAterDeDuplication, source, filename, options, textSnapshotInfo, fileVersion, builder, tcPrior, creationErrors, userOpName) return checkAnswer finally bc.ImplicitlyStartCheckProjectInBackground(options, userOpName) @@ -2574,9 +2585,9 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC // Do the parsing. let parsingOptions = FSharpParsingOptions.FromTcConfig(builder.TcConfig, Array.ofList (builder.SourceFiles)) - let parseErrors, inputOpt, anyErrors = Parser.parseFile (source, filename, parsingOptions, userOpName) - - let parseResults = FSharpParseFileResults(parseErrors, inputOpt, anyErrors, builder.AllDependenciesDeprecated) + let parseErrors, parseTreeOpt, anyErrors = Parser.parseFile (source, filename, parsingOptions, userOpName) + let parseTreeOpt = parseTreeOpt |> Option.map builder.DeduplicateParsedInputModuleNameInProject + let parseResults = FSharpParseFileResults(parseErrors, parseTreeOpt, anyErrors, builder.AllDependenciesDeprecated) let! checkResults = bc.CheckOneFileImpl(parseResults, source, filename, options, textSnapshotInfo, fileVersion, builder, tcPrior, creationErrors, userOpName) return parseResults, checkResults finally @@ -2595,12 +2606,12 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC let typedResults = MakeCheckFileResultsEmpty(filename, creationErrors) return (parseResults, typedResults) | Some builder -> - let! (inputOpt, _, _, untypedErrors) = builder.GetParseResultsForFile (ctok, filename) + let! (parseTreeOpt, _, _, untypedErrors) = builder.GetParseResultsForFile (ctok, filename) let! tcProj = builder.GetCheckResultsAfterFileInProject (ctok, filename) let errorOptions = builder.TcConfig.errorSeverityOptions let untypedErrors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (errorOptions, false, filename, untypedErrors) |] let tcErrors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (errorOptions, false, filename, tcProj.Errors) |] - let parseResults = FSharpParseFileResults(errors = untypedErrors, input = inputOpt, parseHadErrors = false, dependencyFiles = builder.AllDependenciesDeprecated) + let parseResults = FSharpParseFileResults(errors = untypedErrors, input = parseTreeOpt, parseHadErrors = false, dependencyFiles = builder.AllDependenciesDeprecated) let loadClosure = scriptClosureCacheLock.AcquireLock (fun ltok -> scriptClosureCache.TryGet (ltok, options) ) let scope = TypeCheckInfo(tcProj.TcConfig, tcProj.TcGlobals, tcProj.TcState.PartialAssemblySignature, tcProj.TcState.Ccu, tcProj.TcImports, tcProj.TcEnvAtEnd.AccessRights, @@ -2711,7 +2722,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC member bc.InvalidateConfiguration(options : FSharpProjectOptions, startBackgroundCompileIfAlreadySeen, userOpName) = let startBackgroundCompileIfAlreadySeen = defaultArg startBackgroundCompileIfAlreadySeen implicitlyStartBackgroundWork // This operation can't currently be cancelled nor awaited - reactor.EnqueueOp(userOpName, "InvalidateConfiguration", options.ProjectFileName, fun ctok -> + reactor.EnqueueOp(userOpName, "InvalidateConfiguration: Stamp(" + (options.Stamp |> Option.defaultValue 0L).ToString() + ")", options.ProjectFileName, fun ctok -> // If there was a similar entry then re-establish an empty builder . This is a somewhat arbitrary choice - it // will have the effect of releasing memory associated with the previous builder, but costs some time. if incrementalBuildersCache.ContainsSimilarKey (ctok, options) then @@ -3136,9 +3147,9 @@ type FsiInteractiveChecker(legacyReferenceResolver, reactorOps: IReactorOperatio let filename = Path.Combine(tcConfig.implicitIncludeDir, "stdin.fsx") // Note: projectSourceFiles is only used to compute isLastCompiland, and is ignored if Build.IsScript(mainInputFileName) is true (which it is in this case). let parsingOptions = FSharpParsingOptions.FromTcConfig(tcConfig, [| filename |]) - let parseErrors, inputOpt, anyErrors = Parser.parseFile (source, filename, parsingOptions, userOpName) + let parseErrors, parseTreeOpt, anyErrors = Parser.parseFile (source, filename, parsingOptions, userOpName) let dependencyFiles = [| |] // interactions have no dependencies - let parseResults = FSharpParseFileResults(parseErrors, inputOpt, parseHadErrors = anyErrors, dependencyFiles = dependencyFiles) + let parseResults = FSharpParseFileResults(parseErrors, parseTreeOpt, parseHadErrors = anyErrors, dependencyFiles = dependencyFiles) let backgroundDiagnostics = [] diff --git a/src/fsharp/vs/service.fsi b/src/fsharp/vs/service.fsi index 986b9a0e4c8..e6471120f5f 100755 --- a/src/fsharp/vs/service.fsi +++ b/src/fsharp/vs/service.fsi @@ -132,21 +132,23 @@ type internal FSharpCheckFileResults = /// 'record field' locations and r.h.s. of 'range' operator a..b /// /// The line number where the completion is happening - /// The column number at the end of the 'names' text - /// The long identifier to the left of the '.' - /// The residue of a partial long identifier to the right of the '.' - /// The residue of a partial long identifier to the right of the '.' + /// + /// Partial long name. QuickParse.GetPartialLongNameEx can be used to get it. + /// /// /// The text of the line where the completion is happening. This is only used to make a couple /// of adhoc corrections to completion accuracy (e.g. checking for "..") /// + /// + /// Function that returns all symbols from current and referenced assemblies. + /// /// /// If text has been used from a captured name resolution from the typecheck, then /// callback to the client to check if the text has changed. If it has, then give up /// and assume that we're going to repeat the operation later on. /// /// An optional string used for tracing compiler operations associated with this request. - member GetDeclarationListInfo : ParsedFileResultsOpt:FSharpParseFileResults option * line: int * colAtEndOfPartialName: int * lineText:string * qualifyingNames: string list * partialName: string * getAllSymbols: (unit -> AssemblySymbol list) * ?hasTextChangedSinceLastTypecheck: (obj * range -> bool) * ?userOpName: string -> Async + member GetDeclarationListInfo : ParsedFileResultsOpt:FSharpParseFileResults option * line: int * lineText:string * partialName: PartialLongName * getAllSymbols: (unit -> AssemblySymbol list) * ?hasTextChangedSinceLastTypecheck: (obj * range -> bool) * ?userOpName: string -> Async /// Get the items for a declaration list in FSharpSymbol format /// @@ -156,21 +158,23 @@ type internal FSharpCheckFileResults = /// 'record field' locations and r.h.s. of 'range' operator a..b /// /// The line number where the completion is happening - /// The column number at the end of the 'names' text - /// The long identifier to the left of the '.' - /// The residue of a partial long identifier to the right of the '.' - /// The residue of a partial long identifier to the right of the '.' + /// + /// Partial long name. QuickParse.GetPartialLongNameEx can be used to get it. + /// /// /// The text of the line where the completion is happening. This is only used to make a couple /// of adhoc corrections to completion accuracy (e.g. checking for "..") /// + /// + /// Function that returns all symbols from current and referenced assemblies. + /// /// /// If text has been used from a captured name resolution from the typecheck, then /// callback to the client to check if the text has changed. If it has, then give up /// and assume that we're going to repeat the operation later on. /// /// An optional string used for tracing compiler operations associated with this request. - member GetDeclarationListSymbols : ParsedFileResultsOpt:FSharpParseFileResults option * line: int * colAtEndOfPartialName: int * lineText:string * qualifyingNames: string list * partialName: string * ?hasTextChangedSinceLastTypecheck: (obj * range -> bool) * ?userOpName: string -> Async + member GetDeclarationListSymbols : ParsedFileResultsOpt:FSharpParseFileResults option * line: int * lineText:string * partialName: PartialLongName * ?hasTextChangedSinceLastTypecheck: (obj * range -> bool) * ?userOpName: string -> Async /// Compute a formatted tooltip for the given location @@ -200,7 +204,7 @@ type internal FSharpCheckFileResults = /// The text of the line where the information is being requested. /// The identifiers at the location where the information is being requested. /// An optional string used for tracing compiler operations associated with this request. - member GetF1Keyword : line:int * colAtEndOfNames:int * lineText:string * names:string list * ?userOpName: string -> Async + member GetF1Keyword : line:int * colAtEndOfNames:int * lineText:string * names:string list * ?userOpName: string -> Async /// Compute a set of method overloads to show in a dialog relevant to the given code location. @@ -210,7 +214,7 @@ type internal FSharpCheckFileResults = /// The text of the line where the information is being requested. /// The identifiers at the location where the information is being requested. /// An optional string used for tracing compiler operations associated with this request. - member GetMethods : line:int * colAtEndOfNames:int * lineText:string * names:string list option * ?userOpName: string -> Async + member GetMethods : line:int * colAtEndOfNames:int * lineText:string * names:string list option * ?userOpName: string -> Async /// Compute a set of method overloads to show in a dialog relevant to the given code location. The resulting method overloads are returned as symbols. /// The line number where the information is being requested. @@ -262,6 +266,10 @@ type internal FSharpCheckFileResults = /// An optional string used for tracing compiler operations associated with this request. member internal IsRelativeNameResolvable: cursorPos : pos * plid : string list * item: Item * ?userOpName: string -> Async + /// Determines if a long ident is resolvable at a specific point. + /// An optional string used for tracing compiler operations associated with this request. + member IsRelativeNameResolvableFromSymbol: cursorPos : pos * plid : string list * symbol: FSharpSymbol * ?userOpName: string -> Async + /// Represents complete typechecked implementation files, including thier typechecked signatures if any. member ImplementationFiles: FSharpImplementationFileContents list option diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index e61401fa120..513f95f7859 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -439,6 +439,28 @@ module TypedTest = begin test "check Mutate 1" (<@ let mutable x = 0 in x <- 1 @> |> (function Let(v,Int32 0, VarSet(v2,Int32 1)) when v = v2 -> true | _ -> false)) let q = <@ let mutable x = 0 in x <- 1 @> + + let rec getMethod (e : Expr) = + match e with + | Call(None, mi, _) -> mi + | Let(_,_,m) -> getMethod m + | Lambdas(_, e) -> getMethod e + | _ -> failwithf "not a lambda: %A" e + + let increment (r : byref) = r <- r + 1 + let incrementMeth = getMethod <@ let mutable a = 10 in increment(&a) @> + + let rec rebuild (e : Expr) = + match e with + | ExprShape.ShapeLambda(v,b) -> Expr.Lambda(v, rebuild b) + | ExprShape.ShapeVar(v) -> Expr.Var v + | ExprShape.ShapeCombination(o, args) -> ExprShape.RebuildShapeCombination(o, args |> List.map rebuild) + + test "check AddressOf in call" (try let v = Var("a", typeof, true) in Expr.Let(v, Expr.Value 10, Expr.Call(incrementMeth, [Expr.AddressOf(Expr.Var v)])) |> ignore; true with _ -> false) + test "check AddressOf rebuild" (try rebuild <@ let mutable a = 10 in increment(&a) @> |> ignore; true with _ -> false) + test "check AddressOf argument" (<@ let mutable a = 10 in increment(&a) @> |> function Let(_, _, Call(None, _, [AddressOf(_)])) -> true | _ -> false) + test "check AddressOf type" (<@ let mutable a = 10 in increment(&a) @> |> function Let(_, _, Call(None, _, [AddressOf(_) as e])) -> (try e.Type = typeof.MakeByRefType() with _ -> false) | _ -> false) + // Test basic expression splicing let f8383 (x:int) (y:string) = 0 diff --git a/tests/fsharp/test-framework.fs b/tests/fsharp/test-framework.fs index 4f16991968a..6b9a795ca68 100644 --- a/tests/fsharp/test-framework.fs +++ b/tests/fsharp/test-framework.fs @@ -172,8 +172,8 @@ let config configurationName envVars = let SCRIPT_ROOT = __SOURCE_DIRECTORY__ let FSCBinPath = SCRIPT_ROOT ++ ".." ++ ".." ++ configurationName ++ "net40" ++ "bin" let csc_flags = "/nologo" - let fsc_flags = "-r:System.Core.dll --nowarn:20 --define:COMPILED" - let fsi_flags = "-r:System.Core.dll --nowarn:20 --define:INTERACTIVE --maxerrors:1 --abortonerror" + let fsc_flags = "-r:System.Core.dll --nowarn:20 --define:COMPILED" + let fsi_flags = "-r:System.Core.dll --nowarn:20 --define:INTERACTIVE --maxerrors:1 --abortonerror" let CORDIR, CORSDK = WindowsPlatform.clrPaths envVars let Is64BitOperatingSystem = WindowsPlatform.Is64BitOperatingSystem envVars let CSC = requireFile (CORDIR ++ "csc.exe") diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index 8f8d0cd3dc1..81f282abdda 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -376,7 +376,7 @@ module CoreTests = // Same without the reference to lib.dll - testing an incomplete reference set, but only compiling a subset of the code - fsc cfg "%s --noframework --define:NO_LIB_REFERENCE -r:lib3.dll -r:lib2.dll -o:test.exe -g" cfg.fsc_flags ["test.fsx"] + fsc cfg "%s -r:System.Runtime.dll --noframework --define:NO_LIB_REFERENCE -r:lib3.dll -r:lib2.dll -o:test.exe -g" cfg.fsc_flags ["test.fsx"] peverify cfg "test.exe" diff --git a/tests/fsharp/typecheck/sigs/neg20.bsl b/tests/fsharp/typecheck/sigs/neg20.bsl index bd7559f382a..fc46431486b 100644 --- a/tests/fsharp/typecheck/sigs/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/neg20.bsl @@ -349,9 +349,9 @@ neg20.fs(319,8,319,17): typecheck error FS3132: This type definition may not hav neg20.fs(322,8,322,18): typecheck error FS3132: This type definition may not have the 'CLIMutable' attribute. Only record types may have this attribute. -neg20.fs(335,11,335,24): typecheck error FS0041: A unique overload for method 'String' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: System.String(value: char []) : unit, System.String(value: nativeptr) : unit, System.String(value: nativeptr) : unit +neg20.fs(335,11,335,24): typecheck error FS0041: A unique overload for method 'String' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: System.String(value: char []) : System.String, System.String(value: nativeptr) : System.String, System.String(value: nativeptr) : System.String -neg20.fs(336,11,336,22): typecheck error FS0041: A unique overload for method 'Guid' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: System.Guid(b: byte []) : unit, System.Guid(g: string) : unit +neg20.fs(336,11,336,22): typecheck error FS0041: A unique overload for method 'Guid' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: System.Guid(b: byte []) : System.Guid, System.Guid(g: string) : System.Guid neg20.fs(355,19,355,38): typecheck error FS1124: Multiple types exist called 'OverloadedClassName', taking different numbers of generic parameters. Provide a type instantiation to disambiguate the type resolution, e.g. 'OverloadedClassName<_>'. diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/dumpAllCommandLineOptions/dummy.fsx b/tests/fsharpqa/Source/CompilerOptions/fsc/dumpAllCommandLineOptions/dummy.fsx index aa84cfe70f6..e16db4e42e3 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/dumpAllCommandLineOptions/dummy.fsx +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/dumpAllCommandLineOptions/dummy.fsx @@ -95,6 +95,7 @@ //section='- ADVANCED - ' ! option=readline kind=OptionSwitch //section='- ADVANCED - ' ! option=quotations-debug kind=OptionSwitch //section='- ADVANCED - ' ! option=shadowcopyreferences kind=OptionSwitch +//section='- ADVANCED - ' ! option=simpleresolution kind=OptionUnit // These are for FSC.EXE ONLY: @@ -121,7 +122,6 @@ //section='- ADVANCED - ' ! option=standalone kind=OptionUnit //section='- ADVANCED - ' ! option=staticlink kind=OptionString //section='- ADVANCED - ' ! option=pdb kind=OptionString -//section='- ADVANCED - ' ! option=simpleresolution kind=OptionUnit //section='NoSection ' ! option=generatehtml kind=OptionUnit //section='NoSection ' ! option=htmloutputdir kind=OptionString //section='NoSection ' ! option=htmlcss kind=OptionString diff --git a/tests/fsharpqa/Source/Warnings/DontSuggestIntentionallyUnusedVariables.fs b/tests/fsharpqa/Source/Warnings/DontSuggestIntentionallyUnusedVariables.fs new file mode 100644 index 00000000000..602d459d518 --- /dev/null +++ b/tests/fsharpqa/Source/Warnings/DontSuggestIntentionallyUnusedVariables.fs @@ -0,0 +1,8 @@ +//The value or constructor 'xyz' is not defined. +//Maybe you want one of the following: +//\s+xy +//\s+_xyz + +let hober xy _xyz = xyz + +exit 0 diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 8f88c1c2dac..5d3db7f38e7 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -78,3 +78,4 @@ SOURCE=WarnIfPossiblePropertySetter.fs SOURCE=DoCannotHaveVisibilityDeclarations.fs SOURCE=ModuleAbbreviationsArePrivate.fs + SOURCE=DontSuggestIntentionallyUnusedVariables.fs SCFLAGS="--vserrors" # DontSuggestIntentionallyUnusedVariables.fs diff --git a/tests/fsharpqa/Source/run.pl b/tests/fsharpqa/Source/run.pl index faabcdbc450..f168f6415ab 100644 --- a/tests/fsharpqa/Source/run.pl +++ b/tests/fsharpqa/Source/run.pl @@ -646,7 +646,7 @@ () push @dontmatch, $2 if $2; } # test full xml form - elsif (m@//\s*\s*(.*?)\s*<(/Expect|/)\w*>@i) { + elsif (m@//\s*\s*(.*?)\s*<(/Expect|/)\w*>@i) { push @dontmatch, $2 if $2; } else { next; diff --git a/tests/service/EditorTests.fs b/tests/service/EditorTests.fs index 8b70eeda1bc..e935737511e 100644 --- a/tests/service/EditorTests.fs +++ b/tests/service/EditorTests.fs @@ -86,7 +86,8 @@ let ``Intro test`` () = let tip = typeCheckResults.GetToolTipText(4, 7, inputLines.[1], ["foo"], identToken) |> Async.RunSynchronously // (sprintf "%A" tip).Replace("\n","") |> shouldEqual """FSharpToolTipText [Single ("val foo : unit -> unitFull name: Test.foo",None)]""" // Get declarations (autocomplete) for a location - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 7, 23, inputLines.[6], [], "msg", (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let partialName = { QualifyingIdents = []; PartialIdent = "msg"; EndColumn = 22; LastDotPos = None } + let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 7, inputLines.[6], partialName, (fun _ -> []), fun _ -> false)|> Async.RunSynchronously CollectionAssert.AreEquivalent(stringMethods,[ for item in decls.Items -> item.Name ]) // Get overloads of the String.Concat method let methods = typeCheckResults.GetMethods(5, 27, inputLines.[4], Some ["String"; "Concat"]) |> Async.RunSynchronously @@ -285,7 +286,7 @@ let ``Expression typing test`` () = // gives the results for the string type. // for col in 42..43 do - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 2, col, inputLines.[1], [], "", (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 2, inputLines.[1], PartialLongName.Empty(col), (fun _ -> []), fun _ -> false)|> Async.RunSynchronously let autoCompleteSet = set [ for item in decls.Items -> item.Name ] autoCompleteSet |> shouldEqual (set stringMethods) @@ -306,7 +307,7 @@ type Test() = let file = "/home/user/Test.fsx" let parseResult, typeCheckResults = parseAndCheckScript(file, input) - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, 21, inputLines.[3], [], "", (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(20), (fun _ -> []), fun _ -> false)|> Async.RunSynchronously let item = decls.Items |> Array.tryFind (fun d -> d.Name = "abc") decls.Items |> Seq.exists (fun d -> d.Name = "abc") |> shouldEqual true @@ -323,7 +324,7 @@ type Test() = let file = "/home/user/Test.fsx" let parseResult, typeCheckResults = parseAndCheckScript(file, input) - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, 22, inputLines.[3], [], "", (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(21), (fun _ -> []), fun _ -> false)|> Async.RunSynchronously let item = decls.Items |> Array.tryFind (fun d -> d.Name = "abc") decls.Items |> Seq.exists (fun d -> d.Name = "abc") |> shouldEqual true @@ -340,7 +341,7 @@ type Test() = let file = "/home/user/Test.fsx" let parseResult, typeCheckResults = parseAndCheckScript(file, input) - let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, 15, inputLines.[3], [], "", (fun _ -> []), fun _ -> false)|> Async.RunSynchronously + let decls = typeCheckResults.GetDeclarationListInfo(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(14), (fun _ -> []), fun _ -> false)|> Async.RunSynchronously decls.Items |> Seq.exists (fun d -> d.Name = "abc") |> shouldEqual true [] @@ -356,7 +357,7 @@ type Test() = let file = "/home/user/Test.fsx" let parseResult, typeCheckResults = parseAndCheckScript(file, input) - let decls = typeCheckResults.GetDeclarationListSymbols(Some parseResult, 4, 21, inputLines.[3], [], "", fun _ -> false)|> Async.RunSynchronously + let decls = typeCheckResults.GetDeclarationListSymbols(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(20), fun _ -> false)|> Async.RunSynchronously //decls |> List.map (fun d -> d.Head.Symbol.DisplayName) |> printfn "---> decls = %A" decls |> Seq.exists (fun d -> d.Head.Symbol.DisplayName = "abc") |> shouldEqual true @@ -373,7 +374,7 @@ type Test() = let file = "/home/user/Test.fsx" let parseResult, typeCheckResults = parseAndCheckScript(file, input) - let decls = typeCheckResults.GetDeclarationListSymbols(Some parseResult, 4, 22, inputLines.[3], [], "", fun _ -> false)|> Async.RunSynchronously + let decls = typeCheckResults.GetDeclarationListSymbols(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(21), fun _ -> false)|> Async.RunSynchronously //decls |> List.map (fun d -> d.Head.Symbol.DisplayName) |> printfn "---> decls = %A" decls |> Seq.exists (fun d -> d.Head.Symbol.DisplayName = "abc") |> shouldEqual true @@ -390,7 +391,7 @@ type Test() = let file = "/home/user/Test.fsx" let parseResult, typeCheckResults = parseAndCheckScript(file, input) - let decls = typeCheckResults.GetDeclarationListSymbols(Some parseResult, 4, 15, inputLines.[3], [], "", fun _ -> false)|> Async.RunSynchronously + let decls = typeCheckResults.GetDeclarationListSymbols(Some parseResult, 4, inputLines.[3], PartialLongName.Empty(14), fun _ -> false)|> Async.RunSynchronously //decls |> List.map (fun d -> d.Head.Symbol.DisplayName) |> printfn "---> decls = %A" decls |> Seq.exists (fun d -> d.Head.Symbol.DisplayName = "abc") |> shouldEqual true diff --git a/vsintegration/Utils/LanguageServiceProfiling/Program.fs b/vsintegration/Utils/LanguageServiceProfiling/Program.fs index bc785b787cd..5413e8b9094 100644 --- a/vsintegration/Utils/LanguageServiceProfiling/Program.fs +++ b/vsintegration/Utils/LanguageServiceProfiling/Program.fs @@ -164,10 +164,11 @@ let main argv = fileResults.GetDeclarationListInfo( Some parseResult, completion.Position.Line, - completion.Position.Column, getLine (completion.Position.Line), - completion.QualifyingNames, - completion.PartialName, + { QualifyingIdents = completion.QualifyingNames + PartialIdent = completion.PartialName + EndColumn = completion.Position.Column - 1 + LastDotPos = None }, fun() -> []) for i in listInfo.Items do diff --git a/vsintegration/src/FSharp.Editor/Classification/ColorizationService.fs b/vsintegration/src/FSharp.Editor/Classification/ColorizationService.fs index b60ee3b9bcc..c3b199d4be3 100644 --- a/vsintegration/src/FSharp.Editor/Classification/ColorizationService.fs +++ b/vsintegration/src/FSharp.Editor/Classification/ColorizationService.fs @@ -40,7 +40,7 @@ type internal FSharpColorizationService asyncMaybe { do Trace.TraceInformation("{0:n3} (start) SemanticColorization", DateTime.Now.TimeOfDay.TotalSeconds) do! Async.Sleep DefaultTuning.SemanticColorizationInitialDelay |> liftAsync // be less intrusive, give other work priority most of the time - let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document) + let! _, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document) let! sourceText = document.GetTextAsync(cancellationToken) let! _, _, checkResults = checkerProvider.Checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, allowStaleResults = false, userOpName=userOpName) // it's crucial to not return duplicated or overlapping `ClassifiedSpan`s because Find Usages service crashes. diff --git a/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs b/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs index 99bcd091c91..b8f8ac4c4c9 100644 --- a/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs +++ b/vsintegration/src/FSharp.Editor/Commands/HelpContextService.fs @@ -10,6 +10,7 @@ open Microsoft.CodeAnalysis.Classification open Microsoft.VisualStudio.FSharp.LanguageService open Microsoft.VisualStudio.LanguageServices.Implementation.F1Help open Microsoft.CodeAnalysis.Host.Mef +open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.SourceCodeServices diff --git a/vsintegration/src/FSharp.Editor/Common/AssemblyInfo.fs b/vsintegration/src/FSharp.Editor/Common/AssemblyInfo.fs index 27ec6cf2ad3..b876bf86820 100644 --- a/vsintegration/src/FSharp.Editor/Common/AssemblyInfo.fs +++ b/vsintegration/src/FSharp.Editor/Common/AssemblyInfo.fs @@ -4,10 +4,6 @@ namespace Microsoft.VisualStudio.FSharp.Editor open Microsoft.VisualStudio.Shell -[] -[] -[] - [] [] [] diff --git a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs index e30c0322b47..b3c7448a0c9 100644 --- a/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/Completion/CompletionProvider.fs @@ -55,9 +55,23 @@ type internal FSharpCompletionProvider let xmlMemberIndexService = serviceProvider.GetService(typeof) :?> IVsXMLMemberIndexService let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder(xmlMemberIndexService, serviceProvider.DTE) - + static let noCommitOnSpaceRules = - CompletionItemRules.Default.WithCommitCharacterRule(CharacterSetModificationRule.Create(CharacterSetModificationKind.Remove, ' ', '=', ',', '.', '<', '>', '(', ')', '!', ':')) + // These are important. They make sure we don't _commit_ autocompletion when people don't expect them to. Some examples: + // + // * type Foo() = + // member val a = 12 with get, <<---- Don't commit autocomplete! + // + // * type MyRecord = { name: <<---- Don't commit autocomplete! + // + // * type My< <<---- Don't commit autocomplete! + // + // * let myClassInstance = MyClass(Date= <<---- Don't commit autocomplete! + // + // * let xs = [1..10] <<---- Don't commit autocomplete! (same for arrays) + let noCommitChars = [|' '; '='; ','; '.'; '<'; '>'; '('; ')'; '!'; ':'; '['; ']'; '|'|].ToImmutableArray() + + CompletionItemRules.Default.WithCommitCharacterRule(CharacterSetModificationRule.Create(CharacterSetModificationKind.Remove, noCommitChars)) static let getRules() = if Settings.IntelliSense.ShowAfterCharIsTyped then noCommitOnSpaceRules else CompletionItemRules.Default @@ -100,14 +114,14 @@ type internal FSharpCompletionProvider let caretLine = textLines.GetLineFromPosition(caretPosition) let fcsCaretLineNumber = Line.fromZ caretLinePos.Line // Roslyn line numbers are zero-based, FSharp.Compiler.Service line numbers are 1-based let caretLineColumn = caretLinePos.Character - let qualifyingNames, partialName = QuickParse.GetPartialLongNameEx(caretLine.ToString(), caretLineColumn - 1) + let partialName = QuickParse.GetPartialLongNameEx(caretLine.ToString(), caretLineColumn - 1) let getAllSymbols() = - getAllSymbols() |> List.filter (fun entity -> entity.FullName.Contains "." && not (PrettyNaming.IsOperatorName entity.Symbol.DisplayName)) + getAllSymbols() + |> List.filter (fun entity -> entity.FullName.Contains "." && not (PrettyNaming.IsOperatorName entity.Symbol.DisplayName)) - let! declarations = - checkFileResults.GetDeclarationListInfo(Some(parseResults), fcsCaretLineNumber, caretLineColumn, caretLine.ToString(), qualifyingNames, partialName, getAllSymbols, userOpName=userOpName) |> liftAsync - + let! declarations = checkFileResults.GetDeclarationListInfo(Some(parseResults), fcsCaretLineNumber, caretLine.ToString(), + partialName, getAllSymbols, userOpName=userOpName) |> liftAsync let results = List() let getKindPriority = function @@ -186,7 +200,7 @@ type internal FSharpCompletionProvider declarationItemsCache.Add(completionItem.DisplayText, declItem) results.Add(completionItem)) - if results.Count > 0 && not declarations.IsForType && not declarations.IsError && List.isEmpty qualifyingNames then + if results.Count > 0 && not declarations.IsForType && not declarations.IsError && List.isEmpty partialName.QualifyingIdents then let lineStr = textLines.[caretLinePos.Line].ToString() match UntypedParseImpl.TryGetCompletionContext(Pos.fromZ caretLinePos.Line caretLinePos.Character, Some parseResults, lineStr) with | None -> results.AddRange(keywordCompletionItems) diff --git a/vsintegration/src/FSharp.Editor/Debugging/LanguageDebugInfoService.fs b/vsintegration/src/FSharp.Editor/Debugging/LanguageDebugInfoService.fs index 02ccfc1e6e8..432b0431052 100644 --- a/vsintegration/src/FSharp.Editor/Debugging/LanguageDebugInfoService.fs +++ b/vsintegration/src/FSharp.Editor/Debugging/LanguageDebugInfoService.fs @@ -14,7 +14,7 @@ open Microsoft.CodeAnalysis.Editor.Implementation.Debugging open Microsoft.CodeAnalysis.Host.Mef open Microsoft.CodeAnalysis.Text -open Microsoft.VisualStudio.FSharp.LanguageService +open Microsoft.FSharp.Compiler [] [, FSharpConstants.FSharpLanguageName)>] diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs index ffcf5c6ef83..5b8b1744aeb 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/DocumentDiagnosticAnalyzer.fs @@ -122,7 +122,7 @@ type internal FSharpDocumentDiagnosticAnalyzer() = override this.AnalyzeSemanticsAsync(document: Document, cancellationToken: CancellationToken): Task> = let projectInfoManager = getProjectInfoManager document asyncMaybe { - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document) + let! parsingOptions, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document) let! sourceText = document.GetTextAsync(cancellationToken) let! textVersion = document.GetTextVersionAsync(cancellationToken) return! diff --git a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs index b0b25ca6ead..ace07bf57f2 100644 --- a/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs @@ -69,11 +69,11 @@ type internal SimplifyNameDiagnosticAnalyzer() = |> Array.Parallel.map (fun symbolUse -> let lineStr = sourceText.Lines.[Line.toZ symbolUse.RangeAlternate.StartLine].ToString() // for `System.DateTime.Now` it returns ([|"System"; "DateTime"|], "Now") - let plid, name = QuickParse.GetPartialLongNameEx(lineStr, symbolUse.RangeAlternate.EndColumn - 1) + let partialName = QuickParse.GetPartialLongNameEx(lineStr, symbolUse.RangeAlternate.EndColumn - 1) // `symbolUse.RangeAlternate.Start` does not point to the start of plid, it points to start of `name`, // so we have to calculate plid's start ourselves. - let plidStartCol = symbolUse.RangeAlternate.EndColumn - name.Length - (getPlidLength plid) - symbolUse, plid, plidStartCol, name) + let plidStartCol = symbolUse.RangeAlternate.EndColumn - partialName.PartialIdent.Length - (getPlidLength partialName.QualifyingIdents) + symbolUse, partialName.QualifyingIdents, plidStartCol, partialName.PartialIdent) |> Array.filter (fun (_, plid, _, name) -> name <> "" && not (List.isEmpty plid)) |> Array.groupBy (fun (symbolUse, _, plidStartCol, _) -> symbolUse.RangeAlternate.StartLine, plidStartCol) |> Array.map (fun (_, xs) -> xs |> Array.maxBy (fun (symbolUse, _, _, _) -> symbolUse.RangeAlternate.EndColumn)) diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 25c8ea30208..5bb2b7d613c 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -28,6 +28,11 @@ true true + + + + + true diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs index 238325be41b..8055202d252 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs @@ -18,7 +18,7 @@ open System.Threading open Microsoft.FSharp.Compiler.CompileOps open Microsoft.FSharp.Compiler.SourceCodeServices -open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library +open Microsoft.VisualStudio.FSharp.LanguageService.SiteProvider open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.Diagnostics @@ -61,21 +61,21 @@ type internal FSharpCheckerProvider // When the F# background builder refreshes the background semantic build context for a file, // we request Roslyn to reanalyze that individual file. checker.BeforeBackgroundFileCheck.Add(fun (fileName, extraProjectInfo) -> - async { - try - match extraProjectInfo with - | Some (:? Workspace as workspace) -> - let solution = workspace.CurrentSolution - let documentIds = solution.GetDocumentIdsWithFilePath(fileName) - if not documentIds.IsEmpty then - let docuentIdsFiltered = documentIds |> Seq.filter workspace.IsDocumentOpen |> Seq.toArray - for documentId in docuentIdsFiltered do - Trace.TraceInformation("{0:n3} Requesting Roslyn reanalysis of {1}", DateTime.Now.TimeOfDay.TotalSeconds, documentId) - if docuentIdsFiltered.Length > 0 then - analyzerService.Reanalyze(workspace,documentIds=docuentIdsFiltered) - | _ -> () - with ex -> - Assert.Exception(ex) + async { + try + match extraProjectInfo with + | Some (:? Workspace as workspace) -> + let solution = workspace.CurrentSolution + let documentIds = solution.GetDocumentIdsWithFilePath(fileName) + if not documentIds.IsEmpty then + let documentIdsFiltered = documentIds |> Seq.filter workspace.IsDocumentOpen |> Seq.toArray + for documentId in documentIdsFiltered do + Trace.TraceInformation("{0:n3} Requesting Roslyn reanalysis of {1}", DateTime.Now.TimeOfDay.TotalSeconds, documentId) + if documentIdsFiltered.Length > 0 then + analyzerService.Reanalyze(workspace,documentIds=documentIdsFiltered) + | _ -> () + with ex -> + Assert.Exception(ex) } |> Async.StartImmediate ) checker @@ -83,9 +83,6 @@ type internal FSharpCheckerProvider member this.Checker = checker.Value -/// A value and a function to recompute/refresh the value. The function is passed a flag indicating if a refresh is happening. -type Refreshable<'T> = 'T * (bool -> 'T) - /// Exposes FCS FSharpProjectOptions information management as MEF component. // // This service allows analyzers to get an appropriate FSharpProjectOptions value for a project or single file. @@ -101,49 +98,31 @@ type internal FSharpProjectOptionsManager ) = // A table of information about projects, excluding single-file projects. - let projectTable = ConcurrentDictionary>() + let projectOptionsTable = FSharpProjectOptionsTable() // A table of information about single-file projects. Currently we only need the load time of each such file, plus // the original options for editing let singleFileProjectTable = ConcurrentDictionary() - // Accumulate sources and references for each project file - let projectInfo = new ConcurrentDictionary() - - let projectDisplayNameOf projectFileName = - if String.IsNullOrWhiteSpace projectFileName then projectFileName - else Path.GetFileNameWithoutExtension projectFileName - - let tryGetOrCreateProjectId (projectFileName: string) = + let tryGetOrCreateProjectId (projectFileName:string) = let projectDisplayName = projectDisplayNameOf projectFileName Some (workspace.ProjectTracker.GetOrCreateProjectIdForPath(projectFileName, projectDisplayName)) + /// Retrieve the projectOptionsTable + member __.FSharpOptions = projectOptionsTable + /// Clear a project from the project table - member this.ClearInfoForProject(projectId: ProjectId) = - projectTable.TryRemove(projectId) |> ignore - this.RefreshInfoForProjectsThatReferenceThisProject(projectId) + member this.ClearInfoForProject(projectId:ProjectId) = projectOptionsTable.ClearInfoForProject(projectId) member this.ClearInfoForSingleFileProject(projectId) = singleFileProjectTable.TryRemove(projectId) |> ignore - member this.RefreshInfoForProjectsThatReferenceThisProject(projectId: ProjectId) = - // Search the projectTable for things to refresh - for KeyValue(otherProjectId, ((referencedProjectIds, _parsingOptions, _options), refresh)) in projectTable.ToArray() do - for referencedProjectId in referencedProjectIds do - if referencedProjectId = projectId then - projectTable.[otherProjectId] <- (refresh true, refresh) - - member this.AddOrUpdateProject(projectId, refresh) = - projectTable.[projectId] <- (refresh false, refresh) - this.RefreshInfoForProjectsThatReferenceThisProject(projectId) - - member this.AddOrUpdateSingleFileProject(projectId, data) = - singleFileProjectTable.[projectId] <- data + member this.AddOrUpdateSingleFileProject(projectId, data) = singleFileProjectTable.[projectId] <- data /// Get the exact options for a single-file script member this.ComputeSingleFileOptions (tryGetOrCreateProjectId, fileName, loadTime, fileContents, workspace: Workspace) = async { let extraProjectInfo = Some(box workspace) - let tryGetOptionsForReferencedProject f = f |> tryGetOrCreateProjectId |> Option.bind this.TryGetOptionsForProject |> Option.map snd + let tryGetOptionsForReferencedProject f = f |> tryGetOrCreateProjectId |> Option.bind this.TryGetOptionsForProject |> Option.map(fun (_, _, projectOptions) -> projectOptions) if SourceFile.MustBeSingleFileProject(fileName) then // NOTE: we don't use a unique stamp for single files, instead comparing options structurally. // This is because we repeatedly recompute the options. @@ -153,48 +132,44 @@ type internal FSharpProjectOptionsManager // compiled and #r will refer to files on disk let referencedProjectFileNames = [| |] let site = ProjectSitesAndFiles.CreateProjectSiteForScript(fileName, referencedProjectFileNames, options) - let deps, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject,site,fileName,options.ExtraProjectInfo,serviceProvider, true) + let deps, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, (tryGetOrCreateProjectId fileName), fileName, options.ExtraProjectInfo, Some projectOptionsTable, true) let parsingOptions, _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions(projectOptions) return (deps, parsingOptions, projectOptions) else let site = ProjectSitesAndFiles.ProjectSiteOfSingleFile(fileName) - let deps, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject,site,fileName,extraProjectInfo,serviceProvider, true) + let deps, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, (tryGetOrCreateProjectId fileName), fileName, extraProjectInfo, Some projectOptionsTable, true) let parsingOptions, _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions(projectOptions) return (deps, parsingOptions, projectOptions) } /// Update the info for a project in the project table - member this.UpdateProjectInfo(tryGetOrCreateProjectId, projectId: ProjectId, site: IProjectSite, userOpName) = - this.AddOrUpdateProject(projectId, (fun isRefresh -> + member this.UpdateProjectInfo(tryGetOrCreateProjectId, projectId, site, userOpName) = + projectOptionsTable.AddOrUpdateProject(projectId, (fun isRefresh -> let extraProjectInfo = Some(box workspace) - let tryGetOptionsForReferencedProject f = f |> tryGetOrCreateProjectId |> Option.bind this.TryGetOptionsForProject |> Option.map snd - let referencedProjects, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, site.ProjectFileName, extraProjectInfo, serviceProvider, true) + let tryGetOptionsForReferencedProject f = f |> tryGetOrCreateProjectId |> Option.bind this.TryGetOptionsForProject |> Option.map(fun (_, _, projectOptions) -> projectOptions) + let referencedProjects, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, (tryGetOrCreateProjectId (site.ProjectFileName)), site.ProjectFileName, extraProjectInfo, Some projectOptionsTable, true) + checkerProvider.Checker.InvalidateConfiguration(projectOptions, startBackgroundCompileIfAlreadySeen = not isRefresh, userOpName = userOpName + ".UpdateProjectInfo") let referencedProjectIds = referencedProjects |> Array.choose tryGetOrCreateProjectId - checkerProvider.Checker.InvalidateConfiguration(projectOptions, startBackgroundCompileIfAlreadySeen = not isRefresh, userOpName= userOpName + ".UpdateProjectInfo") let parsingOptions, _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions(projectOptions) - referencedProjectIds, parsingOptions, projectOptions)) - + referencedProjectIds, parsingOptions, Some site, projectOptions)) + /// Get compilation defines relevant for syntax processing. /// Quicker then TryGetOptionsForDocumentOrProject as it doesn't need to recompute the exact project /// options for a script. - member this.GetCompilationDefinesForEditingDocument(document: Document) = + member this.GetCompilationDefinesForEditingDocument(document:Document) = let projectOptionsOpt = this.TryGetOptionsForProject(document.Project.Id) let parsingOptions = match projectOptionsOpt with - | None -> FSharpParsingOptions.Default - | Some (parsingOptions, _projectOptions) -> parsingOptions + | Some (parsingOptions, _site, _projectOptions) -> parsingOptions + | _ -> FSharpParsingOptions.Default CompilerEnvironment.GetCompilationDefinesForEditing(document.Name, parsingOptions) - /// Get the options for a project - member this.TryGetOptionsForProject(projectId: ProjectId) = - match projectTable.TryGetValue(projectId) with - | true, ((_referencedProjects, parsingOptions, projectOptions), _) -> Some (parsingOptions, projectOptions) - | _ -> None + member this.TryGetOptionsForProject(projectId:ProjectId) = projectOptionsTable.TryGetOptionsForProject(projectId) /// Get the exact options for a document or project member this.TryGetOptionsForDocumentOrProject(document: Document) = async { let projectId = document.Project.Id - + // The options for a single-file script project are re-requested each time the file is analyzed. This is because the // single-file project may contain #load and #r references which are changing as the user edits, and we may need to re-analyze // to determine the latest settings. FCS keeps a cache to help ensure these are up-to-date. @@ -209,87 +184,42 @@ type internal FSharpProjectOptionsManager let tryGetOrCreateProjectId _ = None let! _referencedProjectFileNames, parsingOptions, projectOptions = this.ComputeSingleFileOptions (tryGetOrCreateProjectId, fileName, loadTime, sourceText.ToString(), document.Project.Solution.Workspace) this.AddOrUpdateSingleFileProject(projectId, (loadTime, parsingOptions, projectOptions)) - return Some (parsingOptions, projectOptions) + return Some (parsingOptions, None, projectOptions) with ex -> Assert.Exception(ex) return None - | _ -> return this.TryGetOptionsForProject(projectId) + | _ -> return this.TryGetOptionsForProject(projectId) } /// Get the options for a document or project relevant for syntax processing. /// Quicker then TryGetOptionsForDocumentOrProject as it doesn't need to recompute the exact project options for a script. - member this.TryGetOptionsForEditingDocumentOrProject(document: Document) = + member this.TryGetOptionsForEditingDocumentOrProject(document:Document) = let projectId = document.Project.Id match singleFileProjectTable.TryGetValue(projectId) with | true, (_loadTime, parsingOptions, originalOptions) -> Some (parsingOptions, originalOptions) - | _ -> this.TryGetOptionsForProject(projectId) - - member this.ProvideProjectSiteProvider(project:Project) = - let hier = workspace.GetHierarchy(project.Id) - - {new IProvideProjectSite with - member iProvideProjectSite.GetProjectSite() = - let fst (a, _, _) = a - let thrd (_, _, c) = c - let mutable errorReporter = - let reporter = ProjectExternalErrorReporter(project.Id, "FS", serviceProvider) - Some(reporter:> Microsoft.VisualStudio.Shell.Interop.IVsLanguageServiceBuildErrorReporter2) - - {new Microsoft.VisualStudio.FSharp.LanguageService.IProjectSite with - member __.CompilationSourceFiles = this.GetProjectInfo(project.FilePath) |> fst - member __.CompilationOptions = - let _,references,options = this.GetProjectInfo(project.FilePath) - Array.concat [options; references |> Array.map(fun r -> "-r:" + r)] - member __.CompilationReferences = this.GetProjectInfo(project.FilePath) |> thrd - member site.CompilationBinOutputPath = site.CompilationOptions |> Array.tryPick (fun s -> if s.StartsWith("-o:") then Some s.[3..] else None) - member __.Description = project.Name - member __.ProjectFileName = project.FilePath - member __.AdviseProjectSiteChanges(_,_) = () - member __.AdviseProjectSiteCleaned(_,_) = () - member __.AdviseProjectSiteClosed(_,_) = () - member __.IsIncompleteTypeCheckEnvironment = false - member __.TargetFrameworkMoniker = "" - member __.ProjectGuid = project.Id.Id.ToString() - member __.LoadTime = System.DateTime.Now - member __.ProjectProvider = Some iProvideProjectSite - member __.BuildErrorReporter with get () = errorReporter and - set (v) = errorReporter <- v - } - - // TODO: figure out why this is necessary - interface IVsHierarchy with - member __.SetSite(psp) = hier.SetSite(psp) - member __.GetSite(psp) = hier.GetSite(ref psp) - member __.QueryClose(pfCanClose) = hier.QueryClose(ref pfCanClose) - member __.Close() = hier.Close() - member __.GetGuidProperty(itemid, propid, pguid) = hier.GetGuidProperty(itemid, propid, ref pguid) - member __.SetGuidProperty(itemid, propid, rguid) = hier.SetGuidProperty(itemid, propid, ref rguid) - member __.GetProperty(itemid, propid, pvar) = hier.GetProperty(itemid, propid, ref pvar) - member __.SetProperty(itemid, propid, var) = hier.SetProperty(itemid, propid, var) - member __.GetNestedHierarchy(itemid, iidHierarchyNested, ppHierarchyNested, pitemidNested) = hier.GetNestedHierarchy(itemid, ref iidHierarchyNested, ref ppHierarchyNested, ref pitemidNested) - member __.GetCanonicalName(itemid, pbstrName) = hier.GetCanonicalName(itemid, ref pbstrName) - member __.ParseCanonicalName(pszName, pitemid) = hier.ParseCanonicalName(pszName, ref pitemid) - member __.Unused0() = hier.Unused0() - member __.AdviseHierarchyEvents(pEventSink, pdwCookie) = hier.AdviseHierarchyEvents(pEventSink, ref pdwCookie) - member __.UnadviseHierarchyEvents(dwCookie) = hier.UnadviseHierarchyEvents(dwCookie) - member __.Unused1() = hier.Unused1() - member __.Unused2() = hier.Unused2() - member __.Unused3() = hier.Unused3() - member __.Unused4() = hier.Unused4() - } + | _ -> this.TryGetOptionsForProject(projectId) |> Option.map(fun (parsingOptions, _, projectOptions) -> parsingOptions, projectOptions) + /// get a siteprovider + member this.ProvideProjectSiteProvider(project:Project) = provideProjectSiteProvider(workspace, project, serviceProvider, Some projectOptionsTable) + + /// Tell the checker to update the project info for the specified project id member this.UpdateProjectInfoWithProjectId(projectId:ProjectId, userOpName) = let hier = workspace.GetHierarchy(projectId) match hier with + | null -> () | h when (h.IsCapabilityMatch("CPS")) -> let project = workspace.CurrentSolution.GetProject(projectId) - let siteProvider = this.ProvideProjectSiteProvider(project) - this.UpdateProjectInfo(tryGetOrCreateProjectId, projectId, siteProvider.GetProjectSite(), userOpName) + if not (isNull project) then + let siteProvider = this.ProvideProjectSiteProvider(project) + let projectSite = siteProvider.GetProjectSite() + if projectSite.CompilationSourceFiles.Length <> 0 then + this.UpdateProjectInfo(tryGetOrCreateProjectId, projectId, projectSite, userOpName) | _ -> () - member this.UpdateProjectInfoWithPath(path, userOpName) = - let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(path, projectDisplayNameOf path) - this.UpdateProjectInfoWithProjectId(projectId, userOpName) + /// Tell the checker to update the project info for the specified project id + member this.UpdateDocumenttInfoWithProjectId(projectId:ProjectId, documentId:DocumentId, userOpName) = + if workspace.IsDocumentOpen(documentId) then + this.UpdateProjectInfoWithProjectId(projectId, userOpName) [] /// This handles commandline change notifications from the Dotnet Project-system @@ -299,13 +229,9 @@ type internal FSharpProjectOptionsManager else Path.Combine(Path.GetDirectoryName(path), p) let sourcePaths = sources |> Seq.map(fun s -> fullPath s.Path) |> Seq.toArray let referencePaths = references |> Seq.map(fun r -> fullPath r.Reference) |> Seq.toArray - projectInfo.[path] <- (sourcePaths,referencePaths,options.ToArray()) - this.UpdateProjectInfoWithPath(path, "HandleCommandLineChanges") - - member __.GetProjectInfo(path:string) = - match projectInfo.TryGetValue path with - | true, value -> value - | _ -> [||], [||], [||] + let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(path, projectDisplayNameOf path) + projectOptionsTable.SetOptionsWithProjectId(projectId, sourcePaths, referencePaths, options.ToArray()) + this.UpdateProjectInfoWithProjectId(projectId, "HandleCommandLineChanges") member __.Checker = checkerProvider.Checker @@ -419,13 +345,34 @@ type let optionsAssociation = ConditionalWeakTable() - member private this.OnProjectAdded(projectId:ProjectId, _newSolution:Solution) = projectInfoManager.UpdateProjectInfoWithProjectId(projectId, "OnProjectAdded") - override this.Initialize() = + member private this.OnProjectAdded(projectId:ProjectId) = projectInfoManager.UpdateProjectInfoWithProjectId(projectId, "OnProjectAdded") + member private this.OnProjectReloaded(projectId:ProjectId) = projectInfoManager.UpdateProjectInfoWithProjectId(projectId, "OnProjectReloaded") + member private this.OnDocumentAdded(projectId:ProjectId, documentId:DocumentId) = projectInfoManager.UpdateDocumenttInfoWithProjectId(projectId, documentId, "OnDocumentAdded") + member private this.OnDocumentChanged(projectId:ProjectId, documentId:DocumentId) = projectInfoManager.UpdateDocumenttInfoWithProjectId(projectId, documentId, "OnDocumentChanged") + member private this.OnDocumentReloaded(projectId:ProjectId, documentId:DocumentId) = projectInfoManager.UpdateDocumenttInfoWithProjectId(projectId, documentId, "OnDocumentReloaded") + + override this.Initialize() = base.Initialize() let workspaceChanged (args:WorkspaceChangeEventArgs) = match args.Kind with - | WorkspaceChangeKind.ProjectAdded -> this.OnProjectAdded(args.ProjectId, args.NewSolution) + | WorkspaceChangeKind.ProjectAdded -> this.OnProjectAdded(args.ProjectId) + | WorkspaceChangeKind.ProjectReloaded -> this.OnProjectReloaded(args.ProjectId) + | WorkspaceChangeKind.DocumentAdded -> this.OnDocumentAdded(args.ProjectId, args.DocumentId) + | WorkspaceChangeKind.DocumentChanged -> this.OnDocumentChanged(args.ProjectId, args.DocumentId) + | WorkspaceChangeKind.DocumentReloaded -> this.OnDocumentReloaded(args.ProjectId, args.DocumentId) + | WorkspaceChangeKind.DocumentRemoved + | WorkspaceChangeKind.ProjectRemoved + | WorkspaceChangeKind.AdditionalDocumentAdded + | WorkspaceChangeKind.AdditionalDocumentReloaded + | WorkspaceChangeKind.AdditionalDocumentRemoved + | WorkspaceChangeKind.AdditionalDocumentChanged + | WorkspaceChangeKind.DocumentInfoChanged + | WorkspaceChangeKind.DocumentChanged + | WorkspaceChangeKind.SolutionAdded + | WorkspaceChangeKind.SolutionChanged + | WorkspaceChangeKind.SolutionReloaded + | WorkspaceChangeKind.SolutionCleared | _ -> () this.Workspace.Options <- this.Workspace.Options.WithChangedOption(Completion.CompletionOptions.BlockForCompletionItems, FSharpConstants.FSharpLanguageName, false) @@ -553,7 +500,7 @@ type // Roslyn is expecting site to be an IVsHierarchy. // It just so happens that the object that implements IProvideProjectSite is also // an IVsHierarchy. This assertion is to ensure that the assumption holds true. - Debug.Assert(hierarchy <> null, "About to CreateProjectContext with a non-hierarchy site") + Debug.Assert(not (isNull hierarchy), "About to CreateProjectContext with a non-hierarchy site") let projectContext = projectContextFactory.CreateProjectContext( @@ -582,7 +529,7 @@ type optionsAssociation.Remove(projectContext) |> ignore project.Disconnect())) - for referencedSite in ProjectSitesAndFiles.GetReferencedProjectSites (site, this.SystemServiceProvider) do + for referencedSite in ProjectSitesAndFiles.GetReferencedProjectSites(site, this.SystemServiceProvider, Some (this.Workspace :>obj), Some projectInfoManager.FSharpOptions ) do setup referencedSite setup (siteProvider.GetProjectSite()) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs b/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs index 15995d015f0..b2ad08f76ad 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/SymbolHelpers.fs @@ -59,7 +59,7 @@ module internal SymbolHelpers = |> Seq.map (fun project -> async { match projectInfoManager.TryGetOptionsForProject(project.Id) with - | Some (_parsingOptions, projectOptions) -> + | Some (_parsingOptions, _site, projectOptions) -> let! projectCheckResults = checker.ParseAndCheckProject(projectOptions, userOpName = userOpName) return! projectCheckResults.GetUsesOfSymbol(symbol) | None -> return [||] diff --git a/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs b/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs index 2ef32dd1941..840138c00b3 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/Tokenizer.fs @@ -532,7 +532,7 @@ module internal Tokenizer = | _ -> false) |> Option.orElseWith (fun _ -> tokensUnderCursor |> List.tryFind (fun { DraftToken.Kind = k } -> k = LexerSymbolKind.Operator)) |> Option.map (fun token -> - let plid, _ = QuickParse.GetPartialLongNameEx(lineStr, token.RightColumn) + let partialName = QuickParse.GetPartialLongNameEx(lineStr, token.RightColumn) let identStr = lineStr.Substring(token.Token.LeftColumn, token.Token.FullMatchedLength) { Kind = token.Kind Ident = @@ -541,7 +541,7 @@ module internal Tokenizer = fileName (Range.mkPos (linePos.Line + 1) token.Token.LeftColumn) (Range.mkPos (linePos.Line + 1) (token.RightColumn + 1))) - FullIsland = plid @ [identStr] }) + FullIsland = partialName.QualifyingIdents @ [identStr] }) let private getCachedSourceLineData(documentKey: DocumentId, sourceText: SourceText, position: int, fileName: string, defines: string list) = let textLine = sourceText.Lines.GetLineFromPosition(position) diff --git a/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs b/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs index e3479737db0..0f7fde12e79 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs @@ -51,7 +51,7 @@ type internal FSharpFindUsagesService asyncMaybe { let! sourceText = document.GetTextAsync(context.CancellationToken) |> Async.AwaitTask |> liftAsync let checker = checkerProvider.Checker - let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document) + let! parsingOptions, _, projectOptions = projectInfoManager.TryGetOptionsForDocumentOrProject(document) let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, projectOptions, sourceText = sourceText, allowStaleResults = true, userOpName = userOpName) let textLine = sourceText.Lines.GetLineFromPosition(position).ToString() let lineNumber = sourceText.Lines.GetLinePosition(position).Line + 1 @@ -112,7 +112,7 @@ type internal FSharpFindUsagesService projectsToCheck |> Seq.map (fun project -> asyncMaybe { - let! _parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForProject(project.Id) + let! _parsingOptions, _site, projectOptions = projectInfoManager.TryGetOptionsForProject(project.Id) let! projectCheckResults = checker.ParseAndCheckProject(projectOptions, userOpName = userOpName) |> liftAsync return! projectCheckResults.GetUsesOfSymbol(symbolUse.Symbol) |> liftAsync } |> Async.map (Option.defaultValue [||])) diff --git a/vsintegration/src/FSharp.Editor/Navigation/NavigateToSearchService.fs b/vsintegration/src/FSharp.Editor/Navigation/NavigateToSearchService.fs index a1cee3bff49..38c2abc9687 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/NavigateToSearchService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/NavigateToSearchService.fs @@ -233,7 +233,7 @@ type internal FSharpNavigateToSearchService interface INavigateToSearchService with member __.SearchProjectAsync(project, searchPattern, cancellationToken) : Task> = asyncMaybe { - let! parsingOptions, _options = projectInfoManager.TryGetOptionsForProject(project.Id) + let! parsingOptions, _site, _options = projectInfoManager.TryGetOptionsForProject(project.Id) let! items = project.Documents |> Seq.map (fun document -> getCachedIndexedNavigableItems(document, parsingOptions)) @@ -265,7 +265,7 @@ type internal FSharpNavigateToSearchService member __.SearchDocumentAsync(document, searchPattern, cancellationToken) : Task> = asyncMaybe { - let! parsingOptions, _options = projectInfoManager.TryGetOptionsForDocumentOrProject(document) + let! parsingOptions, _, _ = projectInfoManager.TryGetOptionsForDocumentOrProject(document) let! items = getCachedIndexedNavigableItems(document, parsingOptions) |> liftAsync return items.Find(searchPattern) } diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs index faf5230a7cd..0f4409a99d1 100644 --- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs +++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs @@ -13,7 +13,7 @@ module DefaultTuning = let UnusedDeclarationsAnalyzerInitialDelay = 0 (* 1000 *) (* milliseconds *) let UnusedOpensAnalyzerInitialDelay = 0 (* 2000 *) (* milliseconds *) let SimplifyNameInitialDelay = 2000 (* milliseconds *) - let SimplifyNameEachItemDelay = 5 (* milliseconds *) + let SimplifyNameEachItemDelay = 0 (* milliseconds *) // CLIMutable to make the record work also as a view model [] diff --git a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs index 8e4a6fa82a0..802d8948ca5 100644 --- a/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs +++ b/vsintegration/src/FSharp.Editor/QuickInfo/QuickInfoProvider.fs @@ -55,7 +55,7 @@ module private FSharpQuickInfo = let extLineText = (extSourceText.Lines.GetLineFromPosition extSpan.Start).ToString() // project options need to be retrieved because the signature file could be in another project - let! extParsingOptions, extProjectOptions = projectInfoManager.TryGetOptionsForProject extDocId.ProjectId + let! extParsingOptions, _extSite, extProjectOptions = projectInfoManager.TryGetOptionsForProject extDocId.ProjectId let extDefines = CompilerEnvironment.GetCompilationDefinesForEditing (extDocument.FilePath, extParsingOptions) let! extLexerSymbol = Tokenizer.getSymbolAtPosition(extDocId, extSourceText, extSpan.Start, declRange.FileName, extDefines, SymbolLookupKind.Greedy, true) let! _, _, extCheckFileResults = checker.ParseAndCheckDocument(extDocument, extProjectOptions, allowStaleResults=true, sourceText=extSourceText, userOpName = userOpName) diff --git a/vsintegration/src/FSharp.LanguageService/AssemblyInfo.fs b/vsintegration/src/FSharp.LanguageService/AssemblyInfo.fs index e1972d2d075..a043d6eb300 100644 --- a/vsintegration/src/FSharp.LanguageService/AssemblyInfo.fs +++ b/vsintegration/src/FSharp.LanguageService/AssemblyInfo.fs @@ -5,17 +5,6 @@ namespace Microsoft.FSharp open System.Reflection open Microsoft.VisualStudio.Shell -[] -[] -[] -[] -[] -[] -[] -[] -[] -[] - [] do() diff --git a/vsintegration/src/FSharp.LanguageService/BackgroundRequests.fs b/vsintegration/src/FSharp.LanguageService/BackgroundRequests.fs index 36404fd5eb8..42c673d90b7 100644 --- a/vsintegration/src/FSharp.LanguageService/BackgroundRequests.fs +++ b/vsintegration/src/FSharp.LanguageService/BackgroundRequests.fs @@ -7,14 +7,10 @@ namespace Microsoft.VisualStudio.FSharp.LanguageService open System -open System.Runtime.InteropServices -open Microsoft.VisualStudio open Microsoft.VisualStudio.TextManager.Interop open Microsoft.VisualStudio.Text -open Microsoft.VisualStudio.OLE.Interop -open Microsoft.VisualStudio.Shell.Interop -open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.SourceCodeServices +open Microsoft.VisualStudio.FSharp.LanguageService.SiteProvider #nowarn "44" // use of obsolete CheckFileInProjectAllowingStaleCachedResults @@ -113,7 +109,7 @@ type internal FSharpLanguageServiceBackgroundRequests_DEPRECATED let rdt = getServiceProvider().RunningDocumentTable let projectSite = getProjectSitesAndFiles().FindOwningProject_DEPRECATED(rdt,fileName) let enableInMemoryCrossProjectReferences = true - let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, (fun _ -> None), projectSite, fileName, None, getServiceProvider(), false) + let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, (fun _ -> None), projectSite, getServiceProvider(), None(*projectId*), fileName, None(*extraProjectInfo*), None(*FSharpProjectOptionsTable*), false) let projectFileName = projectSite.ProjectFileName let data = { ProjectSite = projectSite diff --git a/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj b/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj index 7cacb5885ee..22c3f49cf78 100644 --- a/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj +++ b/vsintegration/src/FSharp.LanguageService/FSharp.LanguageService.fsproj @@ -42,6 +42,18 @@ + + + + + + + + + + + + $(FSharpSourcesRoot)\..\loc\lcl\{Lang}\$(AssemblyName).dll.lcl @@ -56,7 +68,6 @@ - @@ -67,7 +78,6 @@ - @@ -84,7 +94,6 @@ - $(FSharpSourcesRoot)\..\packages\Microsoft.VisualFSharp.Msbuild.15.0.1.0.1\lib\net45\Microsoft.Build.Framework.dll @@ -96,7 +105,7 @@ $(FSharpSourcesRoot)\..\packages\EnvDTE80.8.0.1\lib\net10\EnvDTE80.dll True - + $(FSharpSourcesRoot)\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj.dll True @@ -150,7 +159,7 @@ $(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Designer.Interfaces.1.1.4322\lib\microsoft.visualstudio.designer.interfaces.dll - + $(FSharpSourcesRoot)\..\packages\VSSDK.VSHelp.7.0.4\lib\net20\Microsoft.VisualStudio.VSHelp.dll True diff --git a/vsintegration/src/FSharp.LanguageService/GotoDefinition.fs b/vsintegration/src/FSharp.LanguageService/GotoDefinition.fs index dd4f2df45be..b027528e689 100644 --- a/vsintegration/src/FSharp.LanguageService/GotoDefinition.fs +++ b/vsintegration/src/FSharp.LanguageService/GotoDefinition.fs @@ -57,7 +57,7 @@ module internal GotoDefinition = | Some (s, colIdent, isQuoted) -> let qualId = if isQuoted then [s] else s.Split '.' |> Array.toList // chop it up (in case it's a qualified ident) // this is a bit irratiting: `GetTokenInfoAt` won't handle just-past-the-end, so we take the just-past-the-end position and adjust it by the `magicalAdjustmentConstant` to just-*at*-the-end - let colIdentAdjusted = colIdent - QuickParse.magicalAdjustmentConstant + let colIdentAdjusted = colIdent - QuickParse.MagicalAdjustmentConstant // Corrrect the identifier (e.g. to correctly handle active pattern names that end with "BAR" token) let tag = colourizer.GetTokenInfoAt(VsTextLines.TextColorState(VsTextView.Buffer textView), line, colIdentAdjusted).Token diff --git a/vsintegration/src/FSharp.LanguageService/IProjectSite.fs b/vsintegration/src/FSharp.LanguageService/IProjectSite.fs index dfdc99d8ec4..18e75ee37db 100644 --- a/vsintegration/src/FSharp.LanguageService/IProjectSite.fs +++ b/vsintegration/src/FSharp.LanguageService/IProjectSite.fs @@ -29,6 +29,9 @@ and internal IProjectSite = /// The '-o:' output bin path, without the '-o:' abstract CompilationBinOutputPath : string option + /// The name of the project file. + abstract ProjectFileName : string + /// Register for notifications for when the above change abstract AdviseProjectSiteChanges : callbackOwnerKey: string * AdviseProjectSiteChanges -> unit @@ -41,9 +44,6 @@ and internal IProjectSite = /// A user-friendly description of the project. Used only for developer/DEBUG tooltips and such. abstract Description : string - /// The name of the project file. - abstract ProjectFileName : string - /// The error list task reporter abstract BuildErrorReporter : Microsoft.VisualStudio.Shell.Interop.IVsLanguageServiceBuildErrorReporter2 option with get, set diff --git a/vsintegration/src/FSharp.LanguageService/Intellisense.fs b/vsintegration/src/FSharp.LanguageService/Intellisense.fs index f34c49f3fcd..2a5fa9e6ebf 100644 --- a/vsintegration/src/FSharp.LanguageService/Intellisense.fs +++ b/vsintegration/src/FSharp.LanguageService/Intellisense.fs @@ -528,14 +528,14 @@ type internal FSharpIntellisenseInfo_DEPRECATED else None // TODO don't use QuickParse below, we have parse info available - let plid = QuickParse.GetPartialLongNameEx(lineText, col-1) - ignore plid // for breakpoint + let pname = QuickParse.GetPartialLongNameEx(lineText, col-1) + let _x = 1 // for breakpoint let detectTextChange (oldTextSnapshotInfo: obj, range) = let oldTextSnapshot = oldTextSnapshotInfo :?> ITextSnapshot hasTextChangedSinceLastTypecheck (textSnapshot, oldTextSnapshot, Range.Range.toZ range) - let! decls = typedResults.GetDeclarationListInfo(untypedParseInfoOpt, Range.Line.fromZ line, col, lineText, fst plid, snd plid, (fun() -> []), detectTextChange) + let! decls = typedResults.GetDeclarationListInfo(untypedParseInfoOpt, Range.Line.fromZ line, lineText, pname, (fun() -> []), detectTextChange) return (new FSharpDeclarations_DEPRECATED(documentationBuilder, decls.Items, reason) :> Declarations_DEPRECATED) else // no TypeCheckInfo in ParseResult. diff --git a/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs b/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs index 122d685184a..7f706e98443 100644 --- a/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs +++ b/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs @@ -7,7 +7,7 @@ // information is conveyed to the rest of the implementation via an IProjectSite interface. // // For most purposes, an IProjectSite has to provide three main things -// - the source files +// - the source files` // - the compilation options // - the assembly references. // Project.fs collects the first two from MSBuild. For the third - assembly references - it looks @@ -30,29 +30,47 @@ // This means a lot of the stuff above is irrelevant in that case, apart from where FSharpProjectOptionsManager // incrementally maintains a corresponding F# CompilerService FSharpProjectOptions value. -namespace Microsoft.VisualStudio.FSharp.LanguageService +module internal rec Microsoft.VisualStudio.FSharp.LanguageService.SiteProvider open System +open System.Collections.Concurrent +open System.ComponentModel.Composition open System.IO open System.Diagnostics -open System.Runtime.InteropServices open Microsoft.VisualStudio open Microsoft.VisualStudio.TextManager.Interop open Microsoft.VisualStudio.Shell.Interop open Microsoft.FSharp.Compiler.SourceCodeServices +open Microsoft.CodeAnalysis +open Microsoft.VisualStudio.LanguageServices +open Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem +open Microsoft.VisualStudio.LanguageServices.Implementation.TaskList +open VSLangProj +open System.ComponentModel.Composition.Primitives +open Microsoft.VisualStudio.Shell +open System.Collections.Immutable + + /// An additional interface that an IProjectSite object can implement to indicate it has an FSharpProjectOptions /// already available, so we don't have to recreate it type private IHaveCheckOptions = abstract OriginalCheckOptions : unit -> string[] * FSharpProjectOptions - + +let projectDisplayNameOf projectFileName = + if String.IsNullOrWhiteSpace projectFileName then projectFileName + else Path.GetFileNameWithoutExtension projectFileName + +/// A value and a function to recompute/refresh the value. The function is passed a flag indicating if a refresh is happening. +type Refreshable<'T> = 'T * (bool -> 'T) + /// Convert from FSharpProjectOptions into IProjectSite. -type private ProjectSiteOfScriptFile(filename:string, referencedProjectFileNames, checkOptions : FSharpProjectOptions) = +type private ProjectSiteOfScriptFile(filename:string, referencedProjectFileNames, checkOptions: FSharpProjectOptions) = interface IProjectSite with override this.Description = sprintf "Script Closure at Root %s" filename override this.CompilationSourceFiles = checkOptions.SourceFiles override this.CompilationOptions = checkOptions.OtherOptions - override this.CompilationReferences = + override this.CompilationReferences = checkOptions.OtherOptions |> Array.choose (fun flag -> if flag.StartsWith("-r:") then Some flag.[3..] else None) override this.CompilationBinOutputPath = None @@ -69,21 +87,23 @@ type private ProjectSiteOfScriptFile(filename:string, referencedProjectFileNames interface IHaveCheckOptions with override this.OriginalCheckOptions() = (referencedProjectFileNames, checkOptions) - + override x.ToString() = sprintf "ProjectSiteOfScriptFile(%s)" filename - + /// An orphan file project is a .fs, .ml, .fsi, .mli that is not associated with a .fsproj. /// By design, these are never going to typecheck because there is no affiliated references. /// We show many squiggles in this case because they're not particularly informational. -type private ProjectSiteOfSingleFile(sourceFile) = - // CompilationOptions gets called a lot, so pre-compute what we can +type private ProjectSiteOfSingleFile(sourceFile) = + // CompilerFlags() gets called a lot, so pre-compute what we can static let compilerFlags = let flags = ["--noframework";"--warn:3"] let assumeDotNetFramework = true let defaultReferences = [ for r in CompilerEnvironment.DefaultReferencesForOrphanSources(assumeDotNetFramework) do yield sprintf "-r:%s%s" r (if r.EndsWith(".dll",StringComparison.OrdinalIgnoreCase) then "" else ".dll") ] - (flags @ defaultReferences) |> List.toArray + (flags @ defaultReferences) + |> List.toArray + |> Array.choose (fun flag -> if flag.StartsWith("-r:") then Some flag.[3..] elif flag.StartsWith("--reference:") then Some flag.[12..] else None) let projectFileName = sourceFile + ".orphan.fsproj" @@ -91,9 +111,9 @@ type private ProjectSiteOfSingleFile(sourceFile) = override this.Description = projectFileName override this.CompilationSourceFiles = [|sourceFile|] override this.CompilationOptions = compilerFlags - override this.CompilationReferences = compilerFlags |> Array.choose (fun flag -> if flag.StartsWith("-r:") then Some flag.[3..] else None) + override this.CompilationReferences = compilerFlags override this.CompilationBinOutputPath = None - override this.ProjectFileName = projectFileName + override this.ProjectFileName = projectFileName override this.BuildErrorReporter with get() = None and set _v = () override this.AdviseProjectSiteChanges(_,_) = () override this.AdviseProjectSiteCleaned(_,_) = () @@ -103,20 +123,112 @@ type private ProjectSiteOfSingleFile(sourceFile) = override this.ProjectGuid = "" override this.LoadTime = new DateTime(2000,1,1) // any constant time is fine, orphan files do not interact with reloading based on update time override this.ProjectProvider = None - + override x.ToString() = sprintf "ProjectSiteOfSingleFile(%s)" sourceFile - + +/// Manage Storage of FSharpProjectOptions the options for a project +type internal FSharpProjectOptionsTable () = + // A table of information about projects, excluding single-file projects. + let projectTable = ConcurrentDictionary>() + let commandLineOptions = new ConcurrentDictionary() + + /// Go and re-get all of the options for everything that references projectId + let refreshInfoForProjectsThatReferenceThisProject (projectId:ProjectId) = + for KeyValue(otherProjectId, ((referencedProjectIds, _parsingOptions, _site, _options), refresh)) in projectTable.ToArray() do + for referencedProjectId in referencedProjectIds do + if referencedProjectId = projectId then + projectTable.[otherProjectId] <- (refresh true, refresh) + + /// Add or update a project in the project table + member __.AddOrUpdateProject(projectId:ProjectId, refresh) = + projectTable.[projectId] <- (refresh false, refresh) + refreshInfoForProjectsThatReferenceThisProject(projectId) + + /// Clear a project from the project table + member this.ClearInfoForProject(projectId:ProjectId) = + projectTable.TryRemove(projectId) |> ignore + refreshInfoForProjectsThatReferenceThisProject projectId + + /// Get the options for a project + member this.TryGetOptionsForProject(projectId:ProjectId) = + match projectTable.TryGetValue(projectId) with + | true, ((_referencedProjects, parsingOptions, site, projectOptions), _) -> Some (parsingOptions, site, projectOptions) + | _ -> None + + /// Given a projectId return the most recent set of command line options for it + member __.GetCommandLineOptionsWithProjectId(projectId:ProjectId) = + match commandLineOptions.TryGetValue projectId with + | true, (sources, references, options) -> sources, references, options + | _ -> [||], [||], [||] + + member this.SetOptionsWithProjectId(projectId:ProjectId, sourcePaths:string[], referencePaths:string[], options:string[]) = + commandLineOptions.[projectId] <- (sourcePaths, referencePaths, options) + +let internal provideProjectSiteProvider(workspace:VisualStudioWorkspaceImpl, project:Project, serviceProvider:System.IServiceProvider, projectOptionsTable:FSharpProjectOptionsTable option) = + let hier = workspace.GetHierarchy(project.Id) + let getCommandLineOptionsWithProjectId (projectId) = + match projectOptionsTable with + | Some (options) -> options.GetCommandLineOptionsWithProjectId(projectId) + | None -> [||], [||], [||] + {new IProvideProjectSite with + member x.GetProjectSite() = + let fst (a, _, _) = a + let snd (_, b, _) = b + let mutable errorReporter = + let reporter = ProjectExternalErrorReporter(project.Id, "FS", serviceProvider) + Some(reporter:> IVsLanguageServiceBuildErrorReporter2) + + { new IProjectSite with + member __.Description = project.Name + member __.CompilationSourceFiles = getCommandLineOptionsWithProjectId(project.Id) |> fst + member __.CompilationOptions = + let _,references,options = getCommandLineOptionsWithProjectId(project.Id) + Array.concat [options; references |> Array.map(fun r -> "-r:" + r)] + member __.CompilationReferences = getCommandLineOptionsWithProjectId(project.Id) |> snd + member site.CompilationBinOutputPath = site.CompilationOptions |> Array.tryPick (fun s -> if s.StartsWith("-o:") then Some s.[3..] else None) + member __.ProjectFileName = project.FilePath + member __.AdviseProjectSiteChanges(_,_) = () + member __.AdviseProjectSiteCleaned(_,_) = () + member __.AdviseProjectSiteClosed(_,_) = () + member __.IsIncompleteTypeCheckEnvironment = false + member __.TargetFrameworkMoniker = "" + member __.ProjectGuid = project.Id.Id.ToString() + member __.LoadTime = System.DateTime.Now + member __.ProjectProvider = Some (x) + member __.BuildErrorReporter with get () = errorReporter and + set (v) = errorReporter <- v + } + + interface IVsHierarchy with + member __.SetSite(psp) = hier.SetSite(psp) + member __.GetSite(psp) = hier.GetSite(ref psp) + member __.QueryClose(pfCanClose) = hier.QueryClose(ref pfCanClose) + member __.Close() = hier.Close() + member __.GetGuidProperty(itemid, propid, pguid) = hier.GetGuidProperty(itemid, propid, ref pguid) + member __.SetGuidProperty(itemid, propid, rguid) = hier.SetGuidProperty(itemid, propid, ref rguid) + member __.GetProperty(itemid, propid, pvar) = hier.GetProperty(itemid, propid, ref pvar) + member __.SetProperty(itemid, propid, var) = hier.SetProperty(itemid, propid, var) + member __.GetNestedHierarchy(itemid, iidHierarchyNested, ppHierarchyNested, pitemidNested) = hier.GetNestedHierarchy(itemid, ref iidHierarchyNested, ref ppHierarchyNested, ref pitemidNested) + member __.GetCanonicalName(itemid, pbstrName) = hier.GetCanonicalName(itemid, ref pbstrName) + member __.ParseCanonicalName(pszName, pitemid) = hier.ParseCanonicalName(pszName, ref pitemid) + member __.Unused0() = hier.Unused0() + member __.AdviseHierarchyEvents(pEventSink, pdwCookie) = hier.AdviseHierarchyEvents(pEventSink, ref pdwCookie) + member __.UnadviseHierarchyEvents(dwCookie) = hier.UnadviseHierarchyEvents(dwCookie) + member __.Unused1() = hier.Unused1() + member __.Unused2() = hier.Unused2() + member __.Unused3() = hier.Unused3() + member __.Unused4() = hier.Unused4() + } + /// Information about projects, open files and other active artifacts in visual studio. /// Keeps track of the relationship between IVsTextLines buffers, IFSharpSource_DEPRECATED objects, IProjectSite objects and FSharpProjectOptions [] type internal ProjectSitesAndFiles() = static let sourceUserDataGuid = new Guid("{55F834FD-B950-4C61-BBAA-0511ABAF4AE2}") // Guid for source user data on text buffer - static let mutable stamp = 0L static let tryGetProjectSite(hierarchy:IVsHierarchy) = match hierarchy with - | :? IProvideProjectSite as siteFactory -> - Some(siteFactory.GetProjectSite()) + | :? IProvideProjectSite as siteFactory -> Some(siteFactory.GetProjectSite()) | _ -> None static let fullOutputAssemblyPath (p:EnvDTE.Project) = @@ -132,64 +244,95 @@ type internal ProjectSitesAndFiles() = static let referencedProjects (projectSite:IProjectSite) = match projectSite.ProjectProvider with - | None -> Seq.empty - | Some (:? IVsHierarchy as hier) -> + | None -> None + | Some (:? IVsHierarchy as hier) -> match hier.GetProperty(VSConstants.VSITEMID_ROOT, int __VSHPROPID.VSHPROPID_ExtObject) with - | VSConstants.S_OK, (:? EnvDTE.Project as p) -> - (p.Object :?> VSLangProj.VSProject).References - |> Seq.cast - |> Seq.choose (fun r -> - Option.ofObj r - |> Option.bind (fun r -> try Option.ofObj r.SourceProject with _ -> None)) - | _ -> Seq.empty - | Some _ -> Seq.empty - - static let rec referencedProvideProjectSites (projectSite:IProjectSite, serviceProvider:System.IServiceProvider) = - seq { - let solutionService = try Some (serviceProvider.GetService(typeof) :?> IVsSolution) with _ -> None - match solutionService with - | Some solutionService -> - for p in referencedProjects projectSite do - match solutionService.GetProjectOfUniqueName(p.UniqueName) with - | VSConstants.S_OK, (:? IProvideProjectSite as ps) -> - yield (p, ps) - | _ -> () - | None -> () - } - - static let rec referencedProjectsOf (enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite:IProjectSite, extraProjectInfo, serviceProvider:System.IServiceProvider, useUniqueStamp) = - [| for (p,ps) in referencedProvideProjectSites (projectSite, serviceProvider) do - match fullOutputAssemblyPath p with + | VSConstants.S_OK, (:? EnvDTE.Project as p) when not (isNull p) -> + Some ((p.Object :?> VSLangProj.VSProject).References + |> Seq.cast + |> Seq.choose (fun r -> + Option.ofObj r + |> Option.bind (fun r -> try Option.ofObj r.SourceProject with _ -> None)) ) + | _ -> None + | Some _ -> None + + static let rec referencedProvideProjectSites(projectSite:IProjectSite, serviceProvider:System.IServiceProvider, extraProjectInfo:obj option, projectOptionsTable:FSharpProjectOptionsTable option) = + let getReferencesForSolutionService (solutionService:IVsSolution) = + [| + match referencedProjects projectSite, extraProjectInfo with + | None, Some (:? VisualStudioWorkspaceImpl as workspace) when not (isNull workspace.CurrentSolution)-> + let path = projectSite.ProjectFileName + if not (String.IsNullOrWhiteSpace(path)) then + let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(path, projectDisplayNameOf path) + let project = workspace.CurrentSolution.GetProject(projectId) + if not (isNull project) then + for reference in project.ProjectReferences do + let project = workspace.CurrentSolution.GetProject(reference.ProjectId) + if not (isNull project) then + let siteProvider = provideProjectSiteProvider (workspace, project, serviceProvider, projectOptionsTable) + let referenceProject = workspace.ProjectTracker.GetProject(reference.ProjectId) + let outputPath = referenceProject.BinOutputPath + yield Some projectId, project.FilePath, outputPath, siteProvider + + | (Some references), _ -> + for p in references do + match solutionService.GetProjectOfUniqueName(p.UniqueName) with + | VSConstants.S_OK, (:? IProvideProjectSite as ps) -> + yield None, p.FileName, (fullOutputAssemblyPath p) |> Option.defaultValue "", ps + | _ -> () + | None, _ -> () + |] + let solutionService = try Some (serviceProvider.GetService(typeof) :?> IVsSolution) with _ -> None + seq { match solutionService with + | Some solutionService -> + for reference in getReferencesForSolutionService solutionService do yield reference | None -> () - | Some path -> - let referencedProjectOptions = - // Lookup may not succeed if the project has not been established yet - // In this case we go and compute the options recursively. - match tryGetOptionsForReferencedProject p.FileName with - | None -> getProjectOptionsForProjectSite (enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, ps.GetProjectSite(), p.FileName, extraProjectInfo, serviceProvider, useUniqueStamp) |> snd - | Some options -> options - yield (p.FileName, (path, referencedProjectOptions)) |] - - and getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite:IProjectSite, fileName, extraProjectInfo, serviceProvider, useUniqueStamp) = + } + + static let rec referencedProjectsOf(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, extraProjectInfo, projectOptionsTable, useUniqueStamp) = + [| for (projectId, projectFileName, outputPath, projectSiteProvider) in referencedProvideProjectSites (projectSite, serviceProvider, extraProjectInfo, projectOptionsTable) do + let referencedProjectOptions = + // Lookup may not succeed if the project has not been established yet + // In this case we go and compute the options recursively. + match tryGetOptionsForReferencedProject projectFileName with + | None -> getProjectOptionsForProjectSite (enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSiteProvider.GetProjectSite(), serviceProvider, projectId, projectFileName, extraProjectInfo, projectOptionsTable, useUniqueStamp) |> snd + | Some options -> options + yield projectFileName, (outputPath, referencedProjectOptions) |] + + and getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, projectId, fileName, extraProjectInfo, projectOptionsTable, useUniqueStamp) = let referencedProjectFileNames, referencedProjectOptions = if enableInMemoryCrossProjectReferences then - referencedProjectsOf(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, extraProjectInfo, serviceProvider, useUniqueStamp) + referencedProjectsOf(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, extraProjectInfo, projectOptionsTable, useUniqueStamp) |> Array.unzip else [| |], [| |] - - let options = - {ProjectFileName = projectSite.ProjectFileName - SourceFiles = projectSite.CompilationSourceFiles - OtherOptions = projectSite.CompilationOptions - ReferencedProjects = referencedProjectOptions - IsIncompleteTypeCheckEnvironment = projectSite.IsIncompleteTypeCheckEnvironment - UseScriptResolutionRules = SourceFile.MustBeSingleFileProject fileName - LoadTime = projectSite.LoadTime - UnresolvedReferences = None - OriginalLoadReferences = [] - ExtraProjectInfo=extraProjectInfo - Stamp = (if useUniqueStamp then (stamp <- stamp + 1L; Some stamp) else None) } - referencedProjectFileNames, options + let option = + let newOption () = { + ProjectFileName = projectSite.ProjectFileName + SourceFiles = projectSite.CompilationSourceFiles + OtherOptions = projectSite.CompilationOptions + ReferencedProjects = referencedProjectOptions + IsIncompleteTypeCheckEnvironment = projectSite.IsIncompleteTypeCheckEnvironment + UseScriptResolutionRules = SourceFile.MustBeSingleFileProject fileName + LoadTime = projectSite.LoadTime + UnresolvedReferences = None + OriginalLoadReferences = [] + ExtraProjectInfo=extraProjectInfo + Stamp = if useUniqueStamp then (stamp <- stamp + 1L; Some stamp) else None + } + match projectId, projectOptionsTable with + | Some id, Some optionsTable -> + // Get options from cache + match optionsTable.TryGetOptionsForProject(id) with + | Some (_parsingOptions, _site, projectOptions) -> + if projectSite.CompilationSourceFiles <> projectOptions.SourceFiles || + projectSite.CompilationOptions <> projectOptions.OtherOptions || + referencedProjectOptions <> projectOptions.ReferencedProjects then + newOption() + else + projectOptions + | _ -> newOption() + | _ -> newOption() + referencedProjectFileNames, option /// Construct a project site for a single file. May be a single file project (for scripts) or an orphan project site (for everything else). static member ProjectSiteOfSingleFile(filename:string) : IProjectSite = @@ -198,9 +341,9 @@ type internal ProjectSitesAndFiles() = failwith ".fsx or .fsscript should have been treated as implicit project" new ProjectSiteOfSingleFile(filename) :> IProjectSite - static member GetReferencedProjectSites(projectSite:IProjectSite, serviceProvider:System.IServiceProvider) = - referencedProvideProjectSites (projectSite, serviceProvider) - |> Seq.map (fun (_, ps) -> ps.GetProjectSite()) + static member GetReferencedProjectSites(projectSite:IProjectSite, serviceProvider:System.IServiceProvider, extraProjectInfo, projectOptions) = + referencedProvideProjectSites (projectSite, serviceProvider, extraProjectInfo, projectOptions) + |> Seq.map (fun (_, _, _, ps) -> ps.GetProjectSite()) |> Seq.toArray member art.SetSource_DEPRECATED(buffer:IVsTextLines, source:IFSharpSource_DEPRECATED) : unit = @@ -208,11 +351,10 @@ type internal ProjectSitesAndFiles() = (buffer :?> IVsUserData).SetData(&guid, source) |> ErrorHandler.ThrowOnFailure |> ignore /// Create project options for this project site. - static member GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite:IProjectSite,filename,extraProjectInfo,serviceProvider:System.IServiceProvider, useUniqueStamp) = + static member GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite:IProjectSite, serviceProvider, projectId, filename, extraProjectInfo, projectOptionsTable, useUniqueStamp) = match projectSite with | :? IHaveCheckOptions as hco -> hco.OriginalCheckOptions() - | _ -> - getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, filename, extraProjectInfo, serviceProvider, useUniqueStamp) + | _ -> getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, projectId, filename, extraProjectInfo, projectOptionsTable, useUniqueStamp) /// Create project site for these project options static member CreateProjectSiteForScript (filename, referencedProjectFileNames, checkOptions) = @@ -249,10 +391,9 @@ type internal ProjectSitesAndFiles() = | Some site -> site | None -> ProjectSitesAndFiles.ProjectSiteOfSingleFile(filename) - let parsingOptions,_ = checker.GetParsingOptionsFromCommandLineArgs( site.CompilationOptions |> Array.toList) + let parsingOptions,_ = checker.GetParsingOptionsFromCommandLineArgs(site.CompilationOptions |> Array.toList) CompilerEnvironment.GetCompilationDefinesForEditing(filename,parsingOptions) - member art.TryFindOwningProject_DEPRECATED(rdt:IVsRunningDocumentTable, filename) = if SourceFile.MustBeSingleFileProject(filename) then None else @@ -271,4 +412,4 @@ type internal ProjectSitesAndFiles() = member art.FindOwningProject_DEPRECATED(rdt:IVsRunningDocumentTable, filename) = match art.TryFindOwningProject_DEPRECATED(rdt, filename) with | Some site -> site - | None -> ProjectSitesAndFiles.ProjectSiteOfSingleFile(filename) + | None -> ProjectSitesAndFiles.ProjectSiteOfSingleFile(filename) \ No newline at end of file diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/AssemblyInfo.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/AssemblyInfo.fs index 5980c7a3b49..3edcdc6b15b 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/AssemblyInfo.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/AssemblyInfo.fs @@ -5,10 +5,6 @@ open System.Reflection open System.Runtime.CompilerServices open Microsoft.VisualStudio.Shell -[] -[] -[] - [] do() diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj b/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj index d475e39d0df..b7b90d75070 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/ProjectSystem.fsproj @@ -43,6 +43,7 @@ $(IntermediateOutputPath)\ProjectResources.rc.res + @@ -63,6 +64,11 @@ + + + + + $(FSharpSourcesRoot)\..\loc\lcl\{Lang}\$(AssemblyName).dll.lcl diff --git a/vsintegration/src/FSharp.VS.FSI/AssemblyInfo.fs b/vsintegration/src/FSharp.VS.FSI/AssemblyInfo.fs index 077cf8ecf08..3274ae4f265 100644 --- a/vsintegration/src/FSharp.VS.FSI/AssemblyInfo.fs +++ b/vsintegration/src/FSharp.VS.FSI/AssemblyInfo.fs @@ -8,12 +8,6 @@ open System.Runtime.InteropServices open Microsoft.VisualStudio.Shell [] - -[] -[] -[] -[] - [] do() diff --git a/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj b/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj index 674dd169377..71b3f802763 100644 --- a/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj +++ b/vsintegration/src/FSharp.VS.FSI/FSHarp.VS.FSI.fsproj @@ -39,6 +39,14 @@ + + + + + + + + $(FSharpSourcesRoot)\..\loc\lcl\{Lang}\$(AssemblyName).dll.lcl diff --git a/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs b/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs index 7a2976e0936..21b290c3819 100644 --- a/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs +++ b/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs @@ -17,6 +17,7 @@ open Microsoft.VisualStudio.OLE.Interop open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.SourceCodeServices open Microsoft.VisualStudio.FSharp.LanguageService +open Microsoft.VisualStudio.FSharp.LanguageService.SiteProvider open Microsoft.VisualStudio.FSharp.Editor type internal FSharpLanguageServiceTestable() as this = @@ -127,7 +128,7 @@ type internal FSharpLanguageServiceTestable() as this = /// Respond to project being cleaned/rebuilt (any live type providers in the project should be refreshed) member this.OnProjectCleaned(projectSite:IProjectSite) = let enableInMemoryCrossProjectReferences = true - let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, (fun _ -> None), projectSite, "" ,None, serviceProvider.Value, false) + let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, (fun _ -> None), projectSite, serviceProvider.Value, None(*projectId*), "" ,None, None, false) this.FSharpChecker.NotifyProjectCleaned(checkOptions) |> Async.RunSynchronously member this.OnActiveViewChanged(textView) = @@ -170,7 +171,7 @@ type internal FSharpLanguageServiceTestable() as this = member this.DependencyFileCreated projectSite = let enableInMemoryCrossProjectReferences = true // Invalidate the configuration if we notice any add for any DependencyFiles - let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, (fun _ -> None), projectSite, "", None, this.ServiceProvider, false) + let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, (fun _ -> None), projectSite, serviceProvider.Value, None(*projectId*),"" ,None, None, false) this.FSharpChecker.InvalidateConfiguration(checkOptions) member this.DependencyFileChanged (filename) = diff --git a/vsintegration/tests/Salsa/InternalsVisibleTo.fs b/vsintegration/tests/Salsa/InternalsVisibleTo.fs deleted file mode 100644 index 8543680d835..00000000000 --- a/vsintegration/tests/Salsa/InternalsVisibleTo.fs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.FSharp -open System.Reflection -[] - - -do() - diff --git a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj index 7ddbf1b0dbc..057165e8b47 100644 --- a/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj +++ b/vsintegration/tests/Salsa/VisualFSharp.Salsa.fsproj @@ -17,6 +17,11 @@ $(NoWarn);45;47;52;58;75 v4.6 + + + + + CompilerLocationUtils.fs @@ -24,7 +29,6 @@ UnitTests.TestLib.Utils.fs - @@ -150,6 +154,10 @@ $(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Shell.$(RoslynVSBinariesVersion).$(RoslynVSPackagesVersion)\lib\Microsoft.VisualStudio.Shell.$(RoslynVSBinariesVersion).dll True + + $(FSharpSourcesRoot)\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.$(RoslynVersion)\lib\netstandard1.3\Microsoft.CodeAnalysis.Workspaces.dll + True + True $(NUnitLibDir)\nunit.framework.dll diff --git a/vsintegration/tests/Salsa/salsa.fs b/vsintegration/tests/Salsa/salsa.fs index 305f77d94d6..95e51ca8437 100644 --- a/vsintegration/tests/Salsa/salsa.fs +++ b/vsintegration/tests/Salsa/salsa.fs @@ -25,7 +25,7 @@ open Microsoft.VisualStudio.FSharp.LanguageService open Microsoft.VisualStudio.TextManager.Interop open UnitTests.TestLib.Utils.FilesystemHelpers open Microsoft.Build.Framework -open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.SourceCodeServices open Microsoft.Build.Evaluation diff --git a/vsintegration/tests/unittests/Tests.LanguageService.Completion.fs b/vsintegration/tests/unittests/Tests.LanguageService.Completion.fs index aca191434a8..88d22ecb293 100644 --- a/vsintegration/tests/unittests/Tests.LanguageService.Completion.fs +++ b/vsintegration/tests/unittests/Tests.LanguageService.Completion.fs @@ -7774,6 +7774,15 @@ let rec f l = let bar = 1""", marker = "(*Marker*)") + [] + member public this.``ExpressionDotting.Regression.Bug3709``() = + this.VerifyCtrlSpaceListContainAllAtStartOfMarker( + fileContents = """ + let foo = "" + let foo = foo.E(*marker*)n "a" """, + marker = "(*marker*)", + list = ["EndsWith"]) + // Context project system [] type UsingProjectSystem() = diff --git a/vsintegration/tests/unittests/Tests.LanguageService.GotoDefinition.fs b/vsintegration/tests/unittests/Tests.LanguageService.GotoDefinition.fs index 8794cc6e688..f72aa5c93d8 100644 --- a/vsintegration/tests/unittests/Tests.LanguageService.GotoDefinition.fs +++ b/vsintegration/tests/unittests/Tests.LanguageService.GotoDefinition.fs @@ -1346,7 +1346,7 @@ type UsingMSBuild() = member this.GetCompleteIdTest tolerate (s : string)(exp : string option) : unit = let n = s.IndexOf '$' let s = s.Remove (n, 1) - match (Microsoft.VisualStudio.FSharp.LanguageService.QuickParse.GetCompleteIdentifierIsland tolerate s n, exp) with + match (Microsoft.FSharp.Compiler.QuickParse.GetCompleteIdentifierIsland tolerate s n, exp) with | (Some (s1, _, _), Some s2) -> printfn "%s" "Received result, as expected." Assert.AreEqual (s1, s2) diff --git a/vsintegration/tests/unittests/Tests.LanguageService.QuickParse.fs b/vsintegration/tests/unittests/Tests.LanguageService.QuickParse.fs index 7c5be4fe7c4..7d08f8e4967 100644 --- a/vsintegration/tests/unittests/Tests.LanguageService.QuickParse.fs +++ b/vsintegration/tests/unittests/Tests.LanguageService.QuickParse.fs @@ -3,9 +3,8 @@ namespace Tests.LanguageService open System -open System.IO open NUnit.Framework -open Microsoft.VisualStudio.FSharp.LanguageService +open Microsoft.FSharp.Compiler [] [] @@ -22,37 +21,37 @@ type QuickParse() = [] member public qp.CheckGetPartialLongName() = - let CheckAt(line,index,expected) = - let actual = QuickParse.GetPartialLongNameEx(line,index) - if actual <> expected then + let CheckAt(line, index, expected) = + let actual = QuickParse.GetPartialLongNameEx(line, index) + if (actual.QualifyingIdents, actual.PartialIdent, actual.LastDotPos) <> expected then failwithf "Expected %A but got %A" expected actual let Check(line,expected) = CheckAt(line, line.Length-1, expected) do Microsoft.FSharp.Compiler.AbstractIL.Diagnostics.setDiagnosticsChannel(Some(Console.Out)); - Check("let y = List.",(["List"], "")) - Check("let y = List.conc",(["List"], "conc")) - Check("let y = S", ([], "S")) - Check("S", ([], "S")) - Check("let y=", ([], "")) - Check("Console.Wr", (["Console"], "Wr")) - Check(" .", ([""], "")) - Check(".", ([""], "")) - Check("System.Console.Wr", (["System";"Console"],"Wr")) - Check("let y=f'", ([], "f'")) - Check("let y=SomeModule.f'", (["SomeModule"], "f'")) - Check("let y=Some.OtherModule.f'", (["Some";"OtherModule"], "f'")) - Check("let y=f'g", ([], "f'g")) - Check("let y=SomeModule.f'g", (["SomeModule"], "f'g")) - Check("let y=Some.OtherModule.f'g", (["Some";"OtherModule"], "f'g")) - Check("let y=FSharp.Data.File.``msft-prices.csv``", ([], "")) - Check("let y=FSharp.Data.File.``msft-prices.csv", (["FSharp";"Data";"File"], "msft-prices.csv")) - Check("let y=SomeModule. f", (["SomeModule"], "f")) - Check("let y=SomeModule .f", (["SomeModule"], "f")) - Check("let y=SomeModule . f", (["SomeModule"], "f")) - Check("let y=SomeModule .", (["SomeModule"], "")) - Check("let y=SomeModule . ", (["SomeModule"], "")) + Check("let y = List.",(["List"], "", Some 12)) + Check("let y = List.conc",(["List"], "conc", Some 12)) + Check("let y = S", ([], "S", None)) + Check("S", ([], "S", None)) + Check("let y=", ([], "", None)) + Check("Console.Wr", (["Console"], "Wr", Some 7)) + Check(" .", ([""], "", Some 1)) + Check(".", ([""], "", Some 0)) + Check("System.Console.Wr", (["System";"Console"],"Wr", Some 14)) + Check("let y=f'", ([], "f'", None)) + Check("let y=SomeModule.f'", (["SomeModule"], "f'", Some 16)) + Check("let y=Some.OtherModule.f'", (["Some";"OtherModule"], "f'", Some 22)) + Check("let y=f'g", ([], "f'g", None)) + Check("let y=SomeModule.f'g", (["SomeModule"], "f'g", Some 16)) + Check("let y=Some.OtherModule.f'g", (["Some";"OtherModule"], "f'g", Some 22)) + Check("let y=FSharp.Data.File.``msft-prices.csv``", ([], "", None)) + Check("let y=FSharp.Data.File.``msft-prices.csv", (["FSharp";"Data";"File"], "msft-prices.csv", Some 22)) + Check("let y=SomeModule. f", (["SomeModule"], "f", Some 16)) + Check("let y=SomeModule .f", (["SomeModule"], "f", Some 18)) + Check("let y=SomeModule . f", (["SomeModule"], "f", Some 18)) + Check("let y=SomeModule .", (["SomeModule"], "", Some 18)) + Check("let y=SomeModule . ", (["SomeModule"], "", Some 18)) []